line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
##################################################################### |
2
|
|
|
|
|
|
|
##################################################################### |
3
|
|
|
|
|
|
|
## |
4
|
|
|
|
|
|
|
## |
5
|
|
|
|
|
|
|
## Here starts the actual thing. |
6
|
|
|
|
|
|
|
## |
7
|
|
|
|
|
|
|
## This is way too messy and uncommented. Still. :( |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# DJB August 24 2006 |
10
|
|
|
|
|
|
|
# begin cleaning up the code so that it all runs under use strict |
11
|
|
|
|
|
|
|
# DJB August 31 2006 |
12
|
|
|
|
|
|
|
# moved to use objects for the rule table (ie defvar) in the |
13
|
|
|
|
|
|
|
# hope it's more declarative (since the addition of "::" to |
14
|
|
|
|
|
|
|
# a statement makes it so much-more meaningful :-) |
15
|
|
|
|
|
|
|
# |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# How to convert from the old deftbl format to the new, object-based, |
18
|
|
|
|
|
|
|
# system: |
19
|
|
|
|
|
|
|
# |
20
|
|
|
|
|
|
|
# What used to be, in $PDL::PP::deftbl |
21
|
|
|
|
|
|
|
# [["Name1"], ["Name2"], $ref_to_sub]] |
22
|
|
|
|
|
|
|
# is now |
23
|
|
|
|
|
|
|
# PDL::PP::Rule->new("Name1", "Name2", $ref_to_sub) |
24
|
|
|
|
|
|
|
# where Name1 represents the target of the rule, Name2 the condition, |
25
|
|
|
|
|
|
|
# and the subroutine reference is the routine called when the rule is |
26
|
|
|
|
|
|
|
# applied. |
27
|
|
|
|
|
|
|
# |
28
|
|
|
|
|
|
|
# If their is no condition, the argument can be left out of the call |
29
|
|
|
|
|
|
|
# (unless there is a doc string), so |
30
|
|
|
|
|
|
|
# [["Name1"], [], $ref_to_sub]] |
31
|
|
|
|
|
|
|
# becomes |
32
|
|
|
|
|
|
|
# PDL::PP::Rule->new("Name1", $ref_to_sub) |
33
|
|
|
|
|
|
|
# |
34
|
|
|
|
|
|
|
# The target and conditions can also be an array reference, so |
35
|
|
|
|
|
|
|
# [["Name1"], ["Name2","Name3"], $ref_to_sub]] |
36
|
|
|
|
|
|
|
# [["Name1","Name2"], ["Name3"], $ref_to_sub]] |
37
|
|
|
|
|
|
|
# [["Name1","Name2"], ["Name3","Name4"], $ref_to_sub]] |
38
|
|
|
|
|
|
|
# become, respectively |
39
|
|
|
|
|
|
|
# PDL::PP::Rule->new("Name1", ["Name2","Name3"], $ref_to_sub) |
40
|
|
|
|
|
|
|
# PDL::PP::Rule->new(["Name1","Name2"], "Name3", $ref_to_sub) |
41
|
|
|
|
|
|
|
# PDL::PP::Rule->new(["Name1","Name2"], ["Name3","Name4], $ref_to_sub) |
42
|
|
|
|
|
|
|
# |
43
|
|
|
|
|
|
|
# If the old rule had a document string, this is placed between |
44
|
|
|
|
|
|
|
# the condition and the subroutine reference. To make processing |
45
|
|
|
|
|
|
|
# simpler, if a doc string exists then the condition must also |
46
|
|
|
|
|
|
|
# be supplied, even if it is just [] (ie no condition). |
47
|
|
|
|
|
|
|
# |
48
|
|
|
|
|
|
|
# There are specialized rules for common situations. The rules for the |
49
|
|
|
|
|
|
|
# target, condition, and doc arguments hold from the base class (ie |
50
|
|
|
|
|
|
|
# whether scalar or array values are used, ...) |
51
|
|
|
|
|
|
|
# |
52
|
|
|
|
|
|
|
# Return a constant: |
53
|
|
|
|
|
|
|
# |
54
|
|
|
|
|
|
|
# PDL::PP::Rule::Returns->new($targets [,$conditions [,$doc]], $value) |
55
|
|
|
|
|
|
|
# is used to return a constant. So |
56
|
|
|
|
|
|
|
# [["Name1"], [], sub { "foo" }] |
57
|
|
|
|
|
|
|
# becomes |
58
|
|
|
|
|
|
|
# PDL::PP::Rule::Returns->new("Name1", "foo") |
59
|
|
|
|
|
|
|
# |
60
|
|
|
|
|
|
|
# This class is specialized since there are some common return values: |
61
|
|
|
|
|
|
|
# PDL::PP::Rule::Returns::Zero->new($targets [,$conditions [,$doc]]) |
62
|
|
|
|
|
|
|
# PDL::PP::Rule::Returns::One->new($targets [,$conditions [,$doc]]) |
63
|
|
|
|
|
|
|
# PDL::PP::Rule::Returns::EmptyString->new($targets [,$conditions [,$doc]]) |
64
|
|
|
|
|
|
|
# PDL::PP::Rule::Returns::NULL->new($targets [,$conditions [,$doc]]) |
65
|
|
|
|
|
|
|
# which return 0, 1, "", and "NULL" respectively |
66
|
|
|
|
|
|
|
# |
67
|
|
|
|
|
|
|
# The InsertName class exists to allow you to return something like |
68
|
|
|
|
|
|
|
# "foobar" |
69
|
|
|
|
|
|
|
# The old rules |
70
|
|
|
|
|
|
|
# [["Foo"], ["Name"], sub { return "_pdl_$_[0]_bar"; }] |
71
|
|
|
|
|
|
|
# [["Foo"], ["Name","Arg2"], sub { return "_pdl_$_[0]_bar"; }] |
72
|
|
|
|
|
|
|
# become |
73
|
|
|
|
|
|
|
# PDL::PP::Rule::InsertName->new("Foo", '_pdl_${name}_bar') |
74
|
|
|
|
|
|
|
# PDL::PP::Rule::InsertName->new("Foo", "Arg2", '_pdl_${name}_bar') |
75
|
|
|
|
|
|
|
# Note that the Name argument is automatically used as a condition, so |
76
|
|
|
|
|
|
|
# it does not need to be supplied, and the return value should be |
77
|
|
|
|
|
|
|
# given as a single-quoted string and use the $name variable |
78
|
|
|
|
|
|
|
# |
79
|
|
|
|
|
|
|
# The Substitute rule replaces dollar-signed macros ($P(), $ISBAD(), etc) |
80
|
|
|
|
|
|
|
# with the low-level C code to perform the macro. |
81
|
|
|
|
|
|
|
# |
82
|
|
|
|
|
|
|
# The Substitute class replaces the dosubst rule. The old rule |
83
|
|
|
|
|
|
|
# [["NewXSCoerceMustSubs"], ["NewXSCoerceMustSub1","NewXSSymTab","Name"], |
84
|
|
|
|
|
|
|
# \&dosubst] |
85
|
|
|
|
|
|
|
# becomes |
86
|
|
|
|
|
|
|
# PDL::PP::Rule::Substitute("NewXSCoerceMustSubs", "NewXSCoerceMustSub1") |
87
|
|
|
|
|
|
|
# |
88
|
|
|
|
|
|
|
# PDL::PP::Rule::Substitute->new($target,$condition) |
89
|
|
|
|
|
|
|
# $target and $condition must be scalars. |
90
|
|
|
|
|
|
|
# |
91
|
|
|
|
|
|
|
# Implicit conditions are NewXSSymTab and Name |
92
|
|
|
|
|
|
|
# |
93
|
|
|
|
|
|
|
# The Substitute:Usual class replaces the dousualsubsts rule. The old rule |
94
|
|
|
|
|
|
|
# [["CacheBadFlagInit"], ["CacheBadFlagInitNS","NewXSSymTab","Name"], |
95
|
|
|
|
|
|
|
# \&dousualsubsts], |
96
|
|
|
|
|
|
|
# becomes |
97
|
|
|
|
|
|
|
# PDL::PP::Rule::Substitute::Usual->new("CacheBadFlagInit", "CacheBadFlagInitNS") |
98
|
|
|
|
|
|
|
# |
99
|
|
|
|
|
|
|
# PDL::PP::Rule::Substitute::Usual->new($target, $condition) |
100
|
|
|
|
|
|
|
# $target and $condition must be scalars. |
101
|
|
|
|
|
|
|
# |
102
|
|
|
|
|
|
|
# Implicit conditions are NewXSSymTab and Name |
103
|
|
|
|
|
|
|
# |
104
|
|
|
|
|
|
|
# The MakeComp rule replaces the subst_makecomp routine. The old rule |
105
|
|
|
|
|
|
|
# [["MakeCompiledRepr"], ["MakeComp","CompNames","CompObjs"], |
106
|
|
|
|
|
|
|
# sub {subst_makecomp("COMP",@_)}] |
107
|
|
|
|
|
|
|
# becomes |
108
|
|
|
|
|
|
|
# PDL::PP::Rule::MakeComp->new("MakeCompiledRepr", ["MakeComp","CompNames","CompObjs"], |
109
|
|
|
|
|
|
|
# "COMP") |
110
|
|
|
|
|
|
|
# PDL::PP::Rule::MakeComp->new($target,$conditions,$symbol) |
111
|
|
|
|
|
|
|
# $target and $symbol must be scalars. |
112
|
|
|
|
|
|
|
# |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# Notes: |
115
|
|
|
|
|
|
|
# InsertName could become a subclass of Insert since there are |
116
|
|
|
|
|
|
|
# a few rules that just insert conditions into a text string. |
117
|
|
|
|
|
|
|
# |
118
|
|
|
|
|
|
|
# Substitute, Substitute::Usual, MakeComp classes feel a bit |
119
|
|
|
|
|
|
|
# ugly. See next point. Also the get_std_childparent method is |
120
|
|
|
|
|
|
|
# a bit of a hack. |
121
|
|
|
|
|
|
|
# |
122
|
|
|
|
|
|
|
# DJB thinks that the code fragments themselves could be objects |
123
|
|
|
|
|
|
|
# since they should 'know' what needs doing to them (eg the |
124
|
|
|
|
|
|
|
# substitutions). Not sure whether it would really clarify things. |
125
|
|
|
|
|
|
|
# |
126
|
|
|
|
|
|
|
# To do: |
127
|
|
|
|
|
|
|
# wrap_vfn could propbably be moved into a class. |
128
|
|
|
|
|
|
|
# |
129
|
|
|
|
|
|
|
# move the PDL::PP::Rule and subclasses into their own file? |
130
|
|
|
|
|
|
|
# |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
package PDL::PP::Rule; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
use strict; |
135
|
|
|
|
|
|
|
require PDL::Core::Dev; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
use Carp; |
138
|
|
|
|
|
|
|
our @CARP_NOT; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
my $INVALID_OTHERPARS_RE = qr/^(?:magicno|flags|vtable|freeproc|bvalflag|has_badvalue|badvalue|pdls|__datatype)\z/; |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
use overload ("\"\"" => \&PDL::PP::Rule::stringify); |
143
|
|
|
|
|
|
|
sub stringify { |
144
|
|
|
|
|
|
|
my $self = shift; |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
my $str = ref $self; |
147
|
|
|
|
|
|
|
if ("PDL::PP::Rule" eq $str) { |
148
|
|
|
|
|
|
|
$str = "Rule"; |
149
|
|
|
|
|
|
|
} else { |
150
|
|
|
|
|
|
|
$str =~ s/PDL::PP::Rule:://; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
$str = "($str) "; |
153
|
|
|
|
|
|
|
$str .= exists $self->{doc} ? |
154
|
|
|
|
|
|
|
$self->{doc} : join(",", @{$self->{targets}}); |
155
|
|
|
|
|
|
|
return $str; |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# Takes two args: the calling object and the message, but we only care |
159
|
|
|
|
|
|
|
# about the message: |
160
|
|
|
|
|
|
|
sub report ($$) { print $_[1] if $::PP_VERBOSE; } |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# Very limited error checking. |
163
|
|
|
|
|
|
|
# Allow scalars for targets and conditions to be optional |
164
|
|
|
|
|
|
|
# |
165
|
|
|
|
|
|
|
# At present you have to have a conditions argument if you supply |
166
|
|
|
|
|
|
|
# a doc string |
167
|
|
|
|
|
|
|
# |
168
|
|
|
|
|
|
|
# It seems strange to make the subroutine reference an optional |
169
|
|
|
|
|
|
|
# argument but this is being used to transition to a slightly-different |
170
|
|
|
|
|
|
|
# object design |
171
|
|
|
|
|
|
|
# |
172
|
|
|
|
|
|
|
sub new { |
173
|
|
|
|
|
|
|
my $class = shift; |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
my $self = {}; |
176
|
|
|
|
|
|
|
bless $self, $class; |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
my $usage = "Usage: PDL::PP::Rule->new(\$targets[,\$conditions[,\$doc],] [,\$ref])\n"; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# handle arguments |
181
|
|
|
|
|
|
|
my $nargs = $#_; |
182
|
|
|
|
|
|
|
die $usage if $nargs < 0 or $nargs > 3; |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
my $targets = shift; |
185
|
|
|
|
|
|
|
$targets = [$targets] unless ref $targets eq "ARRAY"; |
186
|
|
|
|
|
|
|
$self->{targets} = $targets; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
if ($#_ != -1) { |
189
|
|
|
|
|
|
|
if (ref $_[-1] eq "CODE") { |
190
|
|
|
|
|
|
|
$self->{ref} = pop; |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
my ($conditions,$doc) = @_; |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
if (defined $conditions) { |
196
|
|
|
|
|
|
|
$conditions = [$conditions] unless ref $conditions eq "ARRAY"; |
197
|
|
|
|
|
|
|
} else { |
198
|
|
|
|
|
|
|
$conditions = []; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
$self->{conditions} = $conditions; |
201
|
|
|
|
|
|
|
$self->{doc} = $doc if defined $doc; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
return $self; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# $rule->check_if_targets_exist($pars); |
208
|
|
|
|
|
|
|
# |
209
|
|
|
|
|
|
|
# Returns 1 if any of the targets exist in $pars, 0 otherwise. |
210
|
|
|
|
|
|
|
# A return value of 1 means that the rule should not be applied. |
211
|
|
|
|
|
|
|
# |
212
|
|
|
|
|
|
|
# Not 100% happy with use of report here. Needs re-thinking. |
213
|
|
|
|
|
|
|
# |
214
|
|
|
|
|
|
|
sub check_if_targets_exist { |
215
|
|
|
|
|
|
|
my $self = shift; |
216
|
|
|
|
|
|
|
my $pars = shift; |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
my $targets = $self->{targets}; |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
foreach my $target (@$targets) { |
221
|
|
|
|
|
|
|
if (exists $pars->{$target}) { |
222
|
|
|
|
|
|
|
$self->report("--skipping since TARGET $target exists\n"); |
223
|
|
|
|
|
|
|
return 1; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
return 0; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# $rule->check_if_conditions_exist($pars); |
230
|
|
|
|
|
|
|
# |
231
|
|
|
|
|
|
|
# Returns 1 if all of the required conditions exist in $pars, 0 otherwise. |
232
|
|
|
|
|
|
|
# A return value of 0 means that the rule should not be applied. |
233
|
|
|
|
|
|
|
# |
234
|
|
|
|
|
|
|
# Not 100% happy with use of report here. Needs re-thinking. |
235
|
|
|
|
|
|
|
# |
236
|
|
|
|
|
|
|
sub check_if_conditions_exist { |
237
|
|
|
|
|
|
|
my $self = shift; |
238
|
|
|
|
|
|
|
my $pars = shift; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
my $conditions = $self->{conditions}; |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
foreach my $condition (@$conditions) { |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
# skip if not a required condition |
245
|
|
|
|
|
|
|
next if substr($condition,0,1) eq "_"; |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
unless (exists $pars->{$condition}) { |
248
|
|
|
|
|
|
|
$self->report("--skipping since CONDITION $condition does not exist\n"); |
249
|
|
|
|
|
|
|
return 0; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
return 1; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# $rule->is_valid($pars); |
257
|
|
|
|
|
|
|
# |
258
|
|
|
|
|
|
|
# Returns 1 if the rule should be applied (ie no targets already |
259
|
|
|
|
|
|
|
# exist in $pars and all the required conditions exist in $pars), |
260
|
|
|
|
|
|
|
# otherwise 0. |
261
|
|
|
|
|
|
|
# |
262
|
|
|
|
|
|
|
sub is_valid { |
263
|
|
|
|
|
|
|
my $self = shift; |
264
|
|
|
|
|
|
|
my $pars = shift; |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
return 0 if $self->check_if_targets_exist($pars); |
267
|
|
|
|
|
|
|
return 0 unless $self->check_if_conditions_exist($pars); |
268
|
|
|
|
|
|
|
return 1; |
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
# my @args = $self->extract_args($pars); |
272
|
|
|
|
|
|
|
# |
273
|
|
|
|
|
|
|
# If this method is called we assume that |
274
|
|
|
|
|
|
|
# $self->check_if_conditions_exist($pars) |
275
|
|
|
|
|
|
|
# returns 1. |
276
|
|
|
|
|
|
|
# |
277
|
|
|
|
|
|
|
sub extract_args { |
278
|
|
|
|
|
|
|
my $self = shift; |
279
|
|
|
|
|
|
|
my $pars = shift; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
my $conditions = $self->{conditions}; |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
my @args; |
284
|
|
|
|
|
|
|
foreach (@$conditions) { |
285
|
|
|
|
|
|
|
# make a copy of each condition so that any changes to it are not |
286
|
|
|
|
|
|
|
# also made to the original array! |
287
|
|
|
|
|
|
|
my $condition = $_; |
288
|
|
|
|
|
|
|
# Remove any possible underscores (which indicate optional conditions): |
289
|
|
|
|
|
|
|
$condition =~ s/^_//; |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
# Note: This will *not* create $pars->{$condition} if it did not already |
292
|
|
|
|
|
|
|
# exist: |
293
|
|
|
|
|
|
|
push @args, $pars->{$condition}; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
return @args; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# Apply the rule using the supplied $pars hash reference. |
300
|
|
|
|
|
|
|
# |
301
|
|
|
|
|
|
|
sub apply { |
302
|
|
|
|
|
|
|
my $self = shift; |
303
|
|
|
|
|
|
|
my $pars = shift; |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
carp "Unable to apply rule $self as there is no subroutine reference!" |
306
|
|
|
|
|
|
|
unless exists $self->{ref}; |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
my $targets = $self->{targets}; |
309
|
|
|
|
|
|
|
my $conditions = $self->{conditions}; |
310
|
|
|
|
|
|
|
my $ref = $self->{ref}; |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
$self->report("Applying: $self\n"); |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# Is the rule valid? |
315
|
|
|
|
|
|
|
# |
316
|
|
|
|
|
|
|
return unless $self->is_valid($pars); |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
# Create the argument array for the routine. |
319
|
|
|
|
|
|
|
# |
320
|
|
|
|
|
|
|
my @args = $self->extract_args($pars); |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# Run this rule's subroutine: |
323
|
|
|
|
|
|
|
my @retval = $self->{ref}(@args); |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
# Check for any inconsistencies: |
326
|
|
|
|
|
|
|
confess "Internal error: rule '$self' returned " . (1+$#retval) |
327
|
|
|
|
|
|
|
. " items and expected " . (1+$#$targets) |
328
|
|
|
|
|
|
|
unless $#retval == $#$targets; |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
$self->report("--setting:"); |
331
|
|
|
|
|
|
|
foreach my $target (@$targets) { |
332
|
|
|
|
|
|
|
$self->report(" $target"); |
333
|
|
|
|
|
|
|
confess "Cannot have multiple meanings for target $target!" |
334
|
|
|
|
|
|
|
if exists $pars->{$target}; |
335
|
|
|
|
|
|
|
my $result = shift @retval; |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
# The following test suggests that things could/should be |
338
|
|
|
|
|
|
|
# improved in the code generation. |
339
|
|
|
|
|
|
|
# |
340
|
|
|
|
|
|
|
if (defined $result and $result eq 'DO NOT SET!!') { |
341
|
|
|
|
|
|
|
$self->report (" is 'DO NOT SET!!'"); |
342
|
|
|
|
|
|
|
} else { |
343
|
|
|
|
|
|
|
$pars->{$target} = $result; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
$self->report("\n"); |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
package PDL::PP::Rule::Croak; |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
# Croaks if all of the input variables are defined. Use this to identify |
353
|
|
|
|
|
|
|
# incompatible arguments. |
354
|
|
|
|
|
|
|
our @ISA = qw(PDL::PP::Rule); |
355
|
|
|
|
|
|
|
use Carp; |
356
|
|
|
|
|
|
|
our @CARP_NOT; |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
sub new { |
360
|
|
|
|
|
|
|
croak('Usage: PDL::PP::Ruel::Croak->new(["incompatible", "arguments"], "Croaking message")') |
361
|
|
|
|
|
|
|
unless @_ == 3; |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
my $class = shift; |
364
|
|
|
|
|
|
|
my $self = $class->SUPER::new([], @_); |
365
|
|
|
|
|
|
|
return bless $self, $class; |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
sub apply { |
369
|
|
|
|
|
|
|
my ($self, $pars) = @_; |
370
|
|
|
|
|
|
|
croak($self->{doc}) if $self->is_valid($pars); |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
package PDL::PP::Rule::Returns; |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
use strict; |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
use Carp; |
378
|
|
|
|
|
|
|
our @CARP_NOT; |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
##use PDL::PP::Rule; |
381
|
|
|
|
|
|
|
our @ISA = qw (PDL::PP::Rule); |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
# This class does not treat return values of "DO NOT SET!!" |
384
|
|
|
|
|
|
|
# as special. |
385
|
|
|
|
|
|
|
# |
386
|
|
|
|
|
|
|
sub new { |
387
|
|
|
|
|
|
|
my $class = shift; |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
my $value = pop; |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
my @args = @_; |
392
|
|
|
|
|
|
|
my $self = $class->SUPER::new(@args); |
393
|
|
|
|
|
|
|
bless $self, $class; |
394
|
|
|
|
|
|
|
$self->{"returns.value"} = $value; |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
my $targets = $self->{targets}; |
397
|
|
|
|
|
|
|
croak "There can only be 1 target for a $self, not " . (1+$#$targets) . "!" |
398
|
|
|
|
|
|
|
unless $#$targets == 0; |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
return $self; |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
sub apply { |
404
|
|
|
|
|
|
|
my $self = shift; |
405
|
|
|
|
|
|
|
my $pars = shift; |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
carp "Unable to apply rule $self as there is no return value!" |
408
|
|
|
|
|
|
|
unless exists $self->{"returns.value"}; |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
my $target = $self->{targets}->[0]; |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
$self->report("Applying: $self\n"); |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
# Is the rule valid? |
415
|
|
|
|
|
|
|
# |
416
|
|
|
|
|
|
|
return unless $self->is_valid($pars); |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
# Set the value |
419
|
|
|
|
|
|
|
# |
420
|
|
|
|
|
|
|
$self->report ("--setting: $target\n"); |
421
|
|
|
|
|
|
|
$pars->{$target} = $self->{"returns.value"}; |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
package PDL::PP::Rule::Returns::Zero; |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
use strict; |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
##use PDL::PP::Rule::Returns; |
429
|
|
|
|
|
|
|
our @ISA = qw (PDL::PP::Rule::Returns); |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
sub new { |
432
|
|
|
|
|
|
|
my $class = shift; |
433
|
|
|
|
|
|
|
my @args = @_; |
434
|
|
|
|
|
|
|
my $self = $class->SUPER::new(@args,0); |
435
|
|
|
|
|
|
|
bless $self, $class; |
436
|
|
|
|
|
|
|
return $self; |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
package PDL::PP::Rule::Returns::One; |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
use strict; |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
##use PDL::PP::Rule::Returns; |
444
|
|
|
|
|
|
|
our @ISA = qw (PDL::PP::Rule::Returns); |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub new { |
447
|
|
|
|
|
|
|
my $class = shift; |
448
|
|
|
|
|
|
|
my @args = @_; |
449
|
|
|
|
|
|
|
my $self = $class->SUPER::new(@args,1); |
450
|
|
|
|
|
|
|
bless $self, $class; |
451
|
|
|
|
|
|
|
return $self; |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
package PDL::PP::Rule::Returns::EmptyString; |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
use strict; |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
##use PDL::PP::Rule::Returns; |
459
|
|
|
|
|
|
|
our @ISA = qw (PDL::PP::Rule::Returns); |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
sub new { |
462
|
|
|
|
|
|
|
my $class = shift; |
463
|
|
|
|
|
|
|
my @args = @_; |
464
|
|
|
|
|
|
|
my $self = $class->SUPER::new(@args,""); |
465
|
|
|
|
|
|
|
bless $self, $class; |
466
|
|
|
|
|
|
|
return $self; |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
package PDL::PP::Rule::Returns::NULL; |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
use strict; |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
##use PDL::PP::Rule::Returns; |
474
|
|
|
|
|
|
|
our @ISA = qw (PDL::PP::Rule::Returns); |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
sub new { |
477
|
|
|
|
|
|
|
my $class = shift; |
478
|
|
|
|
|
|
|
my @args = @_; |
479
|
|
|
|
|
|
|
my $self = $class->SUPER::new(@args,"NULL"); |
480
|
|
|
|
|
|
|
bless $self, $class; |
481
|
|
|
|
|
|
|
return $self; |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
package PDL::PP::Rule::InsertName; |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
use strict; |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
use Carp; |
489
|
|
|
|
|
|
|
our @CARP_NOT; |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
##use PDL::PP::Rule; |
492
|
|
|
|
|
|
|
our @ISA = qw (PDL::PP::Rule); |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
# This class does not treat return values of "DO NOT SET!!" |
495
|
|
|
|
|
|
|
# as special. |
496
|
|
|
|
|
|
|
# |
497
|
|
|
|
|
|
|
sub new { |
498
|
|
|
|
|
|
|
my $class = shift; |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
my $value = pop; |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
my @args = @_; |
503
|
|
|
|
|
|
|
my $self = $class->SUPER::new(@args); |
504
|
|
|
|
|
|
|
bless $self, $class; |
505
|
|
|
|
|
|
|
$self->{"insertname.value"} = $value; |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
# Generate a defaul doc string |
508
|
|
|
|
|
|
|
unless (exists $self->{doc}) { |
509
|
|
|
|
|
|
|
$self->{doc} = 'Sets ' . $self->{targets}->[0] |
510
|
|
|
|
|
|
|
. ' to "' . $value . '"'; |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
my $targets = $self->{targets}; |
514
|
|
|
|
|
|
|
croak "There can only be 1 target for a $self, not " . (1+$#$targets) . "!" |
515
|
|
|
|
|
|
|
unless $#$targets == 0; |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
# we add "Name" as the first condition |
518
|
|
|
|
|
|
|
# |
519
|
|
|
|
|
|
|
my $conditions = $self->{conditions}; |
520
|
|
|
|
|
|
|
unshift @$conditions, "Name"; |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
return $self; |
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
sub apply { |
526
|
|
|
|
|
|
|
my $self = shift; |
527
|
|
|
|
|
|
|
my $pars = shift; |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
carp "Unable to apply rule $self as there is no return value!" |
530
|
|
|
|
|
|
|
unless exists $self->{"insertname.value"}; |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
$self->report("Applying: $self\n"); |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
# Is the rule valid? |
535
|
|
|
|
|
|
|
# |
536
|
|
|
|
|
|
|
return unless $self->is_valid($pars); |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
# Set the value |
539
|
|
|
|
|
|
|
# |
540
|
|
|
|
|
|
|
my $target = $self->{targets}->[0]; |
541
|
|
|
|
|
|
|
my $name = $pars->{Name}; |
542
|
|
|
|
|
|
|
$self->report ("--setting: $target (name=$name)\n"); |
543
|
|
|
|
|
|
|
$pars->{$target} = eval "return \"" . $self->{"insertname.value"} . "\";"; |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
# Poor name. This is the old "dosubst" routine |
547
|
|
|
|
|
|
|
# |
548
|
|
|
|
|
|
|
# PDL::PP::Rule->new("NewXSCoerceMustSubs", ["NewXSCoerceMustSub1","NewXSSymTab","Name"], |
549
|
|
|
|
|
|
|
# \&dosubst), |
550
|
|
|
|
|
|
|
# |
551
|
|
|
|
|
|
|
# PDL::PP::Rule::Substitute->new($target,$condition) |
552
|
|
|
|
|
|
|
# $target and $condition must be scalars. |
553
|
|
|
|
|
|
|
# |
554
|
|
|
|
|
|
|
# Implicit conditions are NewXSSymTab and Name |
555
|
|
|
|
|
|
|
# |
556
|
|
|
|
|
|
|
package PDL::PP::Rule::Substitute; |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
use strict; |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
use Carp; |
561
|
|
|
|
|
|
|
our @CARP_NOT; |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
##use PDL::PP::Rule; |
564
|
|
|
|
|
|
|
our @ISA = qw (PDL::PP::Rule); |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
# Probably want this directly in the apply routine but leave as is for now |
567
|
|
|
|
|
|
|
# |
568
|
|
|
|
|
|
|
sub dosubst_private { |
569
|
|
|
|
|
|
|
my ($src,$symtab,$name) = @_; |
570
|
|
|
|
|
|
|
my $ret = (ref $src ? $src->[0] : $src); |
571
|
|
|
|
|
|
|
my %syms = ( |
572
|
|
|
|
|
|
|
((ref $src) ? %{$src->[1]} : ()), |
573
|
|
|
|
|
|
|
PRIV => sub {return "".$symtab->get_symname('_PDL_ThisTrans'). |
574
|
|
|
|
|
|
|
"->$_[0]"}, |
575
|
|
|
|
|
|
|
CROAK => sub {PDL::PP::pp_line_numbers(__LINE__, "PDL->pdl_barf(\"Error in $name:\" $_[0])")}, |
576
|
0
|
|
|
|
|
|
NAME => sub {return $name}, |
577
|
|
|
|
|
|
|
MODULE => sub {return $::PDLMOD}, |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
SETPDLSTATEBAD => sub { PDL::PP::pp_line_numbers(__LINE__, "$_[0]\->state |= PDL_BADVAL") }, |
580
|
|
|
|
|
|
|
SETPDLSTATEGOOD => sub { PDL::PP::pp_line_numbers(__LINE__, "$_[0]\->state &= ~PDL_BADVAL") }, |
581
|
|
|
|
|
|
|
ISPDLSTATEBAD => sub { PDL::PP::pp_line_numbers(__LINE__, "(($_[0]\->state & PDL_BADVAL) > 0)") }, |
582
|
14
|
|
|
|
|
|
ISPDLSTATEGOOD => sub { PDL::PP::pp_line_numbers(__LINE__, "(($_[0]\->state & PDL_BADVAL) == 0)") }, |
583
|
|
|
|
|
|
|
BADFLAGCACHE => sub { PDL::PP::pp_line_numbers(__LINE__, "badflag_cache") }, |
584
|
14
|
50
|
|
|
|
|
|
585
|
14
|
|
|
|
|
|
SETREVERSIBLE => sub { |
586
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, "if($_[0]) \$PRIV(flags) |= PDL_ITRANS_REVERSIBLE;\n" . |
587
|
|
|
|
|
|
|
" else \$PRIV(flags) &= ~PDL_ITRANS_REVERSIBLE;\n") |
588
|
|
|
|
|
|
|
}, |
589
|
|
|
|
|
|
|
); |
590
|
|
|
|
|
|
|
while( |
591
|
|
|
|
|
|
|
$ret =~ s/\$(\w+)\(([^()]*)\)/ |
592
|
|
|
|
|
|
|
(defined $syms{$1} or |
593
|
|
|
|
|
|
|
confess("$1 not defined in '$ret'!")) and |
594
|
|
|
|
|
|
|
(&{$syms{$1}}($2))/ge |
595
|
|
|
|
|
|
|
) {}; |
596
|
|
|
|
|
|
|
$ret; |
597
|
|
|
|
|
|
|
} |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
sub new { |
600
|
|
|
|
|
|
|
my $class = shift; |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
die "Usage: PDL::PP::Rule::Substitute->new(\$target,\$condition);" |
603
|
|
|
|
|
|
|
unless $#_ == 1; |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
my $target = shift; |
606
|
|
|
|
|
|
|
my $condition = shift; |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
die "\$target must be a scalar for PDL::PP::Rule->Substitute" if ref $target; |
609
|
|
|
|
|
|
|
die "\$condition must be a scalar for PDL::PP::Rule->Substitute" if ref $condition; |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
my $self = $class->SUPER::new($target, [$condition, "NewXSSymTab", "Name"], |
612
|
|
|
|
|
|
|
\&dosubst_private); |
613
|
|
|
|
|
|
|
bless $self, $class; |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
return $self; |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
# Poor name. This is the old "dousualsubsts" routine |
619
|
|
|
|
|
|
|
# |
620
|
|
|
|
|
|
|
# PDL::PP::Rule->new("CacheBadFlagInit", ["CacheBadFlagInitNS","NewXSSymTab","Name"], |
621
|
|
|
|
|
|
|
# \&dousualsubsts), |
622
|
|
|
|
|
|
|
# |
623
|
|
|
|
|
|
|
# PDL::PP::Rule::Substitute::Usual->new($target, $condition) |
624
|
|
|
|
|
|
|
# $target and $condition must be scalars. |
625
|
|
|
|
|
|
|
# |
626
|
|
|
|
|
|
|
# Implicit conditions are NewXSSymTab and Name |
627
|
|
|
|
|
|
|
# |
628
|
|
|
|
|
|
|
# Need to think about @std_childparent as it is also used by |
629
|
|
|
|
|
|
|
# other bits of code. At the moment provide a class method |
630
|
|
|
|
|
|
|
# to access the array but there has to be better ways of |
631
|
|
|
|
|
|
|
# doing this. |
632
|
|
|
|
|
|
|
# |
633
|
|
|
|
|
|
|
package PDL::PP::Rule::Substitute::Usual; |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
use strict; |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
use Carp; |
638
|
|
|
|
|
|
|
our @CARP_NOT; |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
##use PDL::PP::Rule; |
641
|
|
|
|
|
|
|
our @ISA = qw (PDL::PP::Rule::Substitute); |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
# This is a copy of the main one for now. Need a better solution. |
644
|
|
|
|
|
|
|
# |
645
|
|
|
|
|
|
|
my @std_childparent = ( |
646
|
|
|
|
|
|
|
CHILD => sub {PDL::PP::pp_line_numbers(__LINE__, '$PRIV(pdls[1]->'.(join ',',@_).")")}, |
647
|
|
|
|
|
|
|
PARENT => sub {PDL::PP::pp_line_numbers(__LINE__, '$PRIV(pdls[0]->'.(join ',',@_).")")}, |
648
|
|
|
|
|
|
|
CHILD_P => sub {PDL::PP::pp_line_numbers(__LINE__, '$PRIV(pdls[1]->'.(join ',',@_).")")}, |
649
|
|
|
|
|
|
|
PARENT_P => sub {PDL::PP::pp_line_numbers(__LINE__, '$PRIV(pdls[0]->'.(join ',',@_).")")}, |
650
|
|
|
|
|
|
|
CHILD_PTR => sub {PDL::PP::pp_line_numbers(__LINE__, '$PRIV(pdls[1])')}, |
651
|
|
|
|
|
|
|
PARENT_PTR => sub {PDL::PP::pp_line_numbers(__LINE__, '$PRIV(pdls[0])')}, |
652
|
|
|
|
|
|
|
COMP => sub {PDL::PP::pp_line_numbers(__LINE__, '$PRIV('.(join ',',@_).")")} |
653
|
|
|
|
|
|
|
); |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
sub get_std_childparent { return @std_childparent; } |
656
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
sub new { |
658
|
|
|
|
|
|
|
my $class = shift; |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
my @args = @_; |
661
|
|
|
|
|
|
|
my $self = $class->SUPER::new(@args); |
662
|
|
|
|
|
|
|
bless $self, $class; |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
return $self; |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
# We modify the arguments from the conditions to include the |
668
|
|
|
|
|
|
|
# extra information |
669
|
|
|
|
|
|
|
# |
670
|
|
|
|
|
|
|
# We simplify the base-class version since we assume that all |
671
|
|
|
|
|
|
|
# conditions are required here. |
672
|
|
|
|
|
|
|
# |
673
|
|
|
|
|
|
|
sub extract_args { |
674
|
|
|
|
|
|
|
my $self = shift; |
675
|
|
|
|
|
|
|
my $pars = shift; |
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
# The conditions are [, NewXSSymTab, Name] |
678
|
|
|
|
|
|
|
# |
679
|
|
|
|
|
|
|
my $code = $pars->{$self->{conditions}[0]}; |
680
|
|
|
|
|
|
|
my $symtab = $pars->{$self->{conditions}[1]}; |
681
|
|
|
|
|
|
|
my $name = $pars->{$self->{conditions}[2]}; |
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
return ([$code,{@std_childparent}],$symtab,$name); |
684
|
|
|
|
|
|
|
} |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
# Poor name. This is the old "subst_makecomp" routine |
687
|
|
|
|
|
|
|
# |
688
|
|
|
|
|
|
|
# PDL::PP::Rule->new("MakeCompiledRepr", ["MakeComp","CompNames","CompObjs"], |
689
|
|
|
|
|
|
|
# sub {subst_makecomp("COMP",@_)}), |
690
|
|
|
|
|
|
|
# |
691
|
|
|
|
|
|
|
# PDL::PP::Rule::MakeComp->new($target,$conditions,$symbol) |
692
|
|
|
|
|
|
|
# $target and $symbol must be scalars. |
693
|
|
|
|
|
|
|
# |
694
|
|
|
|
|
|
|
package PDL::PP::Rule::MakeComp; |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
use strict; |
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
use Carp; |
699
|
|
|
|
|
|
|
our @CARP_NOT; |
700
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
##use PDL::PP::Rule; |
702
|
|
|
|
|
|
|
our @ISA = qw (PDL::PP::Rule); |
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
# This is a copy of the main one for now. Need a better solution. |
705
|
|
|
|
|
|
|
# |
706
|
|
|
|
|
|
|
my @std_redodims = ( |
707
|
|
|
|
|
|
|
SETNDIMS => sub {PDL::PP::pp_line_numbers(__LINE__, "PDL->reallocdims(__it,$_[0])")}, |
708
|
|
|
|
|
|
|
SETDIMS => sub {PDL::PP::pp_line_numbers(__LINE__, "PDL->setdims_careful(__it)")}, |
709
|
|
|
|
|
|
|
SETDELTATHREADIDS => sub {PDL::PP::pp_line_numbers(__LINE__, ' |
710
|
|
|
|
|
|
|
{int __ind; PDL->reallocthreadids($CHILD_PTR(), |
711
|
|
|
|
|
|
|
$PARENT(nthreadids)); |
712
|
|
|
|
|
|
|
for(__ind=0; __ind<$PARENT(nthreadids)+1; __ind++) { |
713
|
|
|
|
|
|
|
$CHILD(threadids[__ind]) = |
714
|
|
|
|
|
|
|
$PARENT(threadids[__ind]) + ('.$_[0].'); |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
} |
717
|
|
|
|
|
|
|
')}); |
718
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
##sub get_std_redodims { return @std_redodims; } |
720
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
# Probably want this directly in the apply routine but leave as is for now |
722
|
|
|
|
|
|
|
# |
723
|
|
|
|
|
|
|
sub subst_makecomp_private { |
724
|
|
|
|
|
|
|
my($which,$mc,$cn,$co) = @_; |
725
|
|
|
|
|
|
|
return [$mc,{ |
726
|
|
|
|
|
|
|
# @::std_childparent, |
727
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual::get_std_childparent(), |
728
|
|
|
|
|
|
|
($cn ? |
729
|
|
|
|
|
|
|
(('DO'.$which.'DIMS') => sub {PDL::PP::pp_line_numbers(__LINE__, join '', |
730
|
|
|
|
|
|
|
map{$$co{$_}->need_malloc ? |
731
|
|
|
|
|
|
|
$$co{$_}->get_malloc('$PRIV('.$_.')') : |
732
|
|
|
|
|
|
|
()} @$cn)}) : |
733
|
|
|
|
|
|
|
() |
734
|
|
|
|
|
|
|
), |
735
|
|
|
|
|
|
|
($which eq "PRIV" ? |
736
|
|
|
|
|
|
|
@std_redodims : ()), |
737
|
|
|
|
|
|
|
}, |
738
|
|
|
|
|
|
|
]; |
739
|
|
|
|
|
|
|
} |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
sub new { |
742
|
|
|
|
|
|
|
my $class = shift; |
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
die "Usage: PDL::PP::Rule::MakeComp->new(\$target,\$conditions,\$symbol);" |
745
|
|
|
|
|
|
|
unless $#_ == 2; |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
my $target = shift; |
748
|
|
|
|
|
|
|
my $condition = shift; |
749
|
|
|
|
|
|
|
my $symbol = shift; |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
die "\$target must be a scalar for PDL::PP::Rule->MakeComp" if ref $target; |
752
|
|
|
|
|
|
|
die "\$symbol must be a scalar for PDL::PP::Rule->MakeComp" if ref $symbol; |
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
my $self = $class->SUPER::new($target, $condition, |
755
|
|
|
|
|
|
|
\&subst_makecomp_private); |
756
|
|
|
|
|
|
|
bless $self, $class; |
757
|
|
|
|
|
|
|
$self->{"makecomp.value"} = $symbol; |
758
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
return $self; |
760
|
|
|
|
|
|
|
} |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
# We modify the arguments from the conditions to include the |
763
|
|
|
|
|
|
|
# extra information |
764
|
|
|
|
|
|
|
# |
765
|
|
|
|
|
|
|
# We simplify the base-class version since we assume that all |
766
|
|
|
|
|
|
|
# conditions are required here. |
767
|
|
|
|
|
|
|
# |
768
|
|
|
|
|
|
|
sub extract_args { |
769
|
|
|
|
|
|
|
my $self = shift; |
770
|
|
|
|
|
|
|
my $pars = shift; |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
# The conditions are [, conditions...] |
773
|
|
|
|
|
|
|
# - could use slicing here |
774
|
|
|
|
|
|
|
# |
775
|
|
|
|
|
|
|
my @args = ($self->{"makecomp.value"}); |
776
|
|
|
|
|
|
|
foreach my $condition (@{$self->{conditions}}) { |
777
|
|
|
|
|
|
|
push @args, $pars->{$condition}; |
778
|
|
|
|
|
|
|
} |
779
|
|
|
|
|
|
|
return @args; |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
package PDL::PP; |
783
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
use strict; |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
our $VERSION = "2.3"; |
787
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
use PDL::Types ':All'; |
790
|
|
|
|
|
|
|
use Config; |
791
|
|
|
|
|
|
|
use FileHandle; |
792
|
|
|
|
|
|
|
use Exporter; |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
use Data::Dumper; |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
@PDL::PP::EXPORT = qw/pp_addhdr pp_addpm pp_bless pp_def pp_done pp_add_boot |
799
|
|
|
|
|
|
|
pp_add_exported pp_addxs pp_add_isa pp_export_nothing |
800
|
|
|
|
|
|
|
pp_core_importList pp_beginwrap pp_setversion |
801
|
|
|
|
|
|
|
pp_addbegin pp_boundscheck pp_line_numbers |
802
|
|
|
|
|
|
|
pp_deprecate_module/; |
803
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
$PP::boundscheck = 1; |
805
|
|
|
|
|
|
|
$::PP_VERBOSE = 0; |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
$PDL::PP::done = 0; # pp_done has not been called yet |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
END { |
810
|
|
|
|
|
|
|
#you can uncomment this for testing, but this should remain |
811
|
|
|
|
|
|
|
#commented in production code. This causes pp_done to be called |
812
|
|
|
|
|
|
|
#even when a .pd file aborts with die(), potentially bypassing |
813
|
|
|
|
|
|
|
#problem code when build is re-attempted. Having this commented |
814
|
|
|
|
|
|
|
#means we are a bit more strict: a module must call pp_done in |
815
|
|
|
|
|
|
|
#order to have .xs and .pm files written. |
816
|
|
|
|
|
|
|
# pp_done() unless $PDL::PP::done; |
817
|
|
|
|
|
|
|
} |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
use Carp; |
820
|
|
|
|
|
|
|
our @CARP_NOT; |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
# check for bad value support |
823
|
|
|
|
|
|
|
use PDL::Config; |
824
|
|
|
|
|
|
|
my $bvalflag = $PDL::Config{WITH_BADVAL} || 0; |
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
my $ntypes = $#PDL::Types::names; |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
sub nopm { $::PDLPACK eq 'NONE' } # flag that we don't want to generate a PM |
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
sub import { |
831
|
|
|
|
|
|
|
my ($mod,$modname, $packname, $prefix, $callpack) = @_; |
832
|
|
|
|
|
|
|
# Allow for users to not specify the packname |
833
|
|
|
|
|
|
|
($packname, $prefix, $callpack) = ($modname, $packname, $prefix) |
834
|
|
|
|
|
|
|
if ($packname =~ m|/|); |
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
$::PDLMOD=$modname; $::PDLPACK=$packname; $::PDLPREF=$prefix; |
837
|
|
|
|
|
|
|
$::CALLPACK = defined $callpack ? $callpack : $::PDLMOD; |
838
|
|
|
|
|
|
|
$::PDLOBJ = "PDL"; # define pp-funcs in this package |
839
|
|
|
|
|
|
|
$::PDLXS=""; |
840
|
|
|
|
|
|
|
$::PDLBEGIN=""; |
841
|
|
|
|
|
|
|
$::PDLPMROUT=""; |
842
|
|
|
|
|
|
|
for ('Top','Bot','Middle') { $::PDLPM{$_}="" } |
843
|
|
|
|
|
|
|
@::PDLPMISA=('PDL::Exporter', 'DynaLoader'); |
844
|
|
|
|
|
|
|
@::PDL_IFBEGINWRAP = ('',''); |
845
|
|
|
|
|
|
|
$::PDLVERSIONSET = ''; |
846
|
|
|
|
|
|
|
$::PDLMODVERSION = undef; |
847
|
|
|
|
|
|
|
$::DOCUMENTED = 0; |
848
|
|
|
|
|
|
|
$::PDLCOREIMPORT = ""; #import list from core, defaults to everything, i.e. use Core |
849
|
|
|
|
|
|
|
# could be set to () for importing nothing from core. or qw/ barf / for |
850
|
|
|
|
|
|
|
# importing barf only. |
851
|
|
|
|
|
|
|
@_=("PDL::PP"); |
852
|
|
|
|
|
|
|
goto &Exporter::import; |
853
|
|
|
|
|
|
|
} |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
# query/set boundschecking |
857
|
|
|
|
|
|
|
# if on the generated XS code will have optional boundschecking |
858
|
|
|
|
|
|
|
# that can be turned on/off at runtime(!) using |
859
|
|
|
|
|
|
|
# __PACKAGE__::set_boundscheck(arg); # arg should be 0/1 |
860
|
|
|
|
|
|
|
# if off code is speed optimized and no runtime boundschecking |
861
|
|
|
|
|
|
|
# can be performed |
862
|
|
|
|
|
|
|
# ON by default |
863
|
|
|
|
|
|
|
sub pp_boundscheck { |
864
|
|
|
|
|
|
|
my $ret = $PP::boundscheck; |
865
|
|
|
|
|
|
|
$PP::boundscheck = $_[0] if $#_ > -1; |
866
|
|
|
|
|
|
|
return $ret; |
867
|
|
|
|
|
|
|
} |
868
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
sub pp_beginwrap { |
870
|
|
|
|
|
|
|
@::PDL_IFBEGINWRAP = ('BEGIN {','}'); |
871
|
|
|
|
|
|
|
} |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
sub pp_setversion { |
874
|
|
|
|
|
|
|
my ($ver) = @_; |
875
|
|
|
|
|
|
|
$::PDLMODVERSION = '$VERSION'; |
876
|
|
|
|
|
|
|
$::PDLVERSIONSET = "\$$::PDLPACK\::VERSION = $ver;"; |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
sub pp_addhdr { |
880
|
|
|
|
|
|
|
my ($hdr) = @_; |
881
|
|
|
|
|
|
|
$::PDLXSC .= $hdr; |
882
|
|
|
|
|
|
|
} |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
sub pp_addpm { |
885
|
|
|
|
|
|
|
my $pm = shift; |
886
|
|
|
|
|
|
|
my $pos; |
887
|
|
|
|
|
|
|
if (ref $pm) { |
888
|
|
|
|
|
|
|
my $opt = $pm; |
889
|
|
|
|
|
|
|
$pm = shift; |
890
|
|
|
|
|
|
|
croak "unknown option" unless defined $opt->{At} && |
891
|
|
|
|
|
|
|
$opt->{At} =~ /^(Top|Bot|Middle)$/; |
892
|
|
|
|
|
|
|
$pos = $opt->{At}; |
893
|
|
|
|
|
|
|
} else { |
894
|
|
|
|
|
|
|
$pos = 'Middle'; |
895
|
|
|
|
|
|
|
} |
896
|
|
|
|
|
|
|
$::PDLPM{$pos} .= "$pm\n\n"; |
897
|
|
|
|
|
|
|
} |
898
|
|
|
|
|
|
|
|
899
|
|
|
|
|
|
|
sub pp_add_exported { |
900
|
|
|
|
|
|
|
# my ($this,$exp) = @_; |
901
|
|
|
|
|
|
|
my $exp = join ' ', @_; # get rid of this silly $this argument |
902
|
|
|
|
|
|
|
$::PDLPMROUT .= $exp." "; |
903
|
|
|
|
|
|
|
} |
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
sub pp_addbegin { |
906
|
|
|
|
|
|
|
my ($cmd) = @_; |
907
|
|
|
|
|
|
|
if ($cmd =~ /^\s*BOOT\s*$/) { |
908
|
|
|
|
|
|
|
pp_beginwrap; |
909
|
|
|
|
|
|
|
} else { |
910
|
|
|
|
|
|
|
$::PDLBEGIN .= $cmd."\n"; |
911
|
|
|
|
|
|
|
} |
912
|
|
|
|
|
|
|
} |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
# Sub to call to export nothing (i.e. for building OO package/object) |
915
|
|
|
|
|
|
|
sub pp_export_nothing { |
916
|
|
|
|
|
|
|
$::PDLPMROUT = ' '; |
917
|
|
|
|
|
|
|
} |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
sub pp_add_isa { |
920
|
|
|
|
|
|
|
push @::PDLPMISA,@_; |
921
|
|
|
|
|
|
|
} |
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
sub pp_add_boot { |
924
|
|
|
|
|
|
|
my ($boot) = @_; |
925
|
|
|
|
|
|
|
$::PDLXSBOOT .= $boot." "; |
926
|
|
|
|
|
|
|
} |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
sub pp_bless{ |
929
|
|
|
|
|
|
|
my($new_package)=@_; |
930
|
|
|
|
|
|
|
$::PDLOBJ = $new_package; |
931
|
|
|
|
|
|
|
} |
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
# sub to call to set the import list from core on the 'Use Core' line in the .pm file. |
934
|
|
|
|
|
|
|
# set to '()' to not import anything from Core, or 'qw/ barf /' to import barf. |
935
|
|
|
|
|
|
|
sub pp_core_importList{ |
936
|
|
|
|
|
|
|
$::PDLCOREIMPORT = $_[0]; |
937
|
|
|
|
|
|
|
} |
938
|
|
|
|
|
|
|
|
939
|
|
|
|
|
|
|
sub printxs { |
940
|
|
|
|
|
|
|
shift; |
941
|
|
|
|
|
|
|
$::PDLXS .= join'',@_; |
942
|
|
|
|
|
|
|
} |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
sub pp_addxs { |
945
|
|
|
|
|
|
|
PDL::PP->printxs("\nMODULE = $::PDLMOD PACKAGE = $::CALLPACK\n\n", |
946
|
|
|
|
|
|
|
@_, |
947
|
|
|
|
|
|
|
"\nMODULE = $::PDLMOD PACKAGE = $::PDLOBJ\n\n"); |
948
|
|
|
|
|
|
|
} |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
# inserts #line directives into source text. Use like this: |
951
|
|
|
|
|
|
|
# ... |
952
|
|
|
|
|
|
|
# FirstKey => ..., |
953
|
|
|
|
|
|
|
# Code => pp_line_numbers(__LINE__, $x . $y . $c), |
954
|
|
|
|
|
|
|
# OtherKey => ... |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
sub pp_line_numbers ($$) { |
957
|
|
|
|
|
|
|
my ($line, $string) = @_; |
958
|
|
|
|
|
|
|
# The line needs to be incremented by one for the bookkeeping to work |
959
|
|
|
|
|
|
|
$line++; |
960
|
|
|
|
|
|
|
# Get the source filename using caller() |
961
|
|
|
|
|
|
|
my (undef, $filename) = caller; |
962
|
|
|
|
|
|
|
# Escape backslashes: |
963
|
|
|
|
|
|
|
$filename =~ s/\\/\\\\/g; |
964
|
|
|
|
|
|
|
my @to_return = "\n#line $line \"$filename\"\n"; |
965
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
# Look for threadloops and loops and add # line directives |
967
|
|
|
|
|
|
|
foreach (split (/\n/, $string)) { |
968
|
|
|
|
|
|
|
# Always add the current line. |
969
|
|
|
|
|
|
|
s/^=/ =/; # so doesn't look like POD |
970
|
|
|
|
|
|
|
push @to_return, "$_\n"; |
971
|
|
|
|
|
|
|
# If we need to add a # line directive, do so after incrementing |
972
|
|
|
|
|
|
|
$line++; |
973
|
|
|
|
|
|
|
if (/%\{/ or /%}/) { |
974
|
|
|
|
|
|
|
push @to_return, "#line $line \"$filename\"\n"; |
975
|
|
|
|
|
|
|
} |
976
|
|
|
|
|
|
|
} |
977
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
return join('', @to_return); |
979
|
|
|
|
|
|
|
} |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
sub printxsc { |
982
|
|
|
|
|
|
|
shift; |
983
|
|
|
|
|
|
|
$::PDLXSC .= join '',@_; |
984
|
|
|
|
|
|
|
} |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
sub pp_done { |
987
|
|
|
|
|
|
|
return if $PDL::PP::done; # do only once! |
988
|
|
|
|
|
|
|
$PDL::PP::done = 1; |
989
|
|
|
|
|
|
|
$::FUNCSPOD = $::DOCUMENTED ? "\n\n=head1 FUNCTIONS\n\n\n\n=cut\n\n\n" |
990
|
|
|
|
|
|
|
: ''; |
991
|
|
|
|
|
|
|
print "DONE!\n" if $::PP_VERBOSE; |
992
|
|
|
|
|
|
|
print "Inline running PDL::PP version $PDL::PP::VERSION...\n" if nopm(); |
993
|
|
|
|
|
|
|
(my $fh = FileHandle->new(">$::PDLPREF.xs")) or die "Couldn't open xs file\n"; |
994
|
|
|
|
|
|
|
my $pdl_boot = PDL::Core::Dev::PDL_BOOT('PDL', $::PDLMOD); # don't hardcode in more than one place |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
$fh->print(pp_line_numbers(__LINE__, qq% |
997
|
|
|
|
|
|
|
/* |
998
|
|
|
|
|
|
|
* THIS FILE WAS GENERATED BY PDL::PP! Do not modify! |
999
|
|
|
|
|
|
|
*/ |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
#define PDL_COMMENT(comment) |
1002
|
|
|
|
|
|
|
PDL_COMMENT("This preprocessor symbol is used to add commentary in the PDL ") |
1003
|
|
|
|
|
|
|
PDL_COMMENT("autogenerated code. Normally, one would use typical C-style ") |
1004
|
|
|
|
|
|
|
PDL_COMMENT("multiline comments (i.e. /* comment */). However, because such ") |
1005
|
|
|
|
|
|
|
PDL_COMMENT("comments do not nest, it's not possible for PDL::PP users to ") |
1006
|
|
|
|
|
|
|
PDL_COMMENT("comment-out sections of code using multiline comments, as is ") |
1007
|
|
|
|
|
|
|
PDL_COMMENT("often the practice when debugging, for example. So, when you ") |
1008
|
|
|
|
|
|
|
PDL_COMMENT("see something like this: ") |
1009
|
|
|
|
|
|
|
PDL_COMMENT(" ") |
1010
|
|
|
|
|
|
|
PDL_COMMENT("Memory access") |
1011
|
|
|
|
|
|
|
PDL_COMMENT(" ") |
1012
|
|
|
|
|
|
|
PDL_COMMENT("just think of it as a C multiline comment like: ") |
1013
|
|
|
|
|
|
|
PDL_COMMENT(" ") |
1014
|
|
|
|
|
|
|
PDL_COMMENT(" /* Memory access */ ") |
1015
|
|
|
|
|
|
|
|
1016
|
|
|
|
|
|
|
#include "EXTERN.h" |
1017
|
|
|
|
|
|
|
#include "perl.h" |
1018
|
|
|
|
|
|
|
#include "XSUB.h" |
1019
|
|
|
|
|
|
|
#include "pdl.h" |
1020
|
|
|
|
|
|
|
#include "pdlcore.h" |
1021
|
|
|
|
|
|
|
static Core* PDL; PDL_COMMENT("Structure hold core C functions") |
1022
|
|
|
|
|
|
|
static int __pdl_debugging = 0; |
1023
|
|
|
|
|
|
|
static int __pdl_boundscheck = 0; |
1024
|
|
|
|
|
|
|
static SV* CoreSV; PDL_COMMENT("Gets pointer to perl var holding core structure") |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
#if ! $PP::boundscheck |
1027
|
|
|
|
|
|
|
# define PP_INDTERM(max, at) at |
1028
|
|
|
|
|
|
|
#else |
1029
|
|
|
|
|
|
|
# define PP_INDTERM(max, at) (__pdl_boundscheck? PDL->safe_indterm(max,at, __FILE__, __LINE__) : at) |
1030
|
|
|
|
|
|
|
#endif |
1031
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
$::PDLXSC |
1033
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
MODULE = $::PDLMOD PACKAGE = $::PDLMOD |
1035
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
PROTOTYPES: ENABLE |
1037
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
int |
1039
|
|
|
|
|
|
|
set_debugging(i) |
1040
|
|
|
|
|
|
|
int i; |
1041
|
|
|
|
|
|
|
CODE: |
1042
|
|
|
|
|
|
|
RETVAL = __pdl_debugging; |
1043
|
|
|
|
|
|
|
__pdl_debugging = i; |
1044
|
|
|
|
|
|
|
OUTPUT: |
1045
|
|
|
|
|
|
|
RETVAL |
1046
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
int |
1048
|
|
|
|
|
|
|
set_boundscheck(i) |
1049
|
|
|
|
|
|
|
int i; |
1050
|
|
|
|
|
|
|
CODE: |
1051
|
|
|
|
|
|
|
if (! $PP::boundscheck) |
1052
|
|
|
|
|
|
|
warn("Bounds checking is disabled for $::PDLMOD"); |
1053
|
|
|
|
|
|
|
RETVAL = __pdl_boundscheck; |
1054
|
|
|
|
|
|
|
__pdl_boundscheck = i; |
1055
|
|
|
|
|
|
|
OUTPUT: |
1056
|
|
|
|
|
|
|
RETVAL |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
MODULE = $::PDLMOD PACKAGE = $::PDLOBJ |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
$::PDLXS |
1062
|
|
|
|
|
|
|
|
1063
|
|
|
|
|
|
|
BOOT: |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
PDL_COMMENT("Get pointer to structure of core shared C routines") |
1066
|
|
|
|
|
|
|
PDL_COMMENT("make sure PDL::Core is loaded") |
1067
|
|
|
|
|
|
|
$pdl_boot |
1068
|
|
|
|
|
|
|
$::PDLXSBOOT |
1069
|
|
|
|
|
|
|
%)); |
1070
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
unless (nopm) { |
1072
|
|
|
|
|
|
|
$::PDLPMISA = "'".join("','",@::PDLPMISA)."'"; |
1073
|
|
|
|
|
|
|
$::PDLBEGIN = "BEGIN {\n$::PDLBEGIN\n}" |
1074
|
|
|
|
|
|
|
unless $::PDLBEGIN =~ /^\s*$/; |
1075
|
|
|
|
|
|
|
($fh = FileHandle->new(">$::PDLPREF.pm")) or die "Couldn't open pm file\n"; |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
$fh->print(qq% |
1078
|
|
|
|
|
|
|
# |
1079
|
|
|
|
|
|
|
# GENERATED WITH PDL::PP! Don't modify! |
1080
|
|
|
|
|
|
|
# |
1081
|
|
|
|
|
|
|
package $::PDLPACK; |
1082
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
\@EXPORT_OK = qw( $::PDLPMROUT); |
1084
|
|
|
|
|
|
|
\%EXPORT_TAGS = (Func=>[\@EXPORT_OK]); |
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
use PDL::Core$::PDLCOREIMPORT; |
1087
|
|
|
|
|
|
|
use PDL::Exporter; |
1088
|
|
|
|
|
|
|
use DynaLoader; |
1089
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
$::PDL_IFBEGINWRAP[0] |
1092
|
|
|
|
|
|
|
$::PDLVERSIONSET |
1093
|
|
|
|
|
|
|
\@ISA = ( $::PDLPMISA ); |
1094
|
|
|
|
|
|
|
push \@PDL::Core::PP, __PACKAGE__; |
1095
|
|
|
|
|
|
|
bootstrap $::PDLMOD $::PDLMODVERSION; |
1096
|
|
|
|
|
|
|
$::PDL_IFBEGINWRAP[-1] |
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
$::PDLBEGIN |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
$::PDLPM{Top} |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
$::FUNCSPOD |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
$::PDLPM{Middle}; |
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
$::PDLPM{Bot} |
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
# Exit with OK status |
1109
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
1; |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
%); # end of print |
1113
|
|
|
|
|
|
|
} # unless (nopm) {... |
1114
|
|
|
|
|
|
|
} # end pp_done |
1115
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
sub pp_def { |
1117
|
|
|
|
|
|
|
my($name,%obj) = @_; |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
print "*** Entering pp_def for $name\n" if $::PP_VERBOSE; |
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
# See if the 'name' is multiline, in which case we extract the |
1122
|
|
|
|
|
|
|
# name and add the FullDoc field |
1123
|
|
|
|
|
|
|
if ($name =~ /\n/) { |
1124
|
|
|
|
|
|
|
my $fulldoc = $name; |
1125
|
|
|
|
|
|
|
# See if the very first thing is a word. That is going to be the |
1126
|
|
|
|
|
|
|
# name of the function under consideration |
1127
|
|
|
|
|
|
|
if ($fulldoc =~ s/^(\w+)//) { |
1128
|
|
|
|
|
|
|
$name = $1; |
1129
|
|
|
|
|
|
|
} |
1130
|
|
|
|
|
|
|
elsif ($fulldoc =~ /=head2 (\w+)/) { |
1131
|
|
|
|
|
|
|
$name = $1; |
1132
|
|
|
|
|
|
|
} |
1133
|
|
|
|
|
|
|
else { |
1134
|
|
|
|
|
|
|
croak('Unable to extract name'); |
1135
|
|
|
|
|
|
|
} |
1136
|
|
|
|
|
|
|
$obj{FullDoc} = $fulldoc; |
1137
|
|
|
|
|
|
|
} |
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
$obj{Name} = $name; |
1140
|
|
|
|
|
|
|
translate(\%obj,$PDL::PP::deftbl); |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
print "Output of translate for $name:\n" . Dumper(\%obj) . "\n" |
1143
|
|
|
|
|
|
|
if exists $obj{Dump} and $obj{Dump} and $::PP_VERBOSE; |
1144
|
|
|
|
|
|
|
|
1145
|
|
|
|
|
|
|
croak("ERROR: No FreeFunc for pp_def=$name!\n") |
1146
|
|
|
|
|
|
|
unless exists $obj{FreeFunc}; # and $obj{FreeFunc}; |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
PDL::PP->printxsc(join "\n\n",@obj{'StructDecl','RedoDimsFunc', |
1149
|
|
|
|
|
|
|
'CopyFunc', |
1150
|
|
|
|
|
|
|
'ReadDataFunc','WriteBackDataFunc', |
1151
|
|
|
|
|
|
|
'FreeFunc', |
1152
|
|
|
|
|
|
|
'FooFunc', |
1153
|
|
|
|
|
|
|
'VTableDef','NewXSInPrelude', |
1154
|
|
|
|
|
|
|
} |
1155
|
|
|
|
|
|
|
); |
1156
|
|
|
|
|
|
|
PDL::PP->printxs($obj{NewXSCode}); |
1157
|
|
|
|
|
|
|
pp_add_boot($obj{XSBootCode} . $obj{BootSetNewXS}); |
1158
|
|
|
|
|
|
|
PDL::PP->pp_add_exported($name); |
1159
|
|
|
|
|
|
|
PDL::PP::pp_addpm("\n".$obj{PdlDoc}."\n") if $obj{PdlDoc}; |
1160
|
|
|
|
|
|
|
PDL::PP::pp_addpm($obj{PMCode}); |
1161
|
|
|
|
|
|
|
PDL::PP::pp_addpm($obj{PMFunc}."\n"); |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
print "*** Leaving pp_def for $name\n" if $::PP_VERBOSE; |
1164
|
|
|
|
|
|
|
} |
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
# marks this module as deprecated. This handles the user warnings, and adds a |
1167
|
|
|
|
|
|
|
# notice into the documentation. Can take a {infavor => "newmodule"} option |
1168
|
|
|
|
|
|
|
sub pp_deprecate_module |
1169
|
|
|
|
|
|
|
{ |
1170
|
|
|
|
|
|
|
my $options; |
1171
|
|
|
|
|
|
|
if( ref $_[0] eq 'HASH' ) { $options = shift; } |
1172
|
|
|
|
|
|
|
else { $options = { @_ }; } |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
my $infavor; |
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
if( $options && ref $options eq 'HASH' && $options->{infavor} ) |
1177
|
|
|
|
|
|
|
{ |
1178
|
|
|
|
|
|
|
$infavor = $options->{infavor}; |
1179
|
|
|
|
|
|
|
} |
1180
|
|
|
|
|
|
|
|
1181
|
|
|
|
|
|
|
my $mod = $::PDLMOD; |
1182
|
|
|
|
|
|
|
my $envvar = 'PDL_SUPPRESS_DEPRECATION_WARNING__' . uc $mod; |
1183
|
|
|
|
|
|
|
$envvar =~ s/::/_/g; |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
my $warning_main = |
1186
|
|
|
|
|
|
|
"$mod is deprecated."; |
1187
|
|
|
|
|
|
|
$warning_main .= |
1188
|
|
|
|
|
|
|
" Please use $infavor instead." if $infavor; |
1189
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
my $warning_suppression_runtime = |
1191
|
|
|
|
|
|
|
"This module will be removed in the future; please update your code.\n" . |
1192
|
|
|
|
|
|
|
"Set the environment variable $envvar\n" . |
1193
|
|
|
|
|
|
|
"to suppress this warning\n"; |
1194
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
my $warning_suppression_pod = |
1196
|
|
|
|
|
|
|
"A warning will be generated at runtime upon a C |
1197
|
|
|
|
|
|
|
"This warning can be suppressed by setting the $envvar\n" . |
1198
|
|
|
|
|
|
|
"environment variable\n"; |
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
my $deprecation_notice = <
|
1201
|
|
|
|
|
|
|
XXX=head1 DEPRECATION NOTICE |
1202
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
$warning_main |
1204
|
|
|
|
|
|
|
$warning_suppression_pod |
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
XXX=cut |
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
EOF |
1209
|
|
|
|
|
|
|
$deprecation_notice =~ s/^XXX=/=/gms; |
1210
|
|
|
|
|
|
|
pp_addpm( {At => 'Top'}, $deprecation_notice ); |
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
pp_addpm {At => 'Top'}, <
|
1213
|
|
|
|
|
|
|
warn \"$warning_main\n$warning_suppression_runtime\" unless \$ENV{$envvar}; |
1214
|
|
|
|
|
|
|
EOF |
1215
|
|
|
|
|
|
|
|
1216
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
} |
1218
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
# Worst memleaks: not freeing things at redodims or |
1220
|
|
|
|
|
|
|
# final free time (thread, dimmed things). |
1221
|
|
|
|
|
|
|
|
1222
|
|
|
|
|
|
|
use Carp; |
1223
|
|
|
|
|
|
|
$SIG{__DIE__} = sub {print Carp::longmess(@_); die;} |
1224
|
|
|
|
|
|
|
if $::PP_VERBOSE; # seems to give us trouble with 5.6.1 |
1225
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
use PDL::PP::Signature; |
1227
|
|
|
|
|
|
|
use PDL::PP::Dims; |
1228
|
|
|
|
|
|
|
use PDL::PP::CType; |
1229
|
|
|
|
|
|
|
use PDL::PP::XS; |
1230
|
|
|
|
|
|
|
use PDL::PP::SymTab; |
1231
|
|
|
|
|
|
|
use PDL::PP::PDLCode; |
1232
|
|
|
|
|
|
|
|
1233
|
|
|
|
|
|
|
$|=1; |
1234
|
|
|
|
|
|
|
|
1235
|
|
|
|
|
|
|
# |
1236
|
|
|
|
|
|
|
# This is ripped from xsubpp to ease the parsing of the typemap. |
1237
|
|
|
|
|
|
|
# |
1238
|
|
|
|
|
|
|
our $proto_re = "[" . quotemeta('\$%&*@;[]') . "]" ; |
1239
|
|
|
|
|
|
|
|
1240
|
|
|
|
|
|
|
sub ValidProtoString ($) |
1241
|
|
|
|
|
|
|
{ |
1242
|
|
|
|
|
|
|
my($string) = @_ ; |
1243
|
|
|
|
|
|
|
|
1244
|
|
|
|
|
|
|
if ( $string =~ /^$proto_re+$/ ) { |
1245
|
|
|
|
|
|
|
return $string ; |
1246
|
|
|
|
|
|
|
} |
1247
|
|
|
|
|
|
|
|
1248
|
|
|
|
|
|
|
return 0 ; |
1249
|
|
|
|
|
|
|
} |
1250
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
sub C_string ($) |
1252
|
|
|
|
|
|
|
{ |
1253
|
|
|
|
|
|
|
my($string) = @_ ; |
1254
|
|
|
|
|
|
|
|
1255
|
|
|
|
|
|
|
$string =~ s[\\][\\\\]g ; |
1256
|
|
|
|
|
|
|
$string ; |
1257
|
|
|
|
|
|
|
} |
1258
|
|
|
|
|
|
|
|
1259
|
|
|
|
|
|
|
sub TrimWhitespace |
1260
|
|
|
|
|
|
|
{ |
1261
|
|
|
|
|
|
|
$_[0] =~ s/^\s+|\s+$//go ; |
1262
|
|
|
|
|
|
|
} |
1263
|
|
|
|
|
|
|
sub TidyType |
1264
|
|
|
|
|
|
|
{ |
1265
|
|
|
|
|
|
|
local ($_) = @_ ; |
1266
|
|
|
|
|
|
|
|
1267
|
|
|
|
|
|
|
# rationalise any '*' by joining them into bunches and removing whitespace |
1268
|
|
|
|
|
|
|
s#\s*(\*+)\s*#$1#g; |
1269
|
|
|
|
|
|
|
s#(\*+)# $1 #g ; |
1270
|
|
|
|
|
|
|
|
1271
|
|
|
|
|
|
|
# change multiple whitespace into a single space |
1272
|
|
|
|
|
|
|
s/\s+/ /g ; |
1273
|
|
|
|
|
|
|
|
1274
|
|
|
|
|
|
|
# trim leading & trailing whitespace |
1275
|
|
|
|
|
|
|
TrimWhitespace($_) ; |
1276
|
|
|
|
|
|
|
|
1277
|
|
|
|
|
|
|
$_ ; |
1278
|
|
|
|
|
|
|
} |
1279
|
|
|
|
|
|
|
|
1280
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
|
1282
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
1283
|
|
|
|
|
|
|
# Typemap handling in PP. |
1284
|
|
|
|
|
|
|
# |
1285
|
|
|
|
|
|
|
# This subroutine does limited input typemap conversion. |
1286
|
|
|
|
|
|
|
# Given a variable name (to set), its type, and the source |
1287
|
|
|
|
|
|
|
# for the variable, returns the correct input typemap entry. |
1288
|
|
|
|
|
|
|
# Original version: D. Hunt 4/13/00 - Current version J. Brinchmann (06/05/05) |
1289
|
|
|
|
|
|
|
# |
1290
|
|
|
|
|
|
|
# This is an extended typemap handler from the one earlier written by |
1291
|
|
|
|
|
|
|
# Doug Hunt. It should work exactly as the older version, but with extensions. |
1292
|
|
|
|
|
|
|
# Instead of handling a few special cases explicitly we now use Perl's |
1293
|
|
|
|
|
|
|
# built-in typemap handling using code taken straight from xsubpp. |
1294
|
|
|
|
|
|
|
# |
1295
|
|
|
|
|
|
|
# I have infact kept the old part of the code here because I belive any |
1296
|
|
|
|
|
|
|
# subsequent hackers might find it very helpful to refer to this code to |
1297
|
|
|
|
|
|
|
# understand what the following does. So here goes: |
1298
|
|
|
|
|
|
|
# |
1299
|
|
|
|
|
|
|
# ------------ OLD TYPEMAP PARSING: ------------------------ |
1300
|
|
|
|
|
|
|
# |
1301
|
|
|
|
|
|
|
# # Note that I now just look at the basetype. I don't |
1302
|
|
|
|
|
|
|
# # test whether it is a pointer to the base type or not. |
1303
|
|
|
|
|
|
|
# # This is done because it is simpler and I know that the otherpars |
1304
|
|
|
|
|
|
|
# # belong to a restricted set of types. I know a char will really |
1305
|
|
|
|
|
|
|
# # be a char *, for example. I also know that an SV will be an SV *. |
1306
|
|
|
|
|
|
|
# # yes, but how about catching syntax errors in OtherPars (CS)? |
1307
|
|
|
|
|
|
|
# # shouldn't we really parse the perl typemap (we can steal the code |
1308
|
|
|
|
|
|
|
# # from xsubpp)? |
1309
|
|
|
|
|
|
|
# |
1310
|
|
|
|
|
|
|
# my $OLD_PARSING=0; |
1311
|
|
|
|
|
|
|
# if ($OLD_PARSING) { |
1312
|
|
|
|
|
|
|
# my %typemap = (char => "(char *)SvPV($arg,PL_na)", |
1313
|
|
|
|
|
|
|
# short => "(short)SvIV($arg)", |
1314
|
|
|
|
|
|
|
# int => "(int)SvIV($arg)", |
1315
|
|
|
|
|
|
|
# long => "(long)SvIV($arg)", |
1316
|
|
|
|
|
|
|
# double => "(double)SvNV($arg)", |
1317
|
|
|
|
|
|
|
# float => "(float)SvNV($arg)", |
1318
|
|
|
|
|
|
|
# SV => "$arg", |
1319
|
|
|
|
|
|
|
# ); |
1320
|
|
|
|
|
|
|
# my $basetype = $type->{Base}; |
1321
|
|
|
|
|
|
|
# $basetype =~ s/\s+//g; # get rid of whitespace |
1322
|
|
|
|
|
|
|
# |
1323
|
|
|
|
|
|
|
# die "Cannot find $basetype in my (small) typemap" unless exists($typemap{$basetype}); |
1324
|
|
|
|
|
|
|
# return ($typemap{$basetype}); |
1325
|
|
|
|
|
|
|
# } |
1326
|
|
|
|
|
|
|
# |
1327
|
|
|
|
|
|
|
#--------- END OF THE OLD CODE --------------- |
1328
|
|
|
|
|
|
|
# |
1329
|
|
|
|
|
|
|
# The code loads the typemap from the Perl typemap using the loading logic of |
1330
|
|
|
|
|
|
|
# xsubpp. Do note that I made the assumption that |
1331
|
|
|
|
|
|
|
# $Config{}installprivlib}/ExtUtils was the right root directory for the search. |
1332
|
|
|
|
|
|
|
# This could break on some systems? |
1333
|
|
|
|
|
|
|
# |
1334
|
|
|
|
|
|
|
# Also I do _not_ parse the Typemap argument from ExtUtils::MakeMaker because I don't |
1335
|
|
|
|
|
|
|
# know how to catch it here! This would be good to fix! It does look for a file |
1336
|
|
|
|
|
|
|
# called typemap in the current directory however. |
1337
|
|
|
|
|
|
|
# |
1338
|
|
|
|
|
|
|
# The parsing of the typemap is mechanical and taken straight from xsubpp and |
1339
|
|
|
|
|
|
|
# the resulting hash lookup is then used to convert the input type to the |
1340
|
|
|
|
|
|
|
# necessary outputs (as seen in the old code above) |
1341
|
|
|
|
|
|
|
# |
1342
|
|
|
|
|
|
|
# JB 06/05/05 |
1343
|
|
|
|
|
|
|
# |
1344
|
|
|
|
|
|
|
sub typemap { |
1345
|
|
|
|
|
|
|
my $oname = shift; |
1346
|
|
|
|
|
|
|
my $type = shift; |
1347
|
|
|
|
|
|
|
my $arg = shift; |
1348
|
|
|
|
|
|
|
|
1349
|
|
|
|
|
|
|
# |
1350
|
|
|
|
|
|
|
# Modification to parse Perl's typemap here. |
1351
|
|
|
|
|
|
|
# |
1352
|
|
|
|
|
|
|
# The default search path for the typemap taken from xsubpp. It seems it is |
1353
|
|
|
|
|
|
|
# necessary to prepend the installprivlib/ExtUtils directory to find the typemap. |
1354
|
|
|
|
|
|
|
# It is not clear to me how this is to be done. |
1355
|
|
|
|
|
|
|
# |
1356
|
|
|
|
|
|
|
my ($typemap, $mode, $junk, $current, %input_expr, |
1357
|
|
|
|
|
|
|
%proto_letter, %output_expr, %type_kind); |
1358
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
# according to MM_Unix 'privlibexp' is the right directory |
1360
|
|
|
|
|
|
|
# seems to work even on OS X (where installprivlib breaks things) |
1361
|
|
|
|
|
|
|
# if this does not work portably we should split out the typemap finding code |
1362
|
|
|
|
|
|
|
# and make it as complex as necessary + save the typemap location |
1363
|
|
|
|
|
|
|
# in the PDL::Config hash |
1364
|
|
|
|
|
|
|
my $_rootdir = $Config{privlibexp}.'/ExtUtils/'; |
1365
|
|
|
|
|
|
|
# print "_rootdir set to '$_rootdir'\n"; |
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
# First the system typemaps.. |
1368
|
|
|
|
|
|
|
my @tm = ($_rootdir.'../../../../lib/ExtUtils/typemap', |
1369
|
|
|
|
|
|
|
$_rootdir.'../../../lib/ExtUtils/typemap', |
1370
|
|
|
|
|
|
|
$_rootdir.'../../lib/ExtUtils/typemap', |
1371
|
|
|
|
|
|
|
$_rootdir.'../../../typemap', |
1372
|
|
|
|
|
|
|
$_rootdir.'../../typemap', $_rootdir.'../typemap', |
1373
|
|
|
|
|
|
|
$_rootdir.'typemap'); |
1374
|
|
|
|
|
|
|
# Finally tag onto the end, the current directory typemap. Ideally we should here pick |
1375
|
|
|
|
|
|
|
# up the TYPEMAPS flag from ExtUtils::MakeMaker, but a) I don't know how and b) |
1376
|
|
|
|
|
|
|
# it is only a slight inconvenience hopefully! |
1377
|
|
|
|
|
|
|
# |
1378
|
|
|
|
|
|
|
# Note that the OUTPUT typemap is unlikely to be of use here, but I have kept |
1379
|
|
|
|
|
|
|
# the source code from xsubpp for tidiness. |
1380
|
|
|
|
|
|
|
push @tm, 'typemap'; |
1381
|
|
|
|
|
|
|
my $foundtm = 0; |
1382
|
|
|
|
|
|
|
foreach $typemap (@tm) { |
1383
|
|
|
|
|
|
|
next unless -f $typemap ; |
1384
|
|
|
|
|
|
|
# skip directories, binary files etc. |
1385
|
|
|
|
|
|
|
warn("Warning: ignoring non-text typemap file '$typemap'\n"), next |
1386
|
|
|
|
|
|
|
unless -T $typemap ; |
1387
|
|
|
|
|
|
|
$foundtm = 1; |
1388
|
|
|
|
|
|
|
open(TYPEMAP, $typemap) |
1389
|
|
|
|
|
|
|
or warn ("Warning: could not open typemap file '$typemap': $!\n"), next; |
1390
|
|
|
|
|
|
|
$mode = 'Typemap'; |
1391
|
|
|
|
|
|
|
$junk = "" ; |
1392
|
|
|
|
|
|
|
$current = \$junk; |
1393
|
|
|
|
|
|
|
while () { |
1394
|
|
|
|
|
|
|
next if /^\s*#/; |
1395
|
|
|
|
|
|
|
my $line_no = $. + 1; |
1396
|
|
|
|
|
|
|
if (/^INPUT\s*$/) { $mode = 'Input'; $current = \$junk; next; } |
1397
|
|
|
|
|
|
|
if (/^OUTPUT\s*$/) { $mode = 'Output'; $current = \$junk; next; } |
1398
|
|
|
|
|
|
|
if (/^TYPEMAP\s*$/) { $mode = 'Typemap'; $current = \$junk; next; } |
1399
|
|
|
|
|
|
|
if ($mode eq 'Typemap') { |
1400
|
|
|
|
|
|
|
chomp; |
1401
|
|
|
|
|
|
|
my $line = $_ ; |
1402
|
|
|
|
|
|
|
TrimWhitespace($_) ; |
1403
|
|
|
|
|
|
|
# skip blank lines and comment lines |
1404
|
|
|
|
|
|
|
next if /^$/ or /^#/ ; |
1405
|
|
|
|
|
|
|
my($t_type,$kind, $proto) = /^\s*(.*?\S)\s+(\S+)\s*($proto_re*)\s*$/ or |
1406
|
|
|
|
|
|
|
warn("Warning: File '$typemap' Line $. '$line' TYPEMAP entry needs 2 or 3 columns\n"), next; |
1407
|
|
|
|
|
|
|
$t_type = TidyType($t_type) ; |
1408
|
|
|
|
|
|
|
$type_kind{$t_type} = $kind ; |
1409
|
|
|
|
|
|
|
# prototype defaults to '$' |
1410
|
|
|
|
|
|
|
$proto = "\$" unless $proto ; |
1411
|
|
|
|
|
|
|
warn("Warning: File '$typemap' Line $. '$line' Invalid prototype '$proto'\n") |
1412
|
|
|
|
|
|
|
unless ValidProtoString($proto) ; |
1413
|
|
|
|
|
|
|
$proto_letter{$t_type} = C_string($proto) ; |
1414
|
|
|
|
|
|
|
} |
1415
|
|
|
|
|
|
|
elsif (/^\s/) { |
1416
|
|
|
|
|
|
|
$$current .= $_; |
1417
|
|
|
|
|
|
|
} |
1418
|
|
|
|
|
|
|
elsif ($mode eq 'Input') { |
1419
|
|
|
|
|
|
|
s/\s+$//; |
1420
|
|
|
|
|
|
|
$input_expr{$_} = ''; |
1421
|
|
|
|
|
|
|
$current = \$input_expr{$_}; |
1422
|
|
|
|
|
|
|
} |
1423
|
|
|
|
|
|
|
else { |
1424
|
|
|
|
|
|
|
s/\s+$//; |
1425
|
|
|
|
|
|
|
$output_expr{$_} = ''; |
1426
|
|
|
|
|
|
|
$current = \$output_expr{$_}; |
1427
|
|
|
|
|
|
|
} |
1428
|
|
|
|
|
|
|
} |
1429
|
|
|
|
|
|
|
close(TYPEMAP); |
1430
|
|
|
|
|
|
|
} |
1431
|
|
|
|
|
|
|
carp "**CRITICAL** PP found no typemap in $_rootdir/typemap; this will cause problems..." |
1432
|
|
|
|
|
|
|
unless $foundtm; |
1433
|
|
|
|
|
|
|
|
1434
|
|
|
|
|
|
|
# |
1435
|
|
|
|
|
|
|
# Do checks... |
1436
|
|
|
|
|
|
|
# |
1437
|
|
|
|
|
|
|
# First reconstruct the type declaration to look up in type_kind |
1438
|
|
|
|
|
|
|
my $full_type=TidyType($type->get_decl('')); # Skip the variable name |
1439
|
|
|
|
|
|
|
die "The type =$full_type= does not have a typemap entry!\n" unless exists($type_kind{$full_type}); |
1440
|
|
|
|
|
|
|
my $typemap_kind = $type_kind{$full_type}; |
1441
|
|
|
|
|
|
|
# Look up the conversion from the INPUT typemap. Note that we need to do some |
1442
|
|
|
|
|
|
|
# massaging of this. |
1443
|
|
|
|
|
|
|
my $input = $input_expr{$typemap_kind}; |
1444
|
|
|
|
|
|
|
# Remove all before =: |
1445
|
|
|
|
|
|
|
$input =~ s/^(.*?)=\s*//; # This should not be very expensive |
1446
|
|
|
|
|
|
|
# Replace $arg with $arg |
1447
|
|
|
|
|
|
|
$input =~ s/\$arg/$arg/; |
1448
|
|
|
|
|
|
|
# And type with $full_type |
1449
|
|
|
|
|
|
|
$input =~ s/\$type/$full_type/; |
1450
|
|
|
|
|
|
|
|
1451
|
|
|
|
|
|
|
return ($input); |
1452
|
|
|
|
|
|
|
} |
1453
|
|
|
|
|
|
|
|
1454
|
|
|
|
|
|
|
|
1455
|
|
|
|
|
|
|
sub identity2priv { |
1456
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, ' |
1457
|
|
|
|
|
|
|
int i; |
1458
|
|
|
|
|
|
|
$SETNDIMS($PARENT(ndims)); |
1459
|
|
|
|
|
|
|
for(i=0; i<$CHILD(ndims); i++) { |
1460
|
|
|
|
|
|
|
$CHILD(dims[i]) = $PARENT(dims[i]); |
1461
|
|
|
|
|
|
|
} |
1462
|
|
|
|
|
|
|
$SETDIMS(); |
1463
|
|
|
|
|
|
|
$SETDELTATHREADIDS(0); |
1464
|
|
|
|
|
|
|
'); |
1465
|
|
|
|
|
|
|
} |
1466
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
sub pdimexpr2priv { |
1468
|
|
|
|
|
|
|
my($pdimexpr,$hdr,$dimcheck) = @_; |
1469
|
|
|
|
|
|
|
$pdimexpr =~ s/\$CDIM\b/i/g; |
1470
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, ' |
1471
|
|
|
|
|
|
|
int i,cor; |
1472
|
|
|
|
|
|
|
'.$dimcheck.' |
1473
|
|
|
|
|
|
|
$SETNDIMS($PARENT(ndims)); |
1474
|
|
|
|
|
|
|
$DOPRIVDIMS(); |
1475
|
|
|
|
|
|
|
$PRIV(offs) = 0; |
1476
|
|
|
|
|
|
|
for(i=0; i<$CHILD(ndims); i++) { |
1477
|
|
|
|
|
|
|
cor = '.$pdimexpr.'; |
1478
|
|
|
|
|
|
|
$CHILD(dims[i]) = $PARENT(dims[cor]); |
1479
|
|
|
|
|
|
|
$PRIV(incs[i]) = $PARENT(dimincs[cor]); |
1480
|
|
|
|
|
|
|
|
1481
|
|
|
|
|
|
|
} |
1482
|
|
|
|
|
|
|
$SETDIMS(); |
1483
|
|
|
|
|
|
|
$SETDELTATHREADIDS(0); |
1484
|
|
|
|
|
|
|
'); |
1485
|
|
|
|
|
|
|
} |
1486
|
|
|
|
|
|
|
|
1487
|
|
|
|
|
|
|
# something to do with copying values between parent and children |
1488
|
|
|
|
|
|
|
# |
1489
|
|
|
|
|
|
|
# we can NOT assume that PARENT and CHILD have the same type, |
1490
|
|
|
|
|
|
|
# hence the version for bad code |
1491
|
|
|
|
|
|
|
# |
1492
|
|
|
|
|
|
|
# NOTE: we use the same code for 'good' and 'bad' cases - it's |
1493
|
|
|
|
|
|
|
# just that when we use it for 'bad' data, we have to change the |
1494
|
|
|
|
|
|
|
# definition of the EQUIVCPOFFS macro - see the Code rule |
1495
|
|
|
|
|
|
|
# |
1496
|
|
|
|
|
|
|
sub equivcpoffscode { |
1497
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, |
1498
|
|
|
|
|
|
|
'PDL_Indx i; |
1499
|
|
|
|
|
|
|
for(i=0; i<$CHILD_P(nvals); i++) { |
1500
|
|
|
|
|
|
|
$EQUIVCPOFFS(i,i); |
1501
|
|
|
|
|
|
|
}'); |
1502
|
|
|
|
|
|
|
|
1503
|
|
|
|
|
|
|
} # sub: equivcpoffscode() |
1504
|
|
|
|
|
|
|
|
1505
|
|
|
|
|
|
|
# Pars -> ParNames, Parobjs |
1506
|
|
|
|
|
|
|
# |
1507
|
|
|
|
|
|
|
# XXX |
1508
|
|
|
|
|
|
|
# - the need for BadFlag is due to hacked get_xsdatapdecl() |
1509
|
|
|
|
|
|
|
# in PP/PdlParObj and because the PdlParObjs are created by |
1510
|
|
|
|
|
|
|
# PDL::PP::Signature (Doug Burke 07/08/00) |
1511
|
|
|
|
|
|
|
sub Pars_nft { |
1512
|
|
|
|
|
|
|
my($str,$badflag) = @_; |
1513
|
|
|
|
|
|
|
my $sig = PDL::PP::Signature->new($str,$badflag); |
1514
|
|
|
|
|
|
|
return ($sig->names,$sig->objs,1); |
1515
|
|
|
|
|
|
|
} |
1516
|
|
|
|
|
|
|
|
1517
|
|
|
|
|
|
|
# ParNames,Parobjs -> DimObjs |
1518
|
|
|
|
|
|
|
sub ParObjs_DimObjs { |
1519
|
|
|
|
|
|
|
my($pnames,$pobjs) = @_; |
1520
|
|
|
|
|
|
|
my ($dimobjs) = PDL::PP::PdlDimsObj->new(); |
1521
|
|
|
|
|
|
|
for(@$pnames) { |
1522
|
|
|
|
|
|
|
$pobjs->{$_}->add_inds($dimobjs); |
1523
|
|
|
|
|
|
|
} |
1524
|
|
|
|
|
|
|
return ($dimobjs); |
1525
|
|
|
|
|
|
|
} |
1526
|
|
|
|
|
|
|
|
1527
|
|
|
|
|
|
|
# Eliminate whitespace entries |
1528
|
|
|
|
|
|
|
sub nospacesplit {map {/^\s*$/?():$_} split $_[0],$_[1]} |
1529
|
|
|
|
|
|
|
|
1530
|
|
|
|
|
|
|
sub OtherPars_nft { |
1531
|
|
|
|
|
|
|
my($otherpars,$dimobjs) = @_; |
1532
|
|
|
|
|
|
|
my(@names,%types,$type); |
1533
|
|
|
|
|
|
|
# support 'int ndim => n;' syntax |
1534
|
|
|
|
|
|
|
for (nospacesplit ';',$otherpars) { |
1535
|
|
|
|
|
|
|
if (/^\s*([^=]+)\s*=>\s*(\S+)\s*$/) { |
1536
|
|
|
|
|
|
|
my ($ctype,$dim) = ($1,$2); |
1537
|
|
|
|
|
|
|
$ctype =~ s/(\S+)\s+$/$1/; # get rid of trailing ws |
1538
|
|
|
|
|
|
|
print "OtherPars: setting dim '$dim' from '$ctype'\n" if $::PP_VERBOSE; |
1539
|
|
|
|
|
|
|
$type = C::Type->new(undef,$ctype); |
1540
|
|
|
|
|
|
|
croak "can't set unknown dimension" |
1541
|
|
|
|
|
|
|
unless defined($dimobjs->{$dim}); |
1542
|
|
|
|
|
|
|
$dimobjs->{$dim}->set_from($type); |
1543
|
|
|
|
|
|
|
} elsif(/^\s*pdl\s+\*\s*(\w+)$/) { |
1544
|
|
|
|
|
|
|
# It is a piddle -> make it a controlling one. |
1545
|
|
|
|
|
|
|
die("Not supported yet"); |
1546
|
|
|
|
|
|
|
} else { |
1547
|
|
|
|
|
|
|
$type = C::Type->new(undef,$_); |
1548
|
|
|
|
|
|
|
} |
1549
|
|
|
|
|
|
|
my $name = $type->protoname; |
1550
|
|
|
|
|
|
|
if ($name =~ /$INVALID_OTHERPARS_RE/) { |
1551
|
|
|
|
|
|
|
croak "Invalid OtherPars name: $name"; |
1552
|
|
|
|
|
|
|
} |
1553
|
|
|
|
|
|
|
push @names,$name; |
1554
|
|
|
|
|
|
|
$types{$name} = $type; |
1555
|
|
|
|
|
|
|
} |
1556
|
|
|
|
|
|
|
return (\@names,\%types); |
1557
|
|
|
|
|
|
|
} |
1558
|
|
|
|
|
|
|
|
1559
|
|
|
|
|
|
|
sub NXArgs { |
1560
|
|
|
|
|
|
|
my($parnames,$parobjs,$onames,$oobjs) = @_; |
1561
|
|
|
|
|
|
|
my $pdltype = C::Type->new(undef,"pdl *__foo__"); |
1562
|
|
|
|
|
|
|
my $nxargs = [ |
1563
|
|
|
|
|
|
|
( map {[$_,$pdltype]} @$parnames ), |
1564
|
|
|
|
|
|
|
( map {[$_,$oobjs->{$_}]} @$onames ) |
1565
|
|
|
|
|
|
|
]; |
1566
|
|
|
|
|
|
|
return $nxargs; |
1567
|
|
|
|
|
|
|
} |
1568
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
# XXX |
1570
|
|
|
|
|
|
|
# - the need for BadFlag is due to hacked get_xsdatapdecl() |
1571
|
|
|
|
|
|
|
# in PP/PdlParObj and because the PdlParObjs are created by |
1572
|
|
|
|
|
|
|
# PDL::PP::Signature (Doug Burke 07/08/00) |
1573
|
|
|
|
|
|
|
sub NewParentChildPars { |
1574
|
|
|
|
|
|
|
my($p2child,$name,$badflag) = @_; |
1575
|
|
|
|
|
|
|
return (Pars_nft("PARENT(); [oca]CHILD();",$badflag),0,"${name}_NN"); |
1576
|
|
|
|
|
|
|
} |
1577
|
|
|
|
|
|
|
|
1578
|
|
|
|
|
|
|
# XXX |
1579
|
|
|
|
|
|
|
# - the need for BadFlag is due to hacked get_xsdatapdecl() |
1580
|
|
|
|
|
|
|
# in PP/PdlParObj and because the PdlParObjs are created by |
1581
|
|
|
|
|
|
|
# PDL::PP::Signature (Doug Burke 07/08/00) |
1582
|
|
|
|
|
|
|
# |
1583
|
|
|
|
|
|
|
# however, it looks like this isn't being used anymore, |
1584
|
|
|
|
|
|
|
# so commenting out. |
1585
|
|
|
|
|
|
|
# |
1586
|
|
|
|
|
|
|
#sub ParentChildPars { |
1587
|
|
|
|
|
|
|
# my($p2child,$name,$badflag) = @_; |
1588
|
|
|
|
|
|
|
# return (Pars_nft("PARENT(); [oca]CHILD();",$badflag),0,"${name}_XX", |
1589
|
|
|
|
|
|
|
# " |
1590
|
|
|
|
|
|
|
# *$name = \\&PDL::$name; |
1591
|
|
|
|
|
|
|
# sub PDL::$name { |
1592
|
|
|
|
|
|
|
# my \$this = shift; |
1593
|
|
|
|
|
|
|
# my \$foo=\$this->null; |
1594
|
|
|
|
|
|
|
# PDL::${name}_XX(\$this,\$foo,\@_); |
1595
|
|
|
|
|
|
|
# \$foo |
1596
|
|
|
|
|
|
|
# } |
1597
|
|
|
|
|
|
|
# "); |
1598
|
|
|
|
|
|
|
#} |
1599
|
|
|
|
|
|
|
|
1600
|
|
|
|
|
|
|
sub mkstruct { |
1601
|
|
|
|
|
|
|
my($pnames,$pobjs,$comp,$priv,$name) = @_; |
1602
|
|
|
|
|
|
|
my $npdls = $#$pnames+1; |
1603
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, qq{typedef struct $name { |
1604
|
|
|
|
|
|
|
PDL_TRANS_START($npdls); |
1605
|
|
|
|
|
|
|
$priv |
1606
|
|
|
|
|
|
|
$comp |
1607
|
|
|
|
|
|
|
char __ddone; PDL_COMMENT("Dims done") |
1608
|
|
|
|
|
|
|
} $name;}); |
1609
|
|
|
|
|
|
|
} |
1610
|
|
|
|
|
|
|
|
1611
|
|
|
|
|
|
|
sub def_vtable { |
1612
|
|
|
|
|
|
|
my($vname,$sname,$rdname,$rfname,$wfname,$cpfname,$ffname, |
1613
|
|
|
|
|
|
|
$pnames,$pobjs,$affine_ok,$foofname) = @_; |
1614
|
|
|
|
|
|
|
my $nparents = 0 + grep {! $pobjs->{$_}->{FlagW}} @$pnames; |
1615
|
|
|
|
|
|
|
my $aff = ($affine_ok ? "PDL_TPDL_VAFFINE_OK" : 0); |
1616
|
|
|
|
|
|
|
my $npdls = scalar @$pnames; |
1617
|
|
|
|
|
|
|
my $join_flags = join",",map {$pobjs->{$pnames->[$_]}->{FlagPhys} ? |
1618
|
|
|
|
|
|
|
0 : $aff} 0..$npdls-1; |
1619
|
|
|
|
|
|
|
if($Config{cc} eq 'cl') { |
1620
|
|
|
|
|
|
|
$join_flags = '""' if $join_flags eq ''; |
1621
|
|
|
|
|
|
|
} |
1622
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, "static char ${vname}_flags[] = |
1623
|
|
|
|
|
|
|
{ ". $join_flags . "}; |
1624
|
|
|
|
|
|
|
pdl_transvtable $vname = { |
1625
|
|
|
|
|
|
|
0,0, $nparents, $npdls, ${vname}_flags, |
1626
|
|
|
|
|
|
|
$rdname, $rfname, $wfname, |
1627
|
|
|
|
|
|
|
$ffname,NULL,NULL,$cpfname, |
1628
|
|
|
|
|
|
|
sizeof($sname),\"$vname\" |
1629
|
|
|
|
|
|
|
};"); |
1630
|
|
|
|
|
|
|
} |
1631
|
|
|
|
|
|
|
|
1632
|
|
|
|
|
|
|
sub sort_pnobjs { |
1633
|
|
|
|
|
|
|
my($pnames,$pobjs) = @_; |
1634
|
|
|
|
|
|
|
my (@nn); |
1635
|
|
|
|
|
|
|
for(@$pnames) { push ( @nn, $_ ) unless $pobjs->{$_}{FlagW}; } |
1636
|
|
|
|
|
|
|
for(@$pnames) { push ( @nn, $_ ) if $pobjs->{$_}{FlagW}; } |
1637
|
|
|
|
|
|
|
my $no = 0; |
1638
|
|
|
|
|
|
|
for(@nn) { $pobjs->{$_}{Number} = $no++; } |
1639
|
|
|
|
|
|
|
return (\@nn,$pobjs); |
1640
|
|
|
|
|
|
|
} |
1641
|
|
|
|
|
|
|
|
1642
|
|
|
|
|
|
|
# XXX __privtrans explicit :( |
1643
|
|
|
|
|
|
|
sub wrap_vfn { |
1644
|
|
|
|
|
|
|
my($code,$hdrinfo,$rout,$p2child,$name) = @_; |
1645
|
|
|
|
|
|
|
my $type = ($name eq "copy" ? "pdl_trans *" : "void"); |
1646
|
|
|
|
|
|
|
my $sname = $hdrinfo->{StructName}; |
1647
|
|
|
|
|
|
|
my $oargs = ($name eq "foo" ? ",int i1,int i2,int i3" : ""); |
1648
|
|
|
|
|
|
|
|
1649
|
|
|
|
|
|
|
# print "$rout\_$name: $p2child\n"; |
1650
|
|
|
|
|
|
|
my $p2decl = ''; |
1651
|
|
|
|
|
|
|
# Put p2child in simple boolean context rather than strict numerical equality |
1652
|
|
|
|
|
|
|
if ( $p2child ) { |
1653
|
|
|
|
|
|
|
$p2decl = |
1654
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, "pdl *__it = ((pdl_trans_affine *)(__tr))->pdls[1]; pdl *__parent = __tr->pdls[0];"); |
1655
|
|
|
|
|
|
|
if ( $name eq "redodims" ) { |
1656
|
|
|
|
|
|
|
$p2decl .= ' |
1657
|
|
|
|
|
|
|
if (__parent->hdrsv && (__parent->state & PDL_HDRCPY)) { |
1658
|
|
|
|
|
|
|
PDL_COMMENT("call the perl routine _hdr_copy.") |
1659
|
|
|
|
|
|
|
int count; |
1660
|
|
|
|
|
|
|
|
1661
|
|
|
|
|
|
|
dSP; |
1662
|
|
|
|
|
|
|
ENTER ; |
1663
|
|
|
|
|
|
|
SAVETMPS ; |
1664
|
|
|
|
|
|
|
PUSHMARK(SP) ; |
1665
|
|
|
|
|
|
|
XPUSHs( sv_mortalcopy((SV*)__parent->hdrsv) ); |
1666
|
|
|
|
|
|
|
PUTBACK ; |
1667
|
|
|
|
|
|
|
count = call_pv("PDL::_hdr_copy",G_SCALAR); |
1668
|
|
|
|
|
|
|
SPAGAIN ; |
1669
|
|
|
|
|
|
|
if(count != 1) |
1670
|
|
|
|
|
|
|
croak("PDL::_hdr_copy didn\'t return a single value - please report this bug (B)."); |
1671
|
|
|
|
|
|
|
|
1672
|
|
|
|
|
|
|
{ PDL_COMMENT("convenience block for tmp var") |
1673
|
|
|
|
|
|
|
SV *tmp = (SV *) POPs ; |
1674
|
|
|
|
|
|
|
__it->hdrsv = (void*) tmp; |
1675
|
|
|
|
|
|
|
if(tmp != &PL_sv_undef ) |
1676
|
|
|
|
|
|
|
(void)SvREFCNT_inc(tmp); |
1677
|
|
|
|
|
|
|
} |
1678
|
|
|
|
|
|
|
|
1679
|
|
|
|
|
|
|
__it->state |= PDL_HDRCPY; |
1680
|
|
|
|
|
|
|
|
1681
|
|
|
|
|
|
|
FREETMPS ; |
1682
|
|
|
|
|
|
|
LEAVE ; |
1683
|
|
|
|
|
|
|
} |
1684
|
|
|
|
|
|
|
'; |
1685
|
|
|
|
|
|
|
} |
1686
|
|
|
|
|
|
|
} # if: $p2child == 1 |
1687
|
|
|
|
|
|
|
|
1688
|
|
|
|
|
|
|
qq|$type $rout(pdl_trans *__tr $oargs) { |
1689
|
|
|
|
|
|
|
int __dim; |
1690
|
|
|
|
|
|
|
$sname *__privtrans = ($sname *) __tr; |
1691
|
|
|
|
|
|
|
$p2decl |
1692
|
|
|
|
|
|
|
{ |
1693
|
|
|
|
|
|
|
$code |
1694
|
|
|
|
|
|
|
} |
1695
|
|
|
|
|
|
|
} |
1696
|
|
|
|
|
|
|
|; |
1697
|
|
|
|
|
|
|
|
1698
|
|
|
|
|
|
|
} # sub: wrap_vfn() |
1699
|
|
|
|
|
|
|
|
1700
|
|
|
|
|
|
|
sub makesettrans { |
1701
|
|
|
|
|
|
|
my($pnames,$pobjs,$symtab) = @_; |
1702
|
|
|
|
|
|
|
my $trans = $symtab->get_symname('_PDL_ThisTrans'); |
1703
|
|
|
|
|
|
|
my $no=0; |
1704
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, (join '',map { |
1705
|
14
|
|
|
|
|
|
"$trans->pdls[".($no++)."] = $_;\n" |
1706
|
14
|
|
|
|
|
|
} @$pnames). |
1707
|
|
|
|
|
|
|
"PDL->make_trans_mutual((pdl_trans *)$trans);\n"); |
1708
|
|
|
|
|
|
|
} |
1709
|
|
|
|
|
|
|
|
1710
|
|
|
|
|
|
|
sub CopyOtherPars { |
1711
|
|
|
|
|
|
|
my($onames,$otypes,$symtab) = @_; my $repr; |
1712
|
|
|
|
|
|
|
my $sname = $symtab->get_symname('_PDL_ThisTrans'); |
1713
|
|
|
|
|
|
|
for(@$onames) { |
1714
|
|
|
|
|
|
|
$repr .= $otypes->{$_}->get_copy("$_","$sname->$_"); |
1715
|
|
|
|
|
|
|
} |
1716
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $repr); |
1717
|
|
|
|
|
|
|
} |
1718
|
|
|
|
|
|
|
|
1719
|
|
|
|
|
|
|
sub mkxscat { |
1720
|
|
|
|
|
|
|
my($glb,$xs_c_headers,$hdr,@bits) = @_; |
1721
|
|
|
|
|
|
|
my($boot,$prelude,$str); |
1722
|
|
|
|
|
|
|
if($glb) { |
1723
|
|
|
|
|
|
|
$prelude = join '' => ($xs_c_headers->[0], @bits, $xs_c_headers->[1]); |
1724
|
|
|
|
|
|
|
$boot = $xs_c_headers->[3]; |
1725
|
|
|
|
|
|
|
$str = "$hdr\n"; |
1726
|
|
|
|
|
|
|
} else { |
1727
|
|
|
|
|
|
|
my $xscode = join '' => @bits; |
1728
|
|
|
|
|
|
|
$str = "$hdr CODE:\n { $xscode XSRETURN(0);\n}\n\n"; |
1729
|
|
|
|
|
|
|
} |
1730
|
|
|
|
|
|
|
$str =~ s/(\s*\n)+/\n/g; |
1731
|
|
|
|
|
|
|
(PDL::PP::pp_line_numbers(__LINE__, $str),$boot,$prelude) |
1732
|
|
|
|
|
|
|
} |
1733
|
|
|
|
|
|
|
|
1734
|
|
|
|
|
|
|
sub mkVarArgsxscat { |
1735
|
|
|
|
|
|
|
my($glb,$xs_c_headers,$hdr,@bits) = @_; |
1736
|
|
|
|
|
|
|
my($boot,$prelude,$str); |
1737
|
|
|
|
|
|
|
if($glb) { |
1738
|
|
|
|
|
|
|
$prelude = join '' => ($xs_c_headers->[0], @bits, $xs_c_headers->[1]); |
1739
|
|
|
|
|
|
|
$boot = $xs_c_headers->[3]; |
1740
|
|
|
|
|
|
|
$str = "$hdr\n"; |
1741
|
|
|
|
|
|
|
} else { |
1742
|
|
|
|
|
|
|
my $xscode = join '' => @bits; |
1743
|
|
|
|
|
|
|
$str = "$hdr \n { $xscode \n}\n\n"; |
1744
|
|
|
|
|
|
|
} |
1745
|
|
|
|
|
|
|
$str =~ s/(\s*\n)+/\n/g; |
1746
|
|
|
|
|
|
|
(PDL::PP::pp_line_numbers(__LINE__, $str),$boot,$prelude) |
1747
|
|
|
|
|
|
|
} |
1748
|
|
|
|
|
|
|
|
1749
|
|
|
|
|
|
|
|
1750
|
|
|
|
|
|
|
sub MakeNows { |
1751
|
|
|
|
|
|
|
my($pnames, $symtab) = @_; |
1752
|
|
|
|
|
|
|
my $str = "\n"; |
1753
|
|
|
|
|
|
|
for(@$pnames) { $str .= "$_ = PDL->make_now($_);\n"; } |
1754
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $str); |
1755
|
|
|
|
|
|
|
} |
1756
|
|
|
|
|
|
|
|
1757
|
|
|
|
|
|
|
sub Sym2Loc { PDL::PP::pp_line_numbers(__LINE__, $_[0]->decl_locals()) } |
1758
|
|
|
|
|
|
|
|
1759
|
|
|
|
|
|
|
sub MkPrivStructInit { |
1760
|
|
|
|
|
|
|
my( $symtab, $vtable, $affflag, $nopdlthread ) = @_; |
1761
|
|
|
|
|
|
|
my $sname = $symtab->get_symname('_PDL_ThisTrans'); |
1762
|
|
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
my $ci = ' '; |
1764
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, |
1765
|
14
|
|
|
|
|
|
"\n${ci}$sname = malloc(sizeof(*$sname)); memset($sname, 0, sizeof(*$sname));\n" . |
1766
|
14
|
|
|
|
|
|
($nopdlthread ? "" : "${ci}PDL_THR_CLRMAGIC(&$sname->__pdlthread);\n") . |
1767
|
14
|
|
|
|
|
|
"${ci}PDL_TR_SETMAGIC($sname);\n" . |
1768
|
14
|
|
|
|
|
|
"${ci}$sname->flags = $affflag;\n" . |
1769
|
14
|
|
|
|
|
|
"${ci}$sname->__ddone = 0;\n" . |
1770
|
14
|
|
|
|
|
|
"${ci}$sname->vtable = &$vtable;\n" . |
1771
|
14
|
|
|
|
|
|
"${ci}$sname->freeproc = PDL->trans_mallocfreeproc;\n") |
1772
|
|
|
|
|
|
|
|
1773
|
|
|
|
|
|
|
} # sub: MkPrivStructInit() |
1774
|
|
|
|
|
|
|
|
1775
|
|
|
|
|
|
|
sub MkDefSyms { |
1776
|
|
|
|
|
|
|
return SymTab->new( |
1777
|
|
|
|
|
|
|
_PDL_ThisTrans => ["__privtrans",C::Type->new(undef,"$_[0] *foo")], |
1778
|
|
|
|
|
|
|
); |
1779
|
|
|
|
|
|
|
} |
1780
|
|
|
|
|
|
|
|
1781
|
|
|
|
|
|
|
sub AddArgsyms { |
1782
|
|
|
|
|
|
|
my($symtab,$args) = @_; |
1783
|
|
|
|
|
|
|
$symtab->add_params( |
1784
|
|
|
|
|
|
|
map {($_->[0],$_->[0])} @$args |
1785
|
|
|
|
|
|
|
); |
1786
|
|
|
|
|
|
|
return $symtab; |
1787
|
|
|
|
|
|
|
} |
1788
|
|
|
|
|
|
|
|
1789
|
|
|
|
|
|
|
sub indent($$) { |
1790
|
|
|
|
|
|
|
my ($text,$ind) = @_; |
1791
|
|
|
|
|
|
|
$text =~ s/^(.*)$/$ind$1/mg; |
1792
|
|
|
|
|
|
|
return $text; |
1793
|
|
|
|
|
|
|
} |
1794
|
|
|
|
|
|
|
|
1795
|
|
|
|
|
|
|
# This subroutine generates the XS code needed to call the perl 'initialize' |
1796
|
|
|
|
|
|
|
# routine in order to create new output PDLs |
1797
|
|
|
|
|
|
|
sub callPerlInit { |
1798
|
|
|
|
|
|
|
my $names = shift; # names of variables to initialize |
1799
|
|
|
|
|
|
|
my $ci = shift; # current indenting |
1800
|
|
|
|
|
|
|
my $callcopy = $#_ > -1 ? shift : 0; |
1801
|
|
|
|
|
|
|
my $ret = ''; |
1802
|
|
|
|
|
|
|
|
1803
|
|
|
|
|
|
|
foreach my $name (@$names) { |
1804
|
|
|
|
|
|
|
unless ($callcopy) { $ret .= << "EOC"} |
1805
|
|
|
|
|
|
|
|
1806
|
|
|
|
|
|
|
if (strcmp(objname,"PDL") == 0) { PDL_COMMENT("shortcut if just PDL") |
1807
|
|
|
|
|
|
|
$name\_SV = sv_newmortal(); |
1808
|
|
|
|
|
|
|
$name = PDL->null(); |
1809
|
|
|
|
|
|
|
PDL->SetSV_PDL($name\_SV,$name); |
1810
|
|
|
|
|
|
|
if (bless_stash) $name\_SV = sv_bless($name\_SV, bless_stash); |
1811
|
|
|
|
|
|
|
} else { |
1812
|
|
|
|
|
|
|
PUSHMARK(SP); |
1813
|
|
|
|
|
|
|
XPUSHs(sv_2mortal(newSVpv(objname, 0))); |
1814
|
|
|
|
|
|
|
PUTBACK; |
1815
|
|
|
|
|
|
|
perl_call_method(\"initialize\", G_SCALAR); |
1816
|
|
|
|
|
|
|
SPAGAIN; |
1817
|
|
|
|
|
|
|
$name\_SV = POPs; |
1818
|
|
|
|
|
|
|
PUTBACK; |
1819
|
|
|
|
|
|
|
$name = PDL->SvPDLV($name\_SV); |
1820
|
|
|
|
|
|
|
} |
1821
|
|
|
|
|
|
|
|
1822
|
|
|
|
|
|
|
EOC |
1823
|
|
|
|
|
|
|
|
1824
|
|
|
|
|
|
|
else { $ret .= << "EOD" } |
1825
|
|
|
|
|
|
|
|
1826
|
|
|
|
|
|
|
if (strcmp(objname,"PDL") == 0) { PDL_COMMENT("shortcut if just PDL") |
1827
|
|
|
|
|
|
|
$name\_SV = sv_newmortal(); |
1828
|
|
|
|
|
|
|
$name = PDL->null(); |
1829
|
|
|
|
|
|
|
PDL->SetSV_PDL($name\_SV,$name); |
1830
|
|
|
|
|
|
|
if (bless_stash) $name\_SV = sv_bless($name\_SV, bless_stash); |
1831
|
|
|
|
|
|
|
} else { |
1832
|
|
|
|
|
|
|
/* XXX should these commented lines be removed? See also a 8 lines down */ |
1833
|
|
|
|
|
|
|
/* warn("possibly relying on deprecated automatic copy call in derived class\n") |
1834
|
|
|
|
|
|
|
warn("please modify your initialize method to avoid future problems\n"); |
1835
|
|
|
|
|
|
|
*/ |
1836
|
|
|
|
|
|
|
PUSHMARK(SP); |
1837
|
|
|
|
|
|
|
XPUSHs(parent); |
1838
|
|
|
|
|
|
|
PUTBACK; |
1839
|
|
|
|
|
|
|
perl_call_method(\"copy\", G_SCALAR); |
1840
|
|
|
|
|
|
|
/* perl_call_method(\"initialize\", G_SCALAR); */ |
1841
|
|
|
|
|
|
|
SPAGAIN; |
1842
|
|
|
|
|
|
|
$name\_SV = POPs; |
1843
|
|
|
|
|
|
|
PUTBACK; |
1844
|
|
|
|
|
|
|
$name = PDL->SvPDLV($name\_SV); |
1845
|
|
|
|
|
|
|
} |
1846
|
|
|
|
|
|
|
EOD |
1847
|
|
|
|
|
|
|
|
1848
|
|
|
|
|
|
|
} # doreach: $name |
1849
|
|
|
|
|
|
|
|
1850
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, indent($ret,$ci)); |
1851
|
|
|
|
|
|
|
|
1852
|
0
|
0
|
|
|
|
|
} #sub callPerlInit() |
1853
|
0
|
|
|
|
|
|
|
1854
|
0
|
|
|
|
|
|
# This subroutine is called when no 'otherpars' exist. |
1855
|
|
|
|
|
|
|
# This writes an XS header which handles variable argument lists, |
1856
|
|
|
|
|
|
|
# thus avoiding the perl layer in calling the routine. D. Hunt 4/11/00 |
1857
|
|
|
|
|
|
|
# |
1858
|
|
|
|
|
|
|
# The use of 'DO NOT SET!!' looks ugly. |
1859
|
|
|
|
|
|
|
# |
1860
|
|
|
|
|
|
|
# Removing useless use of hasp2child in this function. DCM Sept 12, 2011 |
1861
|
|
|
|
|
|
|
sub VarArgsXSHdr { |
1862
|
|
|
|
|
|
|
my($name,$xsargs,$parobjs,$optypes,#$hasp2child, |
1863
|
|
|
|
|
|
|
$pmcode,$hdrcode,$inplacecode,$globalnew,$callcopy,$bitwise) = @_; |
1864
|
|
|
|
|
|
|
|
1865
|
|
|
|
|
|
|
# Don't do var args processing if the user has pre-defined pmcode |
1866
|
|
|
|
|
|
|
return 'DO NOT SET!!' if ($pmcode); |
1867
|
|
|
|
|
|
|
|
1868
|
|
|
|
|
|
|
# don't generate a HDR if globalnew is set |
1869
|
|
|
|
|
|
|
# globalnew implies internal usage, not XS |
1870
|
|
|
|
|
|
|
return undef if $globalnew; |
1871
|
|
|
|
|
|
|
|
1872
|
|
|
|
|
|
|
my $ci = ' '; # current indenting |
1873
|
|
|
|
|
|
|
my $pars = join "\n",map {$ci.$_->[1]->get_decl($_->[0]).";"} @$xsargs; |
1874
|
|
|
|
|
|
|
|
1875
|
|
|
|
|
|
|
my @args = map { $_->[0] } @$xsargs; |
1876
|
|
|
|
|
|
|
my %out = map { $_ => exists($$parobjs{$_}) |
1877
|
|
|
|
|
|
|
&& exists($$parobjs{$_}{FlagOut}) |
1878
|
|
|
|
|
|
|
&& !exists($$parobjs{$_}{FlagCreateAlways})} |
1879
|
|
|
|
|
|
|
@args; |
1880
|
|
|
|
|
|
|
my %outca = map { $_ => exists($$parobjs{$_}) |
1881
|
|
|
|
|
|
|
&& exists($$parobjs{$_}{FlagOut}) |
1882
|
|
|
|
|
|
|
&& exists($$parobjs{$_}{FlagCreateAlways})} |
1883
|
|
|
|
|
|
|
@args; |
1884
|
|
|
|
|
|
|
my %tmp = map { $_ => exists($$parobjs{$_}) && exists($$parobjs{$_}{FlagTemp}) } @args; |
1885
|
|
|
|
|
|
|
my %other = map { $_ => exists($$optypes{$_}) } @args; |
1886
|
|
|
|
|
|
|
|
1887
|
|
|
|
|
|
|
# remember, othervars *are* input vars |
1888
|
|
|
|
|
|
|
my $nout = (grep { $_ } values %out); |
1889
|
|
|
|
|
|
|
my $noutca = (grep { $_ } values %outca); |
1890
|
|
|
|
|
|
|
my $nother = (grep { $_ } values %other); |
1891
|
|
|
|
|
|
|
my $ntmp = (grep { $_ } values %tmp); |
1892
|
|
|
|
|
|
|
my $ntot = @args; |
1893
|
|
|
|
|
|
|
my $nmaxonstack = $ntot - $noutca; |
1894
|
|
|
|
|
|
|
my $nin = $ntot - ($nout + $noutca + $ntmp); |
1895
|
|
|
|
|
|
|
my $ninout = $nin + $nout; |
1896
|
|
|
|
|
|
|
my $nallout = $nout + $noutca; |
1897
|
|
|
|
|
|
|
my $usageargs = join (",", @args); |
1898
|
|
|
|
|
|
|
|
1899
|
|
|
|
|
|
|
$ci = ' '; # Current indenting |
1900
|
|
|
|
|
|
|
|
1901
|
|
|
|
|
|
|
# Generate declarations for SV * variables corresponding to pdl * output variables. |
1902
|
|
|
|
|
|
|
# These are used in creating output and temp variables. One variable (ex: SV * outvar1_SV;) |
1903
|
|
|
|
|
|
|
# is needed for each output and output create always argument |
1904
|
|
|
|
|
|
|
my $svdecls = join ("\n", map { "${ci}SV *${_}_SV;" } grep { $out{$_} || $outca{$_} || $tmp{$_} } @args); |
1905
|
|
|
|
|
|
|
|
1906
|
|
|
|
|
|
|
my @create = (); # The names of variables which need to be created by calling |
1907
|
|
|
|
|
|
|
# the 'initialize' perl routine from the correct package. |
1908
|
|
|
|
|
|
|
|
1909
|
|
|
|
|
|
|
$ci = ' '; # Current indenting |
1910
|
|
|
|
|
|
|
|
1911
|
|
|
|
|
|
|
# clause for reading in all variables |
1912
|
|
|
|
|
|
|
my $clause1 = ''; my $cnt = 0; |
1913
|
|
|
|
|
|
|
foreach my $i ( 0 .. $#args ) { |
1914
|
|
|
|
|
|
|
my $x = $args[$i]; |
1915
|
|
|
|
|
|
|
if ($other{$x}) { # other par |
1916
|
|
|
|
|
|
|
$clause1 .= "$ci$x = " . typemap($x, $$optypes{$x}, "ST($cnt)") . ";\n"; |
1917
|
|
|
|
|
|
|
$cnt++; |
1918
|
|
|
|
|
|
|
} elsif ($outca{$x}) { |
1919
|
|
|
|
|
|
|
push (@create, $x); |
1920
|
|
|
|
|
|
|
} else { |
1921
|
|
|
|
|
|
|
$clause1 .= "$ci$x = PDL->SvPDLV(ST($cnt));\n"; |
1922
|
|
|
|
|
|
|
$cnt++; |
1923
|
|
|
|
|
|
|
} |
1924
|
|
|
|
|
|
|
} |
1925
|
|
|
|
|
|
|
|
1926
|
|
|
|
|
|
|
# Add code for creating output variables via call to 'initialize' perl routine |
1927
|
|
|
|
|
|
|
$clause1 .= callPerlInit (\@create, $ci, $callcopy); |
1928
|
|
|
|
|
|
|
@create = (); |
1929
|
|
|
|
|
|
|
|
1930
|
|
|
|
|
|
|
# clause for reading in input and output vars and creating temps |
1931
|
|
|
|
|
|
|
my $clause2; |
1932
|
|
|
|
|
|
|
# skip this clause if there are no temps |
1933
|
|
|
|
|
|
|
if ($nmaxonstack == $ninout) { |
1934
|
|
|
|
|
|
|
$clause2 = ''; |
1935
|
|
|
|
|
|
|
} else { |
1936
|
|
|
|
|
|
|
$clause2 = "\n else if (items == $ninout) { PDL_COMMENT(\"all but temps on stack, read in output, create temps\")" . |
1937
|
|
|
|
|
|
|
" nreturn = $noutca;\n"; |
1938
|
|
|
|
|
|
|
|
1939
|
|
|
|
|
|
|
$cnt = 0; |
1940
|
|
|
|
|
|
|
foreach my $i ( 0 .. $#args ) { |
1941
|
|
|
|
|
|
|
my $x = $args[$i]; |
1942
|
|
|
|
|
|
|
if ($other{$x}) { |
1943
|
|
|
|
|
|
|
$clause2 .= "$ci$x = " . typemap($x, $$optypes{$x}, "ST($cnt)") . ";\n"; |
1944
|
|
|
|
|
|
|
$cnt++; |
1945
|
|
|
|
|
|
|
} elsif ($tmp{$x} || $outca{$x}) { |
1946
|
|
|
|
|
|
|
# a temporary or always create variable |
1947
|
|
|
|
|
|
|
push (@create, $x); |
1948
|
|
|
|
|
|
|
} else { # an input or output variable |
1949
|
|
|
|
|
|
|
$clause2 .= "$ci$x = PDL->SvPDLV(ST($cnt));\n"; |
1950
|
|
|
|
|
|
|
$cnt++; |
1951
|
|
|
|
|
|
|
} |
1952
|
|
|
|
|
|
|
} |
1953
|
|
|
|
|
|
|
|
1954
|
|
|
|
|
|
|
# Add code for creating output variables via call to 'initialize' perl routine |
1955
|
|
|
|
|
|
|
$clause2 .= callPerlInit (\@create, $ci, $callcopy); |
1956
|
|
|
|
|
|
|
$clause2 .= "}\n"; |
1957
|
|
|
|
|
|
|
@create = (); |
1958
|
|
|
|
|
|
|
|
1959
|
|
|
|
|
|
|
} |
1960
|
|
|
|
|
|
|
|
1961
|
|
|
|
|
|
|
# clause for reading in input and creating output and temp vars |
1962
|
|
|
|
|
|
|
my $clause3 = ''; |
1963
|
|
|
|
|
|
|
$cnt = 0; |
1964
|
|
|
|
|
|
|
foreach my $i ( 0 .. $#args ) { |
1965
|
|
|
|
|
|
|
my $x = $args[$i]; |
1966
|
|
|
|
|
|
|
if ($other{$x}) { |
1967
|
|
|
|
|
|
|
$clause3 .= "$ci$x = " . typemap($x, $$optypes{$x}, "ST($cnt)") . ";\n"; |
1968
|
|
|
|
|
|
|
$cnt++; |
1969
|
|
|
|
|
|
|
} elsif ($out{$x} || $tmp{$x} || $outca{$x}) { |
1970
|
|
|
|
|
|
|
push (@create, $x); |
1971
|
|
|
|
|
|
|
} else { |
1972
|
|
|
|
|
|
|
$clause3 .= "$ci$x = PDL->SvPDLV(ST($cnt));\n"; |
1973
|
|
|
|
|
|
|
$cnt++; |
1974
|
|
|
|
|
|
|
} |
1975
|
|
|
|
|
|
|
} |
1976
|
|
|
|
|
|
|
|
1977
|
|
|
|
|
|
|
# Add code for creating output variables via call to 'initialize' perl routine |
1978
|
|
|
|
|
|
|
$clause3 .= callPerlInit (\@create, $ci, $callcopy); @create = (); |
1979
|
|
|
|
|
|
|
|
1980
|
|
|
|
|
|
|
# Bitwise ops may get five args |
1981
|
|
|
|
|
|
|
my $bitwise_cond = $bitwise ? " || items == 5" : ''; |
1982
|
|
|
|
|
|
|
|
1983
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, <
|
1984
|
|
|
|
|
|
|
|
1985
|
|
|
|
|
|
|
void |
1986
|
14
|
|
|
|
|
|
$name(...) |
1987
|
|
|
|
|
|
|
PREINIT: |
1988
|
14
|
|
|
|
|
|
char *objname = "PDL"; /* XXX maybe that class should actually depend on the value set |
1989
|
|
|
|
|
|
|
by pp_bless ? (CS) */ |
1990
|
|
|
|
|
|
|
HV *bless_stash = 0; |
1991
|
14
|
|
|
|
|
|
SV *parent = 0; |
1992
|
|
|
|
|
|
|
int nreturn; |
1993
|
|
|
|
|
|
|
$svdecls |
1994
|
|
|
|
|
|
|
$pars |
1995
|
|
|
|
|
|
|
|
1996
|
|
|
|
|
|
|
PPCODE: |
1997
|
|
|
|
|
|
|
|
1998
|
|
|
|
|
|
|
{ |
1999
|
|
|
|
|
|
|
PDL_COMMENT("Check if you can get a package name for this input value. ") |
2000
|
|
|
|
|
|
|
PDL_COMMENT("It can be either a PDL (SVt_PVMG) or a hash which is a ") |
2001
|
|
|
|
|
|
|
PDL_COMMENT("derived PDL subclass (SVt_PVHV) ") |
2002
|
|
|
|
|
|
|
|
2003
|
|
|
|
|
|
|
if (SvROK(ST(0)) && ((SvTYPE(SvRV(ST(0))) == SVt_PVMG) || (SvTYPE(SvRV(ST(0))) == SVt_PVHV))) { |
2004
|
|
|
|
|
|
|
parent = ST(0); |
2005
|
|
|
|
|
|
|
if (sv_isobject(parent)){ |
2006
|
|
|
|
|
|
|
bless_stash = SvSTASH(SvRV(ST(0))); |
2007
|
|
|
|
|
|
|
objname = HvNAME((bless_stash)); PDL_COMMENT("The package to bless output vars into is taken from the first input var") |
2008
|
|
|
|
|
|
|
} |
2009
|
|
|
|
|
|
|
} |
2010
|
|
|
|
|
|
|
if (items == $nmaxonstack) { PDL_COMMENT("all variables on stack, read in output and temp vars") |
2011
|
|
|
|
|
|
|
nreturn = $noutca; |
2012
|
|
|
|
|
|
|
$clause1 |
2013
|
|
|
|
|
|
|
} |
2014
|
|
|
|
|
|
|
$clause2 |
2015
|
|
|
|
|
|
|
else if (items == $nin$bitwise_cond) { PDL_COMMENT("only input variables on stack, create outputs and temps") |
2016
|
|
|
|
|
|
|
nreturn = $nallout; |
2017
|
|
|
|
|
|
|
$clause3 |
2018
|
|
|
|
|
|
|
} |
2019
|
|
|
|
|
|
|
|
2020
|
|
|
|
|
|
|
else { |
2021
|
|
|
|
|
|
|
croak (\"Usage: PDL::$name($usageargs) (you may leave temporaries or output variables out of list)\"); |
2022
|
|
|
|
|
|
|
} |
2023
|
|
|
|
|
|
|
} |
2024
|
|
|
|
|
|
|
{ |
2025
|
|
|
|
|
|
|
$hdrcode |
2026
|
|
|
|
|
|
|
$inplacecode |
2027
|
|
|
|
|
|
|
} |
2028
|
|
|
|
|
|
|
END |
2029
|
|
|
|
|
|
|
|
2030
|
|
|
|
|
|
|
} # sub: VarArgsXSHdr() |
2031
|
|
|
|
|
|
|
|
2032
|
|
|
|
|
|
|
# This subroutine produces the code which returns output variables |
2033
|
|
|
|
|
|
|
# or leaves them as modified input variables. D. Hunt 4/10/00 |
2034
|
|
|
|
|
|
|
sub VarArgsXSReturn { |
2035
|
|
|
|
|
|
|
my($xsargs, $parobjs, $globalnew ) = @_; |
2036
|
|
|
|
|
|
|
|
2037
|
|
|
|
|
|
|
# don't generate a HDR if globalnew is set |
2038
|
|
|
|
|
|
|
# globalnew implies internal usage, not XS |
2039
|
|
|
|
|
|
|
return undef if $globalnew; |
2040
|
|
|
|
|
|
|
|
2041
|
|
|
|
|
|
|
# names of output variables (in calling order) |
2042
|
|
|
|
|
|
|
my @outs; |
2043
|
|
|
|
|
|
|
|
2044
|
|
|
|
|
|
|
# beware of existance tests like this: $$parobjs{$arg->[0]}{FlagOut} ! |
2045
|
|
|
|
|
|
|
# this will cause $$parobjs{$arg->[0]} to spring into existance even if $$parobjs{$arg->[0]}{FlagOut} |
2046
|
|
|
|
|
|
|
# does not exist!! |
2047
|
|
|
|
|
|
|
foreach my $arg (@$xsargs) { |
2048
|
|
|
|
|
|
|
my $x = $arg->[0]; |
2049
|
|
|
|
|
|
|
push (@outs, $x) if (exists ($$parobjs{$x}) and exists ($$parobjs{$x}{FlagOut})); |
2050
|
|
|
|
|
|
|
} |
2051
|
|
|
|
|
|
|
|
2052
|
|
|
|
|
|
|
my $ci = ' '; # Current indenting |
2053
|
|
|
|
|
|
|
|
2054
|
|
|
|
|
|
|
my $clause1 = ''; |
2055
|
|
|
|
|
|
|
foreach my $i ( 0 .. $#outs ) { |
2056
|
|
|
|
|
|
|
$clause1 .= ($ci x 2) . "ST($i) = $outs[$i]_SV;\n"; |
2057
|
|
|
|
|
|
|
} |
2058
|
|
|
|
|
|
|
|
2059
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, <<"END") |
2060
|
8
|
50
|
|
|
|
|
${ci}if (nreturn) { |
2061
|
0
|
0
|
|
|
|
|
${ci} if (nreturn > 0) EXTEND (SP, nreturn ); |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
2062
|
0
|
|
|
|
|
|
$clause1 |
2063
|
|
|
|
|
|
|
${ci} XSRETURN(nreturn); |
2064
|
8
|
|
|
|
|
|
${ci}} else { |
2065
|
|
|
|
|
|
|
${ci} XSRETURN(0); |
2066
|
|
|
|
|
|
|
${ci}} |
2067
|
|
|
|
|
|
|
END |
2068
|
|
|
|
|
|
|
|
2069
|
|
|
|
|
|
|
} # sub: VarArgsXSReturn() |
2070
|
|
|
|
|
|
|
|
2071
|
|
|
|
|
|
|
|
2072
|
|
|
|
|
|
|
sub XSCHdrs { |
2073
|
|
|
|
|
|
|
my($name,$pars,$gname) = @_; |
2074
|
|
|
|
|
|
|
# Hmmm, do we need $shortpars at all? |
2075
|
|
|
|
|
|
|
#my $shortpars = join ',',map {$_->[0]} @$pars; |
2076
|
|
|
|
|
|
|
my $longpars = join ",",map {$_->[1]->get_decl($_->[0])} @$pars; |
2077
|
|
|
|
|
|
|
return ["void $name($longpars) {","}","", |
2078
|
|
|
|
|
|
|
"PDL->$gname = $name;"]; |
2079
|
|
|
|
|
|
|
} |
2080
|
|
|
|
|
|
|
|
2081
|
|
|
|
|
|
|
# abstract the access to the bad value status |
2082
|
|
|
|
|
|
|
# - means we can easily change the representation without too |
2083
|
|
|
|
|
|
|
# many changes |
2084
|
|
|
|
|
|
|
# |
2085
|
|
|
|
|
|
|
# it's also used in one place in PP/PDLCode.pm |
2086
|
|
|
|
|
|
|
# -- there it's hard-coded |
2087
|
|
|
|
|
|
|
# |
2088
|
|
|
|
|
|
|
sub set_badflag { PDL::PP::pp_line_numbers(__LINE__, '$PRIV(bvalflag) = 1;' . "\n") } |
2089
|
0
|
|
|
|
|
|
sub clear_badflag { PDL::PP::pp_line_numbers(__LINE__, '$PRIV(bvalflag) = 0;' . "\n") } |
2090
|
14
|
|
|
|
|
|
sub get_badflag { PDL::PP::pp_line_numbers(__LINE__, '$PRIV(bvalflag)') } |
2091
|
|
|
|
|
|
|
|
2092
|
|
|
|
|
|
|
sub get_badflag_priv { PDL::PP::pp_line_numbers(__LINE__, '$PRIV(bvalflag)') } |
2093
|
|
|
|
|
|
|
|
2094
|
|
|
|
|
|
|
sub set_badstate { |
2095
|
|
|
|
|
|
|
my $pdl = shift; |
2096
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, "\$SETPDLSTATEBAD($pdl)") |
2097
|
|
|
|
|
|
|
} |
2098
|
|
|
|
|
|
|
|
2099
|
|
|
|
|
|
|
sub clear_badstate { |
2100
|
|
|
|
|
|
|
my $pdl = shift; |
2101
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, "\$SETPDLSTATEGOOD($pdl)") |
2102
|
|
|
|
|
|
|
} |
2103
|
|
|
|
|
|
|
|
2104
|
|
|
|
|
|
|
sub get_badstate { |
2105
|
|
|
|
|
|
|
my $pdl = shift; |
2106
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, "\$ISPDLSTATEBAD($pdl)") |
2107
|
|
|
|
|
|
|
} |
2108
|
|
|
|
|
|
|
|
2109
|
|
|
|
|
|
|
# checks the input piddles to see if the routine |
2110
|
|
|
|
|
|
|
# is being any data containing bad values |
2111
|
|
|
|
|
|
|
# |
2112
|
|
|
|
|
|
|
# if FindBadStatusCode is set, use it, |
2113
|
|
|
|
|
|
|
# otherwise create the code automatically. |
2114
|
|
|
|
|
|
|
# |
2115
|
|
|
|
|
|
|
# - in the automatic code creation, |
2116
|
|
|
|
|
|
|
# if $badflag is 0, rather than being undefined, then |
2117
|
|
|
|
|
|
|
# we issue a warning if any piddles contain bad values |
2118
|
|
|
|
|
|
|
# (and set the bvalflag to 0) |
2119
|
|
|
|
|
|
|
# |
2120
|
|
|
|
|
|
|
# XXX it looks like output piddles are included in the |
2121
|
|
|
|
|
|
|
# check. I *think* this is just wasted code, but I'm |
2122
|
|
|
|
|
|
|
# not sure. |
2123
|
|
|
|
|
|
|
# |
2124
|
|
|
|
|
|
|
sub findbadstatus { |
2125
|
|
|
|
|
|
|
my ( $badflag, $badcode, $xsargs, $parobjs, $optypes, $symtab, $name ) = @_; |
2126
|
|
|
|
|
|
|
return '' unless $bvalflag; |
2127
|
|
|
|
|
|
|
|
2128
|
|
|
|
|
|
|
return PDL::PP::pp_line_numbers(__LINE__, $badcode) if defined $badcode; |
2129
|
|
|
|
|
|
|
|
2130
|
|
|
|
|
|
|
my $sname = $symtab->get_symname('_PDL_ThisTrans'); |
2131
|
|
|
|
|
|
|
|
2132
|
|
|
|
|
|
|
my @args = map { $_->[0] } @$xsargs; |
2133
|
|
|
|
|
|
|
my %out = map { |
2134
|
|
|
|
|
|
|
$_ => |
2135
|
|
|
|
|
|
|
exists($$parobjs{$_}) && exists($$parobjs{$_}{FlagOut}) |
2136
|
|
|
|
|
|
|
&& !exists($$parobjs{$_}{FlagCreateAlways}) |
2137
|
|
|
|
|
|
|
} @args; |
2138
|
|
|
|
|
|
|
my %outca = map { |
2139
|
|
|
|
|
|
|
$_ => |
2140
|
|
|
|
|
|
|
exists($$parobjs{$_}) && exists($$parobjs{$_}{FlagOut}) |
2141
|
|
|
|
|
|
|
&& exists($$parobjs{$_}{FlagCreateAlways}) |
2142
|
|
|
|
|
|
|
} @args; |
2143
|
|
|
|
|
|
|
my %tmp = map { |
2144
|
|
|
|
|
|
|
$_ => |
2145
|
|
|
|
|
|
|
exists($$parobjs{$_}) && exists($$parobjs{$_}{FlagTemp}) |
2146
|
|
|
|
|
|
|
} @args; |
2147
|
|
|
|
|
|
|
my %other = map { $_ => exists($$optypes{$_}) } @args; |
2148
|
|
|
|
|
|
|
|
2149
|
|
|
|
|
|
|
my $clear_bad = clear_badflag(); |
2150
|
|
|
|
|
|
|
my $set_bad = set_badflag(); |
2151
|
|
|
|
|
|
|
my $get_bad = get_badflag(); |
2152
|
|
|
|
|
|
|
|
2153
|
|
|
|
|
|
|
my $str = $clear_bad; |
2154
|
|
|
|
|
|
|
|
2155
|
|
|
|
|
|
|
# set the badflag_cache variable if any input piddle has the bad flag set |
2156
|
|
|
|
|
|
|
# |
2157
|
|
|
|
|
|
|
my $add = 0; |
2158
|
|
|
|
|
|
|
my $badflag_str = " \$BADFLAGCACHE() = "; |
2159
|
|
|
|
|
|
|
foreach my $i ( 0 .. $#args ) { |
2160
|
|
|
|
|
|
|
my $x = $args[$i]; |
2161
|
|
|
|
|
|
|
unless ( $other{$x} or $out{$x} or $tmp{$x} or $outca{$x}) { |
2162
|
|
|
|
|
|
|
if ($add) { $badflag_str .= " || "; } |
2163
|
|
|
|
|
|
|
else { $add = 1; } |
2164
|
|
|
|
|
|
|
$badflag_str .= get_badstate($args[$i]); |
2165
|
|
|
|
|
|
|
} |
2166
|
|
|
|
|
|
|
} |
2167
|
|
|
|
|
|
|
|
2168
|
|
|
|
|
|
|
# It is possible, at present, for $add to be 0. I think this is when |
2169
|
|
|
|
|
|
|
# the routine has no input piddles, such as fibonacci in primitive.pd, |
2170
|
|
|
|
|
|
|
# but there may be other cases. These routines could/should (?) |
2171
|
|
|
|
|
|
|
# be marked as NoBadCode to avoid this, or maybe the code here made |
2172
|
|
|
|
|
|
|
# smarter. Left as is for now as do not want to add instability into |
2173
|
|
|
|
|
|
|
# the 2.4.3 release if I can help it - DJB 23 Jul 2006 |
2174
|
|
|
|
|
|
|
# |
2175
|
|
|
|
|
|
|
if ($add != 0) { |
2176
|
|
|
|
|
|
|
$str .= $badflag_str . ";\n if (\$BADFLAGCACHE()) ${set_bad}\n"; |
2177
|
|
|
|
|
|
|
} else { |
2178
|
|
|
|
|
|
|
print "\nNOTE: $name has no input bad piddles.\n\n" if $::PP_VERBOSE; |
2179
|
|
|
|
|
|
|
} |
2180
|
|
|
|
|
|
|
|
2181
|
|
|
|
|
|
|
if ( defined($badflag) and $badflag == 0 ) { |
2182
|
|
|
|
|
|
|
$str .= |
2183
|
|
|
|
|
|
|
" if ( $get_bad ) { |
2184
|
|
|
|
|
|
|
printf(\"WARNING: $name does not handle bad values.\\n\"); |
2185
|
|
|
|
|
|
|
$clear_bad |
2186
|
|
|
|
|
|
|
}\n"; |
2187
|
|
|
|
|
|
|
print "\nNOTE: $name does not handle bad values.\n\n" if $::PP_VERBOSE; |
2188
|
|
|
|
|
|
|
} # if: $badflag |
2189
|
|
|
|
|
|
|
|
2190
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $str) |
2191
|
|
|
|
|
|
|
|
2192
|
|
|
|
|
|
|
} # sub: findbadstatus |
2193
|
|
|
|
|
|
|
|
2194
|
|
|
|
|
|
|
|
2195
|
|
|
|
|
|
|
# copies over the bad value state to the output piddles |
2196
|
|
|
|
|
|
|
# |
2197
|
|
|
|
|
|
|
# if CopyBadStatusCode is set, use it, |
2198
|
|
|
|
|
|
|
# otherwise create the code automatically. |
2199
|
|
|
|
|
|
|
# |
2200
|
|
|
|
|
|
|
# note: this is executed before the trans_mutual call |
2201
|
|
|
|
|
|
|
# is made, since the state may be changed by the |
2202
|
|
|
|
|
|
|
# Code section |
2203
|
|
|
|
|
|
|
# |
2204
|
|
|
|
|
|
|
sub copybadstatus { |
2205
|
|
|
|
|
|
|
my ( $badflag, $badcode, $xsargs, $parobjs, $symtab ) = @_; |
2206
|
|
|
|
|
|
|
## return '' unless $bvalflag or $badflag == 0; |
2207
|
|
|
|
|
|
|
return '' unless $bvalflag; |
2208
|
|
|
|
|
|
|
|
2209
|
|
|
|
|
|
|
if (defined $badcode) { |
2210
|
|
|
|
|
|
|
# realised in 2.4.3 testing that use of $PRIV at this stage is |
2211
|
|
|
|
|
|
|
# dangerous since it may have been freed. So I introduced the |
2212
|
|
|
|
|
|
|
# $BFLACACHE variable which stores the $PRIV(bvalflag) value |
2213
|
|
|
|
|
|
|
# for use here. |
2214
|
|
|
|
|
|
|
# For now make the substitution automatic but it will likely become an |
2215
|
|
|
|
|
|
|
# error to use $PRIV(bvalflag) here. |
2216
|
|
|
|
|
|
|
# |
2217
|
|
|
|
|
|
|
if ($badcode =~ m/\$PRIV(bvalflag)/) { |
2218
|
|
|
|
|
|
|
$badcode =~ s/\$PRIV(bvalflag)/\$BADFLAGCACHE()/; |
2219
|
|
|
|
|
|
|
print "\nPDL::PP WARNING: copybadstatus contains '\$PRIV(bvalflag)'; replace with \$BADFLAGCACHE()\n\n"; |
2220
|
|
|
|
|
|
|
} |
2221
|
|
|
|
|
|
|
return PDL::PP::pp_line_numbers(__LINE__, $badcode); |
2222
|
|
|
|
|
|
|
} |
2223
|
|
|
|
|
|
|
|
2224
|
|
|
|
|
|
|
# names of output variables (in calling order) |
2225
|
|
|
|
|
|
|
my @outs; |
2226
|
|
|
|
|
|
|
|
2227
|
|
|
|
|
|
|
# beware of existance tests like this: $$parobjs{$arg->[0]}{FlagOut} ! |
2228
|
|
|
|
|
|
|
# this will cause $$parobjs{$arg->[0]} to spring into existance even if $$parobjs{$arg->[0]}{FlagOut} |
2229
|
|
|
|
|
|
|
# does not exist!! |
2230
|
|
|
|
|
|
|
foreach my $arg (@$xsargs) { |
2231
|
|
|
|
|
|
|
my $x = $arg->[0]; |
2232
|
|
|
|
|
|
|
push (@outs, $x) if (exists ($$parobjs{$x}) and exists ($$parobjs{$x}{FlagOut})); |
2233
|
|
|
|
|
|
|
} |
2234
|
|
|
|
|
|
|
|
2235
|
|
|
|
|
|
|
my $sname = $symtab->get_symname('_PDL_ThisTrans'); |
2236
|
|
|
|
|
|
|
my $str = ''; |
2237
|
|
|
|
|
|
|
|
2238
|
|
|
|
|
|
|
# It appears that some code in Bad.xs sets the cache value but then |
2239
|
|
|
|
|
|
|
# this bit of code never gets called. Is this an efficiency issue (ie |
2240
|
|
|
|
|
|
|
# should we try and optimise away those ocurrences) or does it perform |
2241
|
|
|
|
|
|
|
# some purpose? |
2242
|
|
|
|
|
|
|
# |
2243
|
|
|
|
|
|
|
$str = "if (\$BADFLAGCACHE()) {\n"; |
2244
|
|
|
|
|
|
|
foreach my $arg ( @outs ) { |
2245
|
|
|
|
|
|
|
$str .= " " . set_badstate($arg) . ";\n"; |
2246
|
|
|
|
|
|
|
} |
2247
|
|
|
|
|
|
|
$str .= "}\n"; |
2248
|
|
|
|
|
|
|
|
2249
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $str); |
2250
|
|
|
|
|
|
|
|
2251
|
|
|
|
|
|
|
} # sub: copybadstatus() |
2252
|
|
|
|
|
|
|
|
2253
|
|
|
|
|
|
|
# insert code, after the autogenerated xs argument processing code |
2254
|
|
|
|
|
|
|
# produced by VarArgsXSHdr and AFTER any in HdrCode |
2255
|
|
|
|
|
|
|
# - this code flags the routine as working inplace, |
2256
|
|
|
|
|
|
|
# |
2257
|
|
|
|
|
|
|
# Inplace can be supplied several values |
2258
|
|
|
|
|
|
|
# => 1 |
2259
|
|
|
|
|
|
|
# assumes fn has an inout and output piddle (eg 'a(); [o] b();') |
2260
|
|
|
|
|
|
|
# |
2261
|
|
|
|
|
|
|
# => [ 'a' ] |
2262
|
|
|
|
|
|
|
# assumes several input piddles in sig, so 'a' labels which |
2263
|
|
|
|
|
|
|
# one is to be marked inplace |
2264
|
|
|
|
|
|
|
# |
2265
|
|
|
|
|
|
|
# => [ 'a', 'b' ] |
2266
|
|
|
|
|
|
|
# input piddle is a(), output pidle is 'b' |
2267
|
|
|
|
|
|
|
# |
2268
|
|
|
|
|
|
|
sub InplaceCode { |
2269
|
|
|
|
|
|
|
my ( $ppname, $xsargs, $parobjs, $arg ) = @_; |
2270
|
|
|
|
|
|
|
return '' unless defined $arg; |
2271
|
|
|
|
|
|
|
|
2272
|
|
|
|
|
|
|
# find input and output piddles |
2273
|
|
|
|
|
|
|
my ( @in, @out ); |
2274
|
|
|
|
|
|
|
foreach my $arg (@$xsargs) { |
2275
|
|
|
|
|
|
|
my $name = $arg->[0]; |
2276
|
|
|
|
|
|
|
if ( exists $$parobjs{$name} ) { |
2277
|
|
|
|
|
|
|
if ( exists $$parobjs{$name}{FlagOut} ) { |
2278
|
|
|
|
|
|
|
push @out, $name; |
2279
|
|
|
|
|
|
|
} elsif ( ! exists $$parobjs{$name}{FlagTemp} ) { |
2280
|
|
|
|
|
|
|
push @in, $name; |
2281
|
|
|
|
|
|
|
} |
2282
|
|
|
|
|
|
|
} |
2283
|
|
|
|
|
|
|
} |
2284
|
|
|
|
|
|
|
|
2285
|
|
|
|
|
|
|
# handle different values of arg |
2286
|
|
|
|
|
|
|
my ( $in, $out ); |
2287
|
|
|
|
|
|
|
|
2288
|
|
|
|
|
|
|
# default vals - only set if we have one input/output piddle |
2289
|
|
|
|
|
|
|
$in = $in[0] if $#in == 0; |
2290
|
|
|
|
|
|
|
$out = $out[0] if $#out == 0; |
2291
|
|
|
|
|
|
|
|
2292
|
|
|
|
|
|
|
if ( ref($arg) eq "ARRAY" ) { |
2293
|
|
|
|
|
|
|
my $narg = $#$arg; |
2294
|
|
|
|
|
|
|
if ( $narg > -1 ) { |
2295
|
|
|
|
|
|
|
$in = $$arg[0]; |
2296
|
|
|
|
|
|
|
$out = $$arg[1] if $narg > 0; |
2297
|
|
|
|
|
|
|
} |
2298
|
|
|
|
|
|
|
} elsif ( ref($arg) eq "" ) { |
2299
|
|
|
|
|
|
|
return '' unless $arg; |
2300
|
|
|
|
|
|
|
# use default values |
2301
|
|
|
|
|
|
|
} else { |
2302
|
|
|
|
|
|
|
die "ERROR: Inplace rule [$ppname] must be sent either an array ref or a scalar.\n"; |
2303
|
|
|
|
|
|
|
} |
2304
|
|
|
|
|
|
|
|
2305
|
|
|
|
|
|
|
die "ERROR: Inplace [$ppname] does not know name of input piddle\n" |
2306
|
|
|
|
|
|
|
unless defined $in; |
2307
|
|
|
|
|
|
|
die "ERROR: Inplace [$ppname] does not know name of output piddle\n" |
2308
|
|
|
|
|
|
|
unless defined $out; |
2309
|
|
|
|
|
|
|
|
2310
|
|
|
|
|
|
|
my $instate = $in . "->state"; |
2311
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, |
2312
|
|
|
|
|
|
|
qq{\tif ( $instate & PDL_INPLACE && ($out != $in)) { |
2313
|
|
|
|
|
|
|
$instate &= ~PDL_INPLACE; PDL_COMMENT("unset") |
2314
|
|
|
|
|
|
|
$out = $in; PDL_COMMENT("discard output value, leak ?") |
2315
|
|
|
|
|
|
|
PDL->SetSV_PDL(${out}_SV,${out}); |
2316
|
|
|
|
|
|
|
}}) |
2317
|
|
|
|
|
|
|
|
2318
|
|
|
|
|
|
|
} # sub: InplaceCode |
2319
|
|
|
|
|
|
|
|
2320
|
|
|
|
|
|
|
# If there is an EquivCPOffsCOde and: |
2321
|
|
|
|
|
|
|
# no bad-value support ==> use that |
2322
|
|
|
|
|
|
|
# bad value support ==> write a bit of code that does |
2323
|
|
|
|
|
|
|
# if ( $PRIV(bvalflag) ) { bad-EquivCPOffsCode } |
2324
|
|
|
|
|
|
|
# else { good-EquivCPOffsCode } |
2325
|
|
|
|
|
|
|
# |
2326
|
|
|
|
|
|
|
# Note: since EquivCPOffsCOde doesn't (or I haven't seen any that |
2327
|
|
|
|
|
|
|
# do) use 'loop %{' or 'threadloop %{', we can't rely on |
2328
|
|
|
|
|
|
|
# PDLCode to automatically write code like above, hence the |
2329
|
|
|
|
|
|
|
# explicit definition here. |
2330
|
|
|
|
|
|
|
# |
2331
|
|
|
|
|
|
|
# Note: I *assume* that bad-Equiv..Code == good-Equiv..Code *EXCEPT* |
2332
|
|
|
|
|
|
|
# that we re-define the meaning of the $EQUIVCPOFFS macro to |
2333
|
|
|
|
|
|
|
# check for bad values when copying things over. |
2334
|
|
|
|
|
|
|
# This means having to write less code. |
2335
|
|
|
|
|
|
|
# |
2336
|
|
|
|
|
|
|
# Since PARENT & CHILD need NOT be the same type we cannot just copy |
2337
|
|
|
|
|
|
|
# values from one to the other - we have to check for the presence |
2338
|
|
|
|
|
|
|
# of bad values, hence the expansion for the $bad code |
2339
|
|
|
|
|
|
|
# |
2340
|
|
|
|
|
|
|
# Some operators (notably range) also have an out-of-range flag; they use |
2341
|
|
|
|
|
|
|
# the macro EQUIVCPTRUNC instead of EQUIVCPOFFS. |
2342
|
|
|
|
|
|
|
# $EQUIVCPTRUNC does the same as EQUIVCPOFFS but accepts a child-out-of-bounds |
2343
|
|
|
|
|
|
|
# flag. If the out-of-bounds flag is set, the forward code puts BAD/0 into |
2344
|
|
|
|
|
|
|
# the child, and reverse code refrains from copying. |
2345
|
|
|
|
|
|
|
# --CED 27-Jan-2003 |
2346
|
|
|
|
|
|
|
# |
2347
|
|
|
|
|
|
|
# sent [EquivCPOffsCode,BadFlag] |
2348
|
|
|
|
|
|
|
|
2349
|
|
|
|
|
|
|
# |
2350
|
|
|
|
|
|
|
# NOTE: EQUIVCPOFFS and EQUIVCPTRUNC both suffer from the macro-block |
2351
|
|
|
|
|
|
|
# wart of C preprocessing. They look like statements but sometimes |
2352
|
|
|
|
|
|
|
# process into blocks, so if/then/else constructs can get broken. |
2353
|
|
|
|
|
|
|
# Either (1) use blocks for if/then/else, or (2) get excited and |
2354
|
|
|
|
|
|
|
# use the "do {BLOCK} while(0)" block-to-statement conversion construct |
2355
|
|
|
|
|
|
|
# in the substitution. I'm too Lazy. --CED 27-Jan-2003 |
2356
|
|
|
|
|
|
|
# |
2357
|
|
|
|
|
|
|
sub CodefromEquivCPOffsCode { |
2358
|
|
|
|
|
|
|
my $good = shift; |
2359
|
|
|
|
|
|
|
my $bflag = shift; |
2360
|
|
|
|
|
|
|
|
2361
|
|
|
|
|
|
|
my $bad = $good; |
2362
|
|
|
|
|
|
|
|
2363
|
|
|
|
|
|
|
# parse 'good' code |
2364
|
|
|
|
|
|
|
$good =~ s/\$EQUIVCPOFFS\(([^()]+),([^()]+)\)/\$PP(CHILD)[$1] = \$PP(PARENT)[$2]/g; |
2365
|
|
|
|
|
|
|
$good =~ s/\$EQUIVCPTRUNC\(([^()]+),([^()]+),([^()]+)\)/\$PP(CHILD)[$1] = ($3) ? 0 : \$PP(PARENT)[$2]/g; |
2366
|
|
|
|
|
|
|
|
2367
|
|
|
|
|
|
|
my $str = $good; |
2368
|
|
|
|
|
|
|
|
2369
|
|
|
|
|
|
|
if ( defined $bflag and $bflag ) { |
2370
|
|
|
|
|
|
|
# parse 'bad' code |
2371
|
|
|
|
|
|
|
$bad =~ s/\$EQUIVCPOFFS\(([^()]+),([^()]+)\)/if( \$PPISBAD(PARENT,[$2]) ) { \$PPSETBAD(CHILD,[$1]); } else { \$PP(CHILD)[$1] = \$PP(PARENT)[$2]; }/g; |
2372
|
|
|
|
|
|
|
$bad =~ s/\$EQUIVCPTRUNC\(([^()]+),([^()]+),([^()]+)\)/ if( ($3) || \$PPISBAD(PARENT,[$2]) ) { \$PPSETBAD(CHILD,[$1]); } else {\$PP(CHILD)[$1] = \$PP(PARENT)[$2]; }/g; |
2373
|
|
|
|
|
|
|
|
2374
|
|
|
|
|
|
|
$str = 'if( $PRIV(bvalflag) ) { ' . $bad . ' } else { ' . $good . '}'; |
2375
|
|
|
|
|
|
|
} |
2376
|
|
|
|
|
|
|
|
2377
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $str); |
2378
|
|
|
|
|
|
|
|
2379
|
|
|
|
|
|
|
} # sub: CodefromEquivCPOffsCode |
2380
|
|
|
|
|
|
|
|
2381
|
|
|
|
|
|
|
# this just reverses PARENT & CHILD in the expansion of |
2382
|
|
|
|
|
|
|
# the $EQUIVCPOFFS macro (ie compared to CodefromEquivCPOffsCode) |
2383
|
|
|
|
|
|
|
# |
2384
|
|
|
|
|
|
|
sub BackCodefromEquivCPOffsCode { |
2385
|
|
|
|
|
|
|
my $good = shift; |
2386
|
|
|
|
|
|
|
my $bflag = shift; |
2387
|
|
|
|
|
|
|
|
2388
|
|
|
|
|
|
|
my $bad = $good; |
2389
|
|
|
|
|
|
|
|
2390
|
|
|
|
|
|
|
# parse 'good' code |
2391
|
|
|
|
|
|
|
$good =~ s/\$EQUIVCPOFFS\(([^()]+),([^()]+)\)/\$PP(PARENT)[$2] = \$PP(CHILD)[$1]/g; |
2392
|
|
|
|
|
|
|
$good =~ s/\$EQUIVCPTRUNC\(([^()]+),([^()]+),([^()]+)\)/if(!($3)) \$PP(PARENT)[$2] = \$PP(CHILD)[$1] /g; |
2393
|
|
|
|
|
|
|
|
2394
|
|
|
|
|
|
|
my $str = $good; |
2395
|
|
|
|
|
|
|
|
2396
|
|
|
|
|
|
|
if ( defined $bflag and $bflag ) { |
2397
|
|
|
|
|
|
|
# parse 'bad' code |
2398
|
|
|
|
|
|
|
$bad =~ s/\$EQUIVCPOFFS\(([^()]+),([^()]+)\)/if( \$PPISBAD(CHILD,[$1]) ) { \$PPSETBAD(PARENT,[$2]); } else { \$PP(PARENT)[$2] = \$PP(CHILD)[$1]; }/g; |
2399
|
|
|
|
|
|
|
$bad =~ s/\$EQUIVCPTRUNC\(([^()]+),([^()]+),([^()]+)\)/if(!($3)) { if( \$PPISBAD(CHILD,[$1]) ) { \$PPSETBAD(PARENT,[$2]); } else { \$PP(PARENT)[$2] = \$PP(CHILD)[$1]; } } /g; |
2400
|
|
|
|
|
|
|
|
2401
|
|
|
|
|
|
|
$str = 'if ( $PRIV(bvalflag) ) { ' . $bad . ' } else { ' . $good . '}'; |
2402
|
|
|
|
|
|
|
} |
2403
|
|
|
|
|
|
|
|
2404
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $str); |
2405
|
|
|
|
|
|
|
|
2406
|
|
|
|
|
|
|
} # sub: BackCodefromEquivCPOffsCode |
2407
|
|
|
|
|
|
|
|
2408
|
|
|
|
|
|
|
sub GenDocs { |
2409
|
|
|
|
|
|
|
my ($name,$pars,$otherpars,$doc,$baddoc) = @_; |
2410
|
|
|
|
|
|
|
|
2411
|
|
|
|
|
|
|
# Allow explcit non-doc using Doc=>undef |
2412
|
|
|
|
|
|
|
|
2413
|
|
|
|
|
|
|
return '' if $doc eq '' && (!defined $doc) && $doc==undef; |
2414
|
|
|
|
|
|
|
return '' if $doc =~ /^\s*internal\s*$/i; |
2415
|
|
|
|
|
|
|
|
2416
|
|
|
|
|
|
|
# remove any 'bad' documentation if we're not compiling support |
2417
|
|
|
|
|
|
|
$baddoc = undef unless $bvalflag; |
2418
|
|
|
|
|
|
|
|
2419
|
|
|
|
|
|
|
# If the doc string is one line let's have to for the |
2420
|
|
|
|
|
|
|
# reference card information as well |
2421
|
|
|
|
|
|
|
my @splitRes; # temp split variable to get rid of |
2422
|
|
|
|
|
|
|
# 'implicit split to @_ is deprecated' messages |
2423
|
|
|
|
|
|
|
$doc = "=for ref\n\n".$doc if( scalar(@splitRes = split("\n", $doc)) <= 1); |
2424
|
|
|
|
|
|
|
|
2425
|
|
|
|
|
|
|
$::DOCUMENTED++; |
2426
|
|
|
|
|
|
|
$pars = "P(); C()" unless $pars; |
2427
|
|
|
|
|
|
|
# Strip leading whitespace and trailing semicolons and whitespace |
2428
|
|
|
|
|
|
|
$pars =~ s/^\s*(.+[^;])[;\s]*$/$1/; |
2429
|
|
|
|
|
|
|
$otherpars =~ s/^\s*(.+[^;])[;\s]*$/$1/ if $otherpars; |
2430
|
|
|
|
|
|
|
my $sig = "$pars".( $otherpars ? "; $otherpars" : ""); |
2431
|
|
|
|
|
|
|
|
2432
|
|
|
|
|
|
|
$doc =~ s/\n(=cut\s*\n)+(\s*\n)*$/\n/m; # Strip extra =cut's |
2433
|
|
|
|
|
|
|
if ( defined $baddoc ) { |
2434
|
|
|
|
|
|
|
# Strip leading newlines and any =cut markings |
2435
|
|
|
|
|
|
|
$baddoc =~ s/\n(=cut\s*\n)+(\s*\n)*$/\n/m; |
2436
|
|
|
|
|
|
|
$baddoc =~ s/^\n+//; |
2437
|
|
|
|
|
|
|
$baddoc = "=for bad\n\n$baddoc"; |
2438
|
|
|
|
|
|
|
} |
2439
|
|
|
|
|
|
|
|
2440
|
|
|
|
|
|
|
my $baddoc_function_pod = <<"EOD" ; |
2441
|
|
|
|
|
|
|
|
2442
|
|
|
|
|
|
|
XXX=head2 $name |
2443
|
|
|
|
|
|
|
|
2444
|
|
|
|
|
|
|
XXX=for sig |
2445
|
|
|
|
|
|
|
|
2446
|
|
|
|
|
|
|
Signature: ($sig) |
2447
|
|
|
|
|
|
|
|
2448
|
|
|
|
|
|
|
$doc |
2449
|
|
|
|
|
|
|
|
2450
|
|
|
|
|
|
|
$baddoc |
2451
|
|
|
|
|
|
|
|
2452
|
|
|
|
|
|
|
XXX=cut |
2453
|
|
|
|
|
|
|
|
2454
|
|
|
|
|
|
|
EOD |
2455
|
|
|
|
|
|
|
|
2456
|
|
|
|
|
|
|
$baddoc_function_pod =~ s/^XXX=/=/gms; |
2457
|
|
|
|
|
|
|
return $baddoc_function_pod; |
2458
|
|
|
|
|
|
|
} |
2459
|
|
|
|
|
|
|
|
2460
|
|
|
|
|
|
|
sub ToIsReversible { |
2461
|
|
|
|
|
|
|
my($rev) = @_; |
2462
|
|
|
|
|
|
|
if($rev eq "1") { |
2463
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, '$SETREVERSIBLE(1)') |
2464
|
|
|
|
|
|
|
} else { |
2465
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $rev) |
2466
|
|
|
|
|
|
|
} |
2467
|
|
|
|
|
|
|
} |
2468
|
|
|
|
|
|
|
|
2469
|
|
|
|
|
|
|
sub make_newcoerce { |
2470
|
|
|
|
|
|
|
my($ftypes) = @_; |
2471
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, join '',map { |
2472
|
|
|
|
|
|
|
"$_->datatype = $ftypes->{$_}; " |
2473
|
|
|
|
|
|
|
} keys %$ftypes); |
2474
|
|
|
|
|
|
|
} |
2475
|
|
|
|
|
|
|
|
2476
|
|
|
|
|
|
|
# Assuming that, if HASP2Child is true, we only have |
2477
|
|
|
|
|
|
|
# PARENT; CHILD parameters, so we can just take the |
2478
|
|
|
|
|
|
|
# datatype to be that of PARENT (which is set up by |
2479
|
|
|
|
|
|
|
# find_datatype()). Little bit complicated because |
2480
|
|
|
|
|
|
|
# we need to set CHILD's datatype under certain |
2481
|
|
|
|
|
|
|
# circumstances |
2482
|
|
|
|
|
|
|
# |
2483
|
|
|
|
|
|
|
sub coerce_types { |
2484
|
|
|
|
|
|
|
my($parnames,$parobjs,$ignore,$newstab,$hasp2child) = @_; |
2485
|
|
|
|
|
|
|
|
2486
|
|
|
|
|
|
|
# assume [oca]CHILD();, although there might be an ignore |
2487
|
|
|
|
|
|
|
if ( $hasp2child ) { |
2488
|
|
|
|
|
|
|
my $child = $$parnames[1]; |
2489
|
|
|
|
|
|
|
return "" if $ignore->{$child}; |
2490
|
|
|
|
|
|
|
|
2491
|
|
|
|
|
|
|
die "ERROR: expected $child to be [oca]\n" |
2492
|
|
|
|
|
|
|
unless $parobjs->{$child}{FlagCreateAlways}; |
2493
|
|
|
|
|
|
|
|
2494
|
|
|
|
|
|
|
return PDL::PP::pp_line_numbers(__LINE__, "$child\->datatype = \$PRIV(__datatype);\n$child\->has_badvalue = \$PRIV(has_badvalue);\n$child\->badvalue = \$PRIV(badvalue);\n"); |
2495
|
|
|
|
|
|
|
} |
2496
|
|
|
|
|
|
|
|
2497
|
|
|
|
|
|
|
my $str = ""; |
2498
|
|
|
|
|
|
|
foreach ( @$parnames ) { |
2499
|
|
|
|
|
|
|
next if $ignore->{$_}; |
2500
|
|
|
|
|
|
|
|
2501
|
|
|
|
|
|
|
my $po = $parobjs->{$_}; |
2502
|
|
|
|
|
|
|
|
2503
|
|
|
|
|
|
|
my $dtype; |
2504
|
|
|
|
|
|
|
if ( $po->{FlagTyped} ) { |
2505
|
|
|
|
|
|
|
$dtype = $po->cenum(); |
2506
|
|
|
|
|
|
|
$dtype = "PDLMAX($dtype,\$PRIV(__datatype))" |
2507
|
|
|
|
|
|
|
if $po->{FlagTplus}; |
2508
|
|
|
|
|
|
|
} else { |
2509
|
|
|
|
|
|
|
$dtype = "\$PRIV(__datatype)"; |
2510
|
|
|
|
|
|
|
} |
2511
|
|
|
|
|
|
|
|
2512
|
|
|
|
|
|
|
if ( $po->{FlagCreateAlways} ) { |
2513
|
|
|
|
|
|
|
$str .= "$_->datatype = $dtype; "; |
2514
|
|
|
|
|
|
|
} else { |
2515
|
|
|
|
|
|
|
$str .= |
2516
|
|
|
|
|
|
|
"if( ($_->state & PDL_NOMYDIMS) && $_->trans == NULL ) { |
2517
|
|
|
|
|
|
|
$_->datatype = $dtype; |
2518
|
|
|
|
|
|
|
} else " |
2519
|
|
|
|
|
|
|
if $po->{FlagCreat}; |
2520
|
|
|
|
|
|
|
$str .= "if($dtype != $_->datatype) { |
2521
|
|
|
|
|
|
|
$_ = PDL->get_convertedpdl($_,$dtype); |
2522
|
|
|
|
|
|
|
}"; |
2523
|
|
|
|
|
|
|
} |
2524
|
|
|
|
|
|
|
} # foreach: @$parnames |
2525
|
|
|
|
|
|
|
|
2526
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $str); |
2527
|
14
|
50
|
|
|
|
|
} # sub: coerce_types() |
2528
|
0
|
|
|
|
|
|
|
2529
|
|
|
|
|
|
|
# First, finds the greatest datatype, then, if not supported, takes |
2530
|
|
|
|
|
|
|
# the largest type supported by the function. |
2531
|
|
|
|
|
|
|
# Not yet optimal. |
2532
|
|
|
|
|
|
|
# |
2533
|
|
|
|
|
|
|
# Assuming that, if HASP2Child is true, we only have |
2534
|
|
|
|
|
|
|
# PARENT; CHILD parameters, so we can just take the |
2535
|
|
|
|
|
|
|
# datatype to be that of PARENT (see also coerce_types()) |
2536
|
|
|
|
|
|
|
# |
2537
|
|
|
|
|
|
|
sub find_datatype { |
2538
|
|
|
|
|
|
|
my($parnames,$parobjs,$ignore,$newstab,$gentypes,$hasp2child) = @_; |
2539
|
|
|
|
|
|
|
|
2540
|
|
|
|
|
|
|
my $dtype = "\$PRIV(__datatype)"; |
2541
|
|
|
|
|
|
|
|
2542
|
|
|
|
|
|
|
# TODO XXX |
2543
|
|
|
|
|
|
|
# the check can probably be removed, but left in since I don't know |
2544
|
|
|
|
|
|
|
# what I'm doing (DJB) |
2545
|
|
|
|
|
|
|
die "ERROR: gentypes != $ntypes with p2child\n" |
2546
|
|
|
|
|
|
|
if $hasp2child and $#$gentypes != $ntypes; |
2547
|
|
|
|
|
|
|
|
2548
|
|
|
|
|
|
|
return "$dtype = $$parnames[0]\->datatype;\n\$PRIV(has_badvalue) = $$parnames[0]\->has_badvalue;\n\$PRIV(badvalue) = $$parnames[0]\->badvalue;\n" |
2549
|
|
|
|
|
|
|
if $hasp2child; |
2550
|
|
|
|
|
|
|
|
2551
|
|
|
|
|
|
|
my $str = "$dtype = 0;"; |
2552
|
|
|
|
|
|
|
foreach ( @$parnames ) { |
2553
|
|
|
|
|
|
|
my $po = $parobjs->{$_}; |
2554
|
|
|
|
|
|
|
next if $ignore->{$_} or $po->{FlagTyped} or $po->{FlagCreateAlways}; |
2555
|
|
|
|
|
|
|
|
2556
|
|
|
|
|
|
|
$str .= "if("; |
2557
|
|
|
|
|
|
|
$str .= "!(($_->state & PDL_NOMYDIMS) && |
2558
|
|
|
|
|
|
|
$_->trans == NULL) && " |
2559
|
|
|
|
|
|
|
if $po->{FlagCreat}; |
2560
|
|
|
|
|
|
|
$str .= "$dtype < $_->datatype) { |
2561
|
|
|
|
|
|
|
$dtype = $_->datatype; |
2562
|
|
|
|
|
|
|
}\n"; |
2563
|
|
|
|
|
|
|
} # foreach: @$parnames |
2564
|
|
|
|
|
|
|
|
2565
|
|
|
|
|
|
|
$str .= join '', map { "if($dtype == PDL_$_) {}\nelse " }(@$gentypes); |
2566
|
|
|
|
|
|
|
|
2567
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $str .= "$dtype = PDL_$gentypes->[-1];\n"); |
2568
|
14
|
50
|
|
|
|
|
} # sub: find_datatype() |
2569
|
14
|
|
|
|
|
|
|
2570
|
|
|
|
|
|
|
sub NT2Decls_p {&NT2Decls__({ToPtrs=>1},@_);} |
2571
|
14
|
50
|
|
|
|
|
|
2572
|
14
|
50
|
|
|
|
|
sub NT2Copies_p {&NT2Copies__({ToPtrs=>1},@_);} |
2573
|
14
|
50
|
|
|
|
|
|
2574
|
14
|
50
|
|
|
|
|
sub NT2Free_p {&NT2Free__({ToPtrs=>1},@_);} |
2575
|
14
|
50
|
|
|
|
|
|
2576
|
14
|
50
|
|
|
|
|
sub NT2Decls {&NT2Decls__({},@_);} |
2577
|
14
|
50
|
|
|
|
|
|
2578
|
14
|
50
|
|
|
|
|
sub NT2Decls__ { |
2579
|
0
|
|
|
|
|
|
my($opts,$onames,$otypes) = @_; |
2580
|
|
|
|
|
|
|
my $decl; |
2581
|
|
|
|
|
|
|
my $dopts = {}; |
2582
|
|
|
|
|
|
|
$dopts->{VarArrays2Ptrs} = 1 if $opts->{ToPtrs}; |
2583
|
|
|
|
|
|
|
for(@$onames) { |
2584
|
|
|
|
|
|
|
$decl .= $otypes->{$_}->get_decl($_,$dopts).";"; |
2585
|
|
|
|
|
|
|
} |
2586
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $decl); |
2587
|
|
|
|
|
|
|
} |
2588
|
|
|
|
|
|
|
|
2589
|
|
|
|
|
|
|
sub NT2Copies__ { |
2590
|
|
|
|
|
|
|
my($opts,$onames,$otypes,$copyname) = @_; |
2591
|
|
|
|
|
|
|
my $decl; |
2592
|
14
|
|
|
|
|
|
my $dopts = {}; |
2593
|
|
|
|
|
|
|
$dopts->{VarArrays2Ptrs} = 1 if $opts->{ToPtrs}; |
2594
|
14
|
|
|
|
|
|
for(@$onames) { |
2595
|
|
|
|
|
|
|
$decl .= $otypes->{$_}->get_copy("\$PRIV($_)","$copyname->$_", |
2596
|
|
|
|
|
|
|
$dopts).";"; |
2597
|
|
|
|
|
|
|
} |
2598
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $decl); |
2599
|
|
|
|
|
|
|
} |
2600
|
0
|
0
|
|
|
|
|
|
2601
|
|
|
|
|
|
|
sub NT2Free__ { |
2602
|
|
|
|
|
|
|
my($opts,$onames,$otypes) = @_; |
2603
|
|
|
|
|
|
|
my $decl; |
2604
|
|
|
|
|
|
|
my $dopts = {}; |
2605
|
|
|
|
|
|
|
$dopts->{VarArrays2Ptrs} = 1 if $opts->{ToPtrs}; |
2606
|
|
|
|
|
|
|
for(@$onames) { |
2607
|
|
|
|
|
|
|
$decl .= $otypes->{$_}->get_free("\$PRIV($_)", |
2608
|
|
|
|
|
|
|
$dopts).";"; |
2609
|
|
|
|
|
|
|
} |
2610
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $decl); |
2611
|
|
|
|
|
|
|
} |
2612
|
8
|
50
|
|
|
|
|
|
2613
|
|
|
|
|
|
|
# The undef is just so that PrivIsInc gets set. Is this really |
2614
|
|
|
|
|
|
|
# needed (well, it is since the rule fails if there aren't 2 |
2615
|
|
|
|
|
|
|
# return values; what I meant is what does PrivIsInc do for |
2616
|
|
|
|
|
|
|
# us?) |
2617
|
8
|
|
|
|
|
|
# |
2618
|
|
|
|
|
|
|
sub make_incsizes { |
2619
|
|
|
|
|
|
|
my($parnames,$parobjs,$dimobjs,$havethreading) = @_; |
2620
|
|
|
|
|
|
|
my $str = ($havethreading?"pdl_thread __pdlthread; ":""). |
2621
|
|
|
|
|
|
|
(join '',map {$parobjs->{$_}->get_incdecls} @$parnames). |
2622
|
|
|
|
|
|
|
(join '',map {$_->get_decldim} sort values %$dimobjs); |
2623
|
|
|
|
|
|
|
return ($str,undef); |
2624
|
|
|
|
|
|
|
} |
2625
|
|
|
|
|
|
|
|
2626
|
|
|
|
|
|
|
sub make_incsize_copy { |
2627
|
|
|
|
|
|
|
my($parnames,$parobjs,$dimobjs,$copyname,$havethreading) = @_; |
2628
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, |
2629
|
0
|
|
|
|
|
|
($havethreading? |
2630
|
|
|
|
|
|
|
"PDL->thread_copy(&(\$PRIV(__pdlthread)),&($copyname->__pdlthread));" |
2631
|
|
|
|
|
|
|
: ""). |
2632
|
|
|
|
|
|
|
(join '',map {$parobjs->{$_}->get_incdecl_copy(sub{"\$PRIV($_[0])"}, |
2633
|
|
|
|
|
|
|
sub{"$copyname->$_[0]"})} @$parnames). |
2634
|
|
|
|
|
|
|
(join '',map {$_->get_copydim(sub{"\$PRIV($_[0])"}, |
2635
|
|
|
|
|
|
|
sub{"$copyname->$_[0]"})} sort values %$dimobjs) |
2636
|
|
|
|
|
|
|
); |
2637
|
|
|
|
|
|
|
|
2638
|
|
|
|
|
|
|
} |
2639
|
|
|
|
|
|
|
|
2640
|
|
|
|
|
|
|
sub make_incsize_free { |
2641
|
|
|
|
|
|
|
my($parnames,$parobjs,$dimobjs,$havethreading) = @_; |
2642
|
|
|
|
|
|
|
$havethreading ? |
2643
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, 'PDL->freethreadloop(&($PRIV(__pdlthread)));') |
2644
|
8
|
|
|
|
|
|
: '' |
2645
|
|
|
|
|
|
|
} |
2646
|
|
|
|
|
|
|
|
2647
|
|
|
|
|
|
|
sub make_parnames { |
2648
|
|
|
|
|
|
|
my($pnames,$pobjs,$dobjs) = @_; |
2649
|
|
|
|
|
|
|
my @pdls = map {$pobjs->{$_}} @$pnames; |
2650
|
|
|
|
|
|
|
my $npdls = $#pdls+1; |
2651
|
|
|
|
|
|
|
my $join__parnames = join ",",map {qq|"$_"|} @$pnames; |
2652
|
|
|
|
|
|
|
my $join__realdims = join ",",map {$#{$_->{IndObjs}}+1} @pdls; |
2653
|
|
|
|
|
|
|
if($Config{cc} eq 'cl') { |
2654
|
|
|
|
|
|
|
$join__parnames = '""' if $join__parnames eq ''; |
2655
|
|
|
|
|
|
|
$join__realdims = '0' if $join__realdims eq ''; |
2656
|
|
|
|
|
|
|
} |
2657
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, "static char *__parnames[] = {". $join__parnames ."}; |
2658
|
|
|
|
|
|
|
static PDL_Indx __realdims[] = {". $join__realdims . "}; |
2659
|
|
|
|
|
|
|
static char __funcname[] = \"\$MODULE()::\$NAME()\"; |
2660
|
|
|
|
|
|
|
static pdl_errorinfo __einfo = { |
2661
|
|
|
|
|
|
|
__funcname, __parnames, $npdls |
2662
|
|
|
|
|
|
|
}; |
2663
|
|
|
|
|
|
|
"); |
2664
|
|
|
|
|
|
|
} |
2665
|
|
|
|
|
|
|
|
2666
|
14
|
|
|
|
|
|
############################## |
2667
|
|
|
|
|
|
|
# |
2668
|
|
|
|
|
|
|
# hdrcheck -- examine the various PDLs that form the output PDL, |
2669
|
14
|
|
|
|
|
|
# and copy headers as necessary. The last header found with the hdrcpy |
2670
|
|
|
|
|
|
|
# bit set is used. This used to do just a simple ref copy but now |
2671
|
|
|
|
|
|
|
# it uses the perl routine PDL::_hdr_copy to do the dirty work. That |
2672
|
|
|
|
|
|
|
# routine makes a deep copy of the header. Copies of the deep copy |
2673
|
|
|
|
|
|
|
# are distributed to all the names of the piddle that are not the source |
2674
|
|
|
|
|
|
|
# of the header. I believe that is the Right Thing to do but I could be |
2675
|
|
|
|
|
|
|
# wrong. |
2676
|
|
|
|
|
|
|
# |
2677
|
|
|
|
|
|
|
# It's hard to read this sort of macro stuff so here's the flow: |
2678
|
|
|
|
|
|
|
# - Check the hdrcpy flag. If it's set, then check the header |
2679
|
|
|
|
|
|
|
# to see if it exists. If it doees, we need to call the |
2680
|
|
|
|
|
|
|
# perl-land PDL::_hdr_copy routine. There are some shenanigans |
2681
|
|
|
|
|
|
|
# to keep the return value from evaporating before we've had a |
2682
|
|
|
|
|
|
|
# chance to do our bit with it. |
2683
|
|
|
|
|
|
|
# - For each output argument in the function signature, try to put |
2684
|
|
|
|
|
|
|
# a reference to the new header into that argument's header slot. |
2685
|
|
|
|
|
|
|
# (For functions with multiple outputs, this produces multiple linked |
2686
|
|
|
|
|
|
|
# headers -- that could be Wrong; fixing it would require making |
2687
|
|
|
|
|
|
|
# yet more explicit copies!) |
2688
|
|
|
|
|
|
|
# - Remortalize the return value from PDL::_hdr_copy, so that we don't |
2689
|
|
|
|
|
|
|
# leak memory. |
2690
|
|
|
|
|
|
|
# |
2691
|
|
|
|
|
|
|
# --CED 12-Apr-2003 |
2692
|
|
|
|
|
|
|
# |
2693
|
|
|
|
|
|
|
|
2694
|
|
|
|
|
|
|
sub hdrcheck { |
2695
|
|
|
|
|
|
|
my ($pnames,$pobjs) = @_; |
2696
|
|
|
|
|
|
|
|
2697
|
|
|
|
|
|
|
my $nn = $#$pnames; |
2698
|
|
|
|
|
|
|
my @names = map { "\$PRIV(pdls[$_])" } 0..$nn; |
2699
|
|
|
|
|
|
|
|
2700
|
|
|
|
|
|
|
# from make_redodims_thread() we know that __creating[] == 0 unless |
2701
|
|
|
|
|
|
|
# ...{FlagCreat} is true |
2702
|
|
|
|
|
|
|
# |
2703
|
|
|
|
|
|
|
my $str = " |
2704
|
|
|
|
|
|
|
{ PDL_COMMENT(\"convenience block\") |
2705
|
|
|
|
|
|
|
void *hdrp = NULL; |
2706
|
|
|
|
|
|
|
char propagate_hdrcpy = 0; |
2707
|
|
|
|
|
|
|
SV *hdr_copy = NULL; |
2708
|
|
|
|
|
|
|
"; |
2709
|
|
|
|
|
|
|
|
2710
|
|
|
|
|
|
|
# Find a header among the possible names |
2711
|
|
|
|
|
|
|
foreach ( 0 .. $nn ) { |
2712
|
|
|
|
|
|
|
my $aux = $pobjs->{$pnames->[$_]}{FlagCreat} ? "!__creating[$_] && \n" : ""; |
2713
|
|
|
|
|
|
|
$str .= <<"HdRCHECK1" |
2714
|
|
|
|
|
|
|
if(!hdrp && |
2715
|
|
|
|
|
|
|
$aux $names[$_]\->hdrsv && |
2716
|
|
|
|
|
|
|
($names[$_]\->state & PDL_HDRCPY) |
2717
|
|
|
|
|
|
|
) { |
2718
|
|
|
|
|
|
|
hdrp = $names[$_]\->hdrsv; |
2719
|
|
|
|
|
|
|
propagate_hdrcpy = (($names[$_]\->state & PDL_HDRCPY) != 0); |
2720
|
|
|
|
|
|
|
} |
2721
|
|
|
|
|
|
|
HdRCHECK1 |
2722
|
|
|
|
|
|
|
; |
2723
|
|
|
|
|
|
|
} |
2724
|
|
|
|
|
|
|
|
2725
|
|
|
|
|
|
|
$str .= << 'DeePcOPY' |
2726
|
|
|
|
|
|
|
if (hdrp) { |
2727
|
|
|
|
|
|
|
if(hdrp == &PL_sv_undef) |
2728
|
|
|
|
|
|
|
hdr_copy = &PL_sv_undef; |
2729
|
|
|
|
|
|
|
else { PDL_COMMENT("Call the perl routine _hdr_copy...") |
2730
|
|
|
|
|
|
|
int count; |
2731
|
|
|
|
|
|
|
PDL_COMMENT("Call the perl routine PDL::_hdr_copy(hdrp)") |
2732
|
|
|
|
|
|
|
dSP; |
2733
|
|
|
|
|
|
|
ENTER ; |
2734
|
|
|
|
|
|
|
SAVETMPS ; |
2735
|
|
|
|
|
|
|
PUSHMARK(SP) ; |
2736
|
|
|
|
|
|
|
XPUSHs( hdrp ); |
2737
|
|
|
|
|
|
|
PUTBACK ; |
2738
|
|
|
|
|
|
|
count = call_pv("PDL::_hdr_copy",G_SCALAR); |
2739
|
|
|
|
|
|
|
SPAGAIN ; |
2740
|
|
|
|
|
|
|
if(count != 1) |
2741
|
|
|
|
|
|
|
croak("PDL::_hdr_copy didn't return a single value - please report this bug (A)."); |
2742
|
|
|
|
|
|
|
|
2743
|
|
|
|
|
|
|
hdr_copy = (SV *)POPs; |
2744
|
|
|
|
|
|
|
|
2745
|
|
|
|
|
|
|
if(hdr_copy && hdr_copy != &PL_sv_undef) { |
2746
|
|
|
|
|
|
|
(void)SvREFCNT_inc(hdr_copy); PDL_COMMENT("Keep hdr_copy from vanishing during FREETMPS") |
2747
|
|
|
|
|
|
|
} |
2748
|
|
|
|
|
|
|
|
2749
|
|
|
|
|
|
|
FREETMPS ; |
2750
|
|
|
|
|
|
|
LEAVE ; |
2751
|
|
|
|
|
|
|
|
2752
|
|
|
|
|
|
|
|
2753
|
|
|
|
|
|
|
} PDL_COMMENT("end of callback block") |
2754
|
|
|
|
|
|
|
|
2755
|
|
|
|
|
|
|
DeePcOPY |
2756
|
|
|
|
|
|
|
; |
2757
|
|
|
|
|
|
|
# if(hdrp) block is still open -- now reassign all the aliases... |
2758
|
|
|
|
|
|
|
|
2759
|
|
|
|
|
|
|
# Found the header -- now copy it into all the right places. |
2760
|
|
|
|
|
|
|
foreach ( 0 .. $nn ) { |
2761
|
|
|
|
|
|
|
$str .= <<"HdRCHECK2" |
2762
|
|
|
|
|
|
|
if ( $names[$_]\->hdrsv != hdrp ){ |
2763
|
|
|
|
|
|
|
if( $names[$_]\->hdrsv && $names[$_]\->hdrsv != &PL_sv_undef) |
2764
|
|
|
|
|
|
|
(void)SvREFCNT_dec( $names[$_]\->hdrsv ); |
2765
|
|
|
|
|
|
|
if( hdr_copy != &PL_sv_undef ) |
2766
|
|
|
|
|
|
|
(void)SvREFCNT_inc(hdr_copy); |
2767
|
|
|
|
|
|
|
$names[$_]\->hdrsv = hdr_copy; |
2768
|
|
|
|
|
|
|
} |
2769
|
|
|
|
|
|
|
if(propagate_hdrcpy) |
2770
|
|
|
|
|
|
|
$names[$_]\->state |= PDL_HDRCPY; |
2771
|
|
|
|
|
|
|
HdRCHECK2 |
2772
|
|
|
|
|
|
|
|
2773
|
|
|
|
|
|
|
# QUESTION: what is the following line doing? |
2774
|
|
|
|
|
|
|
# |
2775
|
|
|
|
|
|
|
if ( $pobjs->{$pnames->[$_]}{FlagCreat} ); |
2776
|
|
|
|
|
|
|
} |
2777
|
|
|
|
|
|
|
|
2778
|
|
|
|
|
|
|
$str .= ' |
2779
|
|
|
|
|
|
|
if(hdr_copy != &PL_sv_undef) |
2780
|
|
|
|
|
|
|
SvREFCNT_dec(hdr_copy); PDL_COMMENT("make hdr_copy mortal again") |
2781
|
|
|
|
|
|
|
} PDL_COMMENT("end of if(hdrp) block") |
2782
|
|
|
|
|
|
|
} PDL_COMMENT("end of conv. block") |
2783
|
|
|
|
|
|
|
'; |
2784
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, $str); |
2785
|
|
|
|
|
|
|
|
2786
|
|
|
|
|
|
|
} # sub: hdrcheck() |
2787
|
14
|
|
|
|
|
|
|
2788
|
14
|
|
|
|
|
|
sub make_redodims_thread { |
2789
|
14
|
|
|
|
|
|
#my($pnames,$pobjs,$dobjs,$dpars,$pcode ) = @_; |
2790
|
14
|
50
|
|
|
|
|
my($pnames,$pobjs,$dobjs,$dpars,$pcode, $noPthreadFlag) = @_; |
|
|
50
|
|
|
|
|
|
2791
|
0
|
0
|
|
|
|
|
my $str = PDL::PP::pp_line_numbers(__LINE__, ''); |
2792
|
0
|
|
|
|
|
|
my $npdls = @$pnames; |
2793
|
14
|
|
|
|
|
|
|
2794
|
14
|
|
|
|
|
|
$noPthreadFlag = 0 unless( defined $noPthreadFlag ); # assume we can pthread, unless indicated otherwise |
2795
|
0
|
|
|
|
|
|
|
2796
|
|
|
|
|
|
|
my $nn = $#$pnames; |
2797
|
14
|
50
|
|
|
|
|
my @privname = map { "\$PRIV(pdls[$_])" } ( 0 .. $nn ); |
2798
|
14
|
0
|
|
|
|
|
$str .= $npdls ? "PDL_Indx __creating[$npdls];\n" : "PDL_Indx __creating[1];\n"; |
2799
|
0
|
|
|
|
|
|
$str .= join '',map {$_->get_initdim."\n"} sort values %$dobjs; |
2800
|
|
|
|
|
|
|
|
2801
|
|
|
|
|
|
|
# if FlagCreat is NOT true, then we set __creating[] to 0 |
2802
|
|
|
|
|
|
|
# and we can use this knowledge below, and in hdrcheck() |
2803
|
0
|
|
|
|
|
|
# and in PP/PdlParObj (get_xsnormdimchecks()) |
2804
|
0
|
|
|
|
|
|
# |
2805
|
0
|
|
|
|
|
|
foreach ( 0 .. $nn ) { |
2806
|
0
|
0
|
|
|
|
|
$str .= "__creating[$_] = "; |
2807
|
0
|
0
|
|
|
|
|
if ( $pobjs->{$pnames->[$_]}{FlagCreat} ) { |
2808
|
0
|
|
|
|
|
|
$str .= "PDL_CR_SETDIMSCOND(__privtrans,$privname[$_]);\n"; |
2809
|
0
|
|
|
|
|
|
} else { |
2810
|
0
|
|
|
|
|
|
$str .= "0;\n"; |
2811
|
0
|
0
|
|
|
|
|
} |
2812
|
0
|
|
|
|
|
|
} # foreach: 0 .. $nn |
2813
|
|
|
|
|
|
|
|
2814
|
0
|
|
|
|
|
|
$str .= " {\n$pcode\n}\n"; |
2815
|
|
|
|
|
|
|
$str .= " {\n " . make_parnames($pnames,$pobjs,$dobjs) . " |
2816
|
0
|
0
|
|
|
|
|
PDL->initthreadstruct(2,\$PRIV(pdls), |
|
|
0
|
|
|
|
|
|
2817
|
0
|
|
|
|
|
|
__realdims,__creating,$npdls, |
2818
|
|
|
|
|
|
|
&__einfo,&(\$PRIV(__pdlthread)), |
2819
|
|
|
|
|
|
|
\$PRIV(vtable->per_pdl_flags), |
2820
|
0
|
0
|
|
|
|
|
$noPthreadFlag ); |
2821
|
0
|
|
|
|
|
|
}\n"; |
2822
|
|
|
|
|
|
|
$str .= join '',map {$pobjs->{$_}->get_xsnormdimchecks()} @$pnames; |
2823
|
|
|
|
|
|
|
$str .= hdrcheck($pnames,$pobjs); |
2824
|
|
|
|
|
|
|
$str .= join '',map {$pobjs->{$pnames->[$_]}-> |
2825
|
|
|
|
|
|
|
get_incsets($privname[$_])} 0..$nn; |
2826
|
|
|
|
|
|
|
return $str; |
2827
|
0
|
0
|
|
|
|
|
|
2828
|
0
|
|
|
|
|
|
} # sub: make_redodims_thread() |
2829
|
|
|
|
|
|
|
|
2830
|
|
|
|
|
|
|
sub XSHdr { |
2831
|
|
|
|
|
|
|
my($xsname,$nxargs) = @_; |
2832
|
|
|
|
|
|
|
return XS::mkproto($xsname,$nxargs); |
2833
|
|
|
|
|
|
|
} |
2834
|
|
|
|
|
|
|
|
2835
|
|
|
|
|
|
|
########################################################### |
2836
|
|
|
|
|
|
|
# Name : extract_signature_from_fulldoc |
2837
|
|
|
|
|
|
|
# Usage : $sig = extract_signature_from_fulldoc($fulldoc) |
2838
|
|
|
|
|
|
|
# Purpose : pull out the signature from the fulldoc string |
2839
|
|
|
|
|
|
|
# Returns : whatever is in parentheses in the signature, or undef |
2840
|
|
|
|
|
|
|
# Parameters : $fulldoc |
2841
|
|
|
|
|
|
|
# Throws : never |
2842
|
|
|
|
|
|
|
# Notes : the signature must have the following form: |
2843
|
|
|
|
|
|
|
# : |
2844
|
|
|
|
|
|
|
# : =for sig |
2845
|
|
|
|
|
|
|
# : |
2846
|
|
|
|
|
|
|
# : Signature: (
|
2847
|
|
|
|
|
|
|
# : be multiline>) |
2848
|
|
|
|
|
|
|
# : |
2849
|
|
|
|
|
|
|
# : |
2850
|
|
|
|
|
|
|
# : The two spaces before "Signature" are required, as are |
2851
|
|
|
|
|
|
|
# : the parentheses. |
2852
|
|
|
|
|
|
|
sub extract_signature_from_fulldoc { |
2853
|
|
|
|
|
|
|
my $fulldoc = shift; |
2854
|
|
|
|
|
|
|
if ($fulldoc =~ /=for sig\n\n Signature: \(([^\n]*)\n/g) { |
2855
|
|
|
|
|
|
|
# Extract the signature and remove the final parenthesis |
2856
|
|
|
|
|
|
|
my $sig = $1; |
2857
|
|
|
|
|
|
|
$sig .= $1 while $fulldoc =~ /\G\h+([^\n]*)\n/g; |
2858
|
|
|
|
|
|
|
$sig =~ s/\)\s*$//; |
2859
|
|
|
|
|
|
|
return $sig; |
2860
|
|
|
|
|
|
|
} |
2861
|
|
|
|
|
|
|
return; |
2862
|
|
|
|
|
|
|
} |
2863
|
|
|
|
|
|
|
|
2864
|
|
|
|
|
|
|
|
2865
|
|
|
|
|
|
|
# Build the valid-types regex and valid Pars argument only once. These are |
2866
|
|
|
|
|
|
|
# also used in PDL::PP::PdlParObj, which is why they are globally available. |
2867
|
|
|
|
|
|
|
use PDL::PP::PdlParObj; |
2868
|
|
|
|
|
|
|
my $pars_re = $PDL::PP::PdlParObj::pars_re; |
2869
|
|
|
|
|
|
|
|
2870
|
|
|
|
|
|
|
########################################################### |
2871
|
|
|
|
|
|
|
# Name : build_pars_from_fulldoc |
2872
|
|
|
|
|
|
|
# Usage : $pars = build_pars_from_fulldoc($fulldoc) |
2873
|
|
|
|
|
|
|
# Purpose : extract the Pars from the signature from the fulldoc string, |
2874
|
|
|
|
|
|
|
# : the part of the signature that specifies the piddles |
2875
|
|
|
|
|
|
|
# Returns : a string appropriate for the Pars key |
2876
|
|
|
|
|
|
|
# Parameters : $fulldoc |
2877
|
|
|
|
|
|
|
# Throws : if there is no signature |
2878
|
|
|
|
|
|
|
# : if there is no extractable Pars section |
2879
|
|
|
|
|
|
|
# : if some PDL arguments come after the OtherPars arguments start |
2880
|
|
|
|
|
|
|
# Notes : This is meant to be used directly in a Rule. Therefore, it |
2881
|
|
|
|
|
|
|
# : is only called if the Pars key does not yet exist, so if it |
2882
|
|
|
|
|
|
|
# : is not possible to extract the Pars section, it dies. |
2883
|
|
|
|
|
|
|
sub build_pars_from_fulldoc { |
2884
|
|
|
|
|
|
|
my $fulldoc = shift; |
2885
|
|
|
|
|
|
|
|
2886
|
|
|
|
|
|
|
# Get the signature or die |
2887
|
|
|
|
|
|
|
my $sig = extract_signature_from_fulldoc($fulldoc) |
2888
|
|
|
|
|
|
|
or confess('No Pars specified and none could be extracted from FullDoc'); |
2889
|
|
|
|
|
|
|
|
2890
|
|
|
|
|
|
|
# Everything is semicolon-delimited |
2891
|
|
|
|
|
|
|
my @args = split /\s*;\s*/, $sig; |
2892
|
|
|
|
|
|
|
my @pars; |
2893
|
|
|
|
|
|
|
my $switched_to_other_pars = 0; |
2894
|
|
|
|
|
|
|
for my $arg (@args) { |
2895
|
|
|
|
|
|
|
confess('All PDL args must come before other pars in FullDoc signature') |
2896
|
|
|
|
|
|
|
if $switched_to_other_pars and $arg =~ $pars_re; |
2897
|
|
|
|
|
|
|
if ($arg =~ $pars_re) { |
2898
|
|
|
|
|
|
|
push @pars, $arg; |
2899
|
|
|
|
|
|
|
} |
2900
|
|
|
|
|
|
|
else { |
2901
|
|
|
|
|
|
|
$switched_to_other_pars = 1; |
2902
|
|
|
|
|
|
|
} |
2903
|
|
|
|
|
|
|
} |
2904
|
|
|
|
|
|
|
|
2905
|
|
|
|
|
|
|
# Make sure there's something there |
2906
|
|
|
|
|
|
|
confess('FullDoc signature contains no PDL arguments') if @pars == 0; |
2907
|
|
|
|
|
|
|
|
2908
|
|
|
|
|
|
|
# All done! |
2909
|
|
|
|
|
|
|
return join('; ', @pars); |
2910
|
|
|
|
|
|
|
} |
2911
|
|
|
|
|
|
|
|
2912
|
|
|
|
|
|
|
########################################################### |
2913
|
|
|
|
|
|
|
# Name : build_otherpars_from_fulldoc |
2914
|
|
|
|
|
|
|
# Usage : $otherpars = build_otherpars_from_fulldoc($fulldoc) |
2915
|
|
|
|
|
|
|
# Purpose : extract the OtherPars from the signature from the fulldoc |
2916
|
|
|
|
|
|
|
# : string, the part of the signature that specifies non-piddle |
2917
|
|
|
|
|
|
|
# : arguments |
2918
|
|
|
|
|
|
|
# Returns : a string appropriate for the OtherPars key |
2919
|
|
|
|
|
|
|
# Parameters : $fulldoc |
2920
|
|
|
|
|
|
|
# Throws : if some OtherPars arguments come before the last PDL argument |
2921
|
|
|
|
|
|
|
# Notes : This is meant to be used directly in a Rule. Therefore, it |
2922
|
|
|
|
|
|
|
# : is only called if the OtherPars key does not yet exist. |
2923
|
|
|
|
|
|
|
sub build_otherpars_from_fulldoc { |
2924
|
|
|
|
|
|
|
my $fulldoc = shift; |
2925
|
|
|
|
|
|
|
|
2926
|
|
|
|
|
|
|
# Get the signature or do not set |
2927
|
|
|
|
|
|
|
my $sig = extract_signature_from_fulldoc($fulldoc) |
2928
|
|
|
|
|
|
|
or return 'DO NOT SET!!'; |
2929
|
|
|
|
|
|
|
|
2930
|
|
|
|
|
|
|
# Everything is semicolon-delimited |
2931
|
|
|
|
|
|
|
my @args = split /\s*;\s*/, $sig; |
2932
|
|
|
|
|
|
|
my @otherpars; |
2933
|
|
|
|
|
|
|
for my $arg (@args) { |
2934
|
|
|
|
|
|
|
confess('All PDL args must come before other pars in FullDoc signature') |
2935
|
|
|
|
|
|
|
if @otherpars > 0 and $arg =~ $pars_re; |
2936
|
|
|
|
|
|
|
if ($arg !~ $pars_re) { |
2937
|
|
|
|
|
|
|
push @otherpars, $arg; |
2938
|
|
|
|
|
|
|
} |
2939
|
|
|
|
|
|
|
} |
2940
|
|
|
|
|
|
|
|
2941
|
|
|
|
|
|
|
# All done! |
2942
|
|
|
|
|
|
|
return 'DO NOT SET!!'if @otherpars == 0; |
2943
|
|
|
|
|
|
|
return join('; ', @otherpars); |
2944
|
|
|
|
|
|
|
} |
2945
|
|
|
|
|
|
|
|
2946
|
|
|
|
|
|
|
# Set up the rules for translating the pp_def contents. |
2947
|
|
|
|
|
|
|
# |
2948
|
|
|
|
|
|
|
$PDL::PP::deftbl = |
2949
|
|
|
|
|
|
|
[ |
2950
|
|
|
|
|
|
|
# used as a flag for many of the routines |
2951
|
|
|
|
|
|
|
# ie should we bother with bad values for this routine? |
2952
|
|
|
|
|
|
|
# 1 - yes, |
2953
|
|
|
|
|
|
|
# 0 - no, maybe issue a warning |
2954
|
|
|
|
|
|
|
# undef - we're not compiling with bad value support |
2955
|
|
|
|
|
|
|
# |
2956
|
|
|
|
|
|
|
PDL::PP::Rule->new("BadFlag", "_HandleBad", |
2957
|
|
|
|
|
|
|
"Sets BadFlag based upon HandleBad key and PDL's ability to handle bad values", |
2958
|
|
|
|
|
|
|
sub { return (defined $_[0]) ? ($bvalflag and $_[0]) : undef; }), |
2959
|
|
|
|
|
|
|
|
2960
|
|
|
|
|
|
|
#################### |
2961
|
|
|
|
|
|
|
# FullDoc Handling # |
2962
|
|
|
|
|
|
|
#################### |
2963
|
|
|
|
|
|
|
|
2964
|
|
|
|
|
|
|
# Error processing: does FullDoc contain BadDoc, yet BadDoc specified? |
2965
|
|
|
|
|
|
|
PDL::PP::Rule::Croak->new(['FullDoc', 'BadDoc'], |
2966
|
|
|
|
|
|
|
'Cannot have both FullDoc and BadDoc defined'), |
2967
|
|
|
|
|
|
|
PDL::PP::Rule::Croak->new(['FullDoc', 'Doc'], |
2968
|
|
|
|
|
|
|
'Cannot have both FullDoc and Doc defined'), |
2969
|
|
|
|
|
|
|
# Note: no error processing on Pars; it's OK for the docs to gloss over |
2970
|
|
|
|
|
|
|
# the details. |
2971
|
|
|
|
|
|
|
|
2972
|
|
|
|
|
|
|
# Add the Pars section based on the signature of the FullDoc if the Pars |
2973
|
|
|
|
|
|
|
# section doesn't already exist |
2974
|
|
|
|
|
|
|
PDL::PP::Rule->new('Pars', 'FullDoc', |
2975
|
|
|
|
|
|
|
'Sets the Pars from the FullDoc if Pars is not explicitly specified', |
2976
|
|
|
|
|
|
|
\&build_pars_from_fulldoc |
2977
|
|
|
|
|
|
|
), |
2978
|
|
|
|
|
|
|
PDL::PP::Rule->new('OtherPars', 'FullDoc', |
2979
|
|
|
|
|
|
|
'Sets the OtherPars from the FullDoc if OtherPars is not explicitly specified', |
2980
|
|
|
|
|
|
|
\&build_otherpars_from_fulldoc |
2981
|
|
|
|
|
|
|
), |
2982
|
|
|
|
|
|
|
|
2983
|
|
|
|
|
|
|
################################ |
2984
|
|
|
|
|
|
|
# Other Documentation Handling # |
2985
|
|
|
|
|
|
|
################################ |
2986
|
|
|
|
|
|
|
|
2987
|
|
|
|
|
|
|
# no docs by default |
2988
|
|
|
|
|
|
|
PDL::PP::Rule::Returns->new("Doc", [], 'Sets the default doc string', |
2989
|
|
|
|
|
|
|
"\n=for ref\n\ninfo not available\n"), |
2990
|
|
|
|
|
|
|
|
2991
|
|
|
|
|
|
|
# try and automate the docs |
2992
|
|
|
|
|
|
|
# could be really clever and include the sig to see about |
2993
|
|
|
|
|
|
|
# input/output params, for instance |
2994
|
|
|
|
|
|
|
|
2995
|
|
|
|
|
|
|
PDL::PP::Rule->new("BadDoc", ["BadFlag","Name","_CopyBadStatusCode"], |
2996
|
|
|
|
|
|
|
'Sets the default documentation for handling of bad values', |
2997
|
|
|
|
|
|
|
sub { |
2998
|
|
|
|
|
|
|
return undef unless $bvalflag; |
2999
|
|
|
|
|
|
|
my ( $bf, $name, $code ) = @_; |
3000
|
|
|
|
|
|
|
my $str; |
3001
|
|
|
|
|
|
|
if ( not defined($bf) ) { |
3002
|
|
|
|
|
|
|
$str = "$name does not process bad values.\n"; |
3003
|
|
|
|
|
|
|
} elsif ( $bf ) { |
3004
|
|
|
|
|
|
|
$str = "$name processes bad values.\n"; |
3005
|
|
|
|
|
|
|
} else { |
3006
|
|
|
|
|
|
|
$str = "$name ignores the bad-value flag of the input piddles.\n"; |
3007
|
|
|
|
|
|
|
} |
3008
|
|
|
|
|
|
|
if ( not defined($code) ) { |
3009
|
|
|
|
|
|
|
$str .= "It will set the bad-value flag of all output piddles if " . |
3010
|
|
|
|
|
|
|
"the flag is set for any of the input piddles.\n"; |
3011
|
|
|
|
|
|
|
} elsif ( $code eq '' ) { |
3012
|
|
|
|
|
|
|
$str .= "The output piddles will NOT have their bad-value flag set.\n"; |
3013
|
|
|
|
|
|
|
} else { |
3014
|
|
|
|
|
|
|
$str .= "The state of the bad-value flag of the output piddles is unknown.\n"; |
3015
|
|
|
|
|
|
|
} |
3016
|
|
|
|
|
|
|
} |
3017
|
|
|
|
|
|
|
), |
3018
|
|
|
|
|
|
|
|
3019
|
|
|
|
|
|
|
# Default: no otherpars |
3020
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::EmptyString->new("OtherPars"), |
3021
|
|
|
|
|
|
|
|
3022
|
|
|
|
|
|
|
# the docs |
3023
|
|
|
|
|
|
|
PDL::PP::Rule->new("PdlDoc", "FullDoc", sub { |
3024
|
|
|
|
|
|
|
my $fulldoc = shift; |
3025
|
|
|
|
|
|
|
|
3026
|
|
|
|
|
|
|
# Remove bad documentation if bad values are not supported |
3027
|
|
|
|
|
|
|
$fulldoc =~ s/=for bad\n\n.*?\n\n//s unless $bvalflag; |
3028
|
|
|
|
|
|
|
|
3029
|
|
|
|
|
|
|
# Append a final cut if it doesn't exist due to heredoc shinanigans |
3030
|
|
|
|
|
|
|
$fulldoc .= "\n\n=cut\n" unless $fulldoc =~ /\n=cut\n*$/; |
3031
|
|
|
|
|
|
|
|
3032
|
|
|
|
|
|
|
# Make sure the =head1 FUNCTIONS section gets added |
3033
|
|
|
|
|
|
|
$::DOCUMENTED++; |
3034
|
|
|
|
|
|
|
|
3035
|
|
|
|
|
|
|
return $fulldoc; |
3036
|
|
|
|
|
|
|
} |
3037
|
|
|
|
|
|
|
), |
3038
|
|
|
|
|
|
|
PDL::PP::Rule->new("PdlDoc", ["Name","_Pars","OtherPars","Doc","_BadDoc"], \&GenDocs), |
3039
|
|
|
|
|
|
|
|
3040
|
|
|
|
|
|
|
################## |
3041
|
|
|
|
|
|
|
# Done with Docs # |
3042
|
|
|
|
|
|
|
################## |
3043
|
|
|
|
|
|
|
|
3044
|
|
|
|
|
|
|
# Notes |
3045
|
|
|
|
|
|
|
# Suffix 'NS' means, "Needs Substitution". In other words, the string |
3046
|
|
|
|
|
|
|
# associated with a key that has the suffix "NS" must be run through a |
3047
|
|
|
|
|
|
|
# Substitute or Substitute::Usual |
3048
|
|
|
|
|
|
|
|
3049
|
|
|
|
|
|
|
# some defaults |
3050
|
|
|
|
|
|
|
# |
3051
|
|
|
|
|
|
|
PDL::PP::Rule::Returns->new("CopyName", [], |
3052
|
|
|
|
|
|
|
'Sets the CopyName key to the default: __copy', "__copy"), |
3053
|
|
|
|
|
|
|
|
3054
|
|
|
|
|
|
|
PDL::PP::Rule->new("DefaultFlowCodeNS", "_DefaultFlow", |
3055
|
|
|
|
|
|
|
'Sets the code to handle dataflow flags, if applicable', |
3056
|
|
|
|
|
|
|
sub { pp_line_numbers(__LINE__, $_[0] ? |
3057
|
|
|
|
|
|
|
'$PRIV(flags) |= PDL_ITRANS_DO_DATAFLOW_F | PDL_ITRANS_DO_DATAFLOW_B;' |
3058
|
|
|
|
|
|
|
: 'PDL_COMMENT("No flow")') }), |
3059
|
|
|
|
|
|
|
|
3060
|
|
|
|
|
|
|
# Question: where is ppdefs defined? |
3061
|
|
|
|
|
|
|
# Answer: Core/Types.pm |
3062
|
|
|
|
|
|
|
# |
3063
|
|
|
|
|
|
|
PDL::PP::Rule->new("GenericTypes", [], |
3064
|
|
|
|
|
|
|
'Sets GenericTypes flag to all types known to PDL::Types', |
3065
|
|
|
|
|
|
|
sub {[ppdefs]}), |
3066
|
|
|
|
|
|
|
|
3067
|
|
|
|
|
|
|
PDL::PP::Rule->new("ExtraGenericLoops", "FTypes", |
3068
|
|
|
|
|
|
|
'Makes ExtraGenericLoops identical to FTypes if the latter exists and the former does not', |
3069
|
|
|
|
|
|
|
sub {return $_[0]}), |
3070
|
|
|
|
|
|
|
PDL::PP::Rule::Returns->new("ExtraGenericLoops", [], |
3071
|
|
|
|
|
|
|
'Sets ExtraGenericLoops to an empty hash if it does not already exist', {}), |
3072
|
|
|
|
|
|
|
|
3073
|
|
|
|
|
|
|
PDL::PP::Rule::InsertName->new("StructName", 'pdl_${name}_struct'), |
3074
|
|
|
|
|
|
|
PDL::PP::Rule::InsertName->new("VTableName", 'pdl_${name}_vtable'), |
3075
|
|
|
|
|
|
|
|
3076
|
|
|
|
|
|
|
PDL::PP::Rule->new("FHdrInfo", ["Name","StructName"], |
3077
|
|
|
|
|
|
|
sub { return { Name => $_[0], StructName => $_[1], }; }), |
3078
|
|
|
|
|
|
|
|
3079
|
|
|
|
|
|
|
# Treat exchanges as affines. Affines assumed to be parent->child. |
3080
|
|
|
|
|
|
|
# Exchanges may, if the want, handle threadids as well. |
3081
|
|
|
|
|
|
|
# Same number of dimensions is assumed, though. |
3082
|
|
|
|
|
|
|
# |
3083
|
|
|
|
|
|
|
PDL::PP::Rule->new("AffinePriv", "XCHGOnly", sub { return @_; }), |
3084
|
|
|
|
|
|
|
PDL::PP::Rule::Returns->new("Priv", "AffinePriv", 'PDL_Indx incs[$CHILD(ndims)];PDL_Indx offs; '), |
3085
|
|
|
|
|
|
|
PDL::PP::Rule::Returns->new("IsAffineFlag", "AffinePriv", "PDL_ITRANS_ISAFFINE"), |
3086
|
|
|
|
|
|
|
|
3087
|
|
|
|
|
|
|
PDL::PP::Rule->new("RedoDims", ["EquivPDimExpr","FHdrInfo","_EquivDimCheck"], |
3088
|
|
|
|
|
|
|
\&pdimexpr2priv), |
3089
|
|
|
|
|
|
|
PDL::PP::Rule->new("RedoDims", ["Identity","FHdrInfo"], |
3090
|
|
|
|
|
|
|
\&identity2priv), |
3091
|
|
|
|
|
|
|
|
3092
|
|
|
|
|
|
|
# NOTE: we use the same bit of code for all-good and bad data - |
3093
|
|
|
|
|
|
|
# see the Code rule |
3094
|
|
|
|
|
|
|
# |
3095
|
|
|
|
|
|
|
PDL::PP::Rule->new("EquivCPOffsCode", "Identity", |
3096
|
|
|
|
|
|
|
"something to do with dataflow between CHILD & PARENT, I think.", |
3097
|
|
|
|
|
|
|
\&equivcpoffscode), |
3098
|
|
|
|
|
|
|
|
3099
|
|
|
|
|
|
|
PDL::PP::Rule->new("Code", ["EquivCPOffsCode","BadFlag"], |
3100
|
|
|
|
|
|
|
"create Code from EquivCPOffsCode", |
3101
|
|
|
|
|
|
|
\&CodefromEquivCPOffsCode), |
3102
|
|
|
|
|
|
|
|
3103
|
|
|
|
|
|
|
PDL::PP::Rule->new("BackCode", ["EquivCPOffsCode","BadFlag"], |
3104
|
|
|
|
|
|
|
"create BackCode from EquivCPOffsCode", |
3105
|
|
|
|
|
|
|
\&BackCodefromEquivCPOffsCode), |
3106
|
|
|
|
|
|
|
|
3107
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::Zero->new("Affine_Ok", "EquivCPOffsCode"), |
3108
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::One->new("Affine_Ok"), |
3109
|
|
|
|
|
|
|
|
3110
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::NULL->new("ReadDataFuncName", "AffinePriv"), |
3111
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::NULL->new("WriteBackDataFuncName", "AffinePriv"), |
3112
|
|
|
|
|
|
|
|
3113
|
|
|
|
|
|
|
PDL::PP::Rule::InsertName->new("ReadDataFuncName", 'pdl_${name}_readdata'), |
3114
|
|
|
|
|
|
|
PDL::PP::Rule::InsertName->new("CopyFuncName", 'pdl_${name}_copy'), |
3115
|
|
|
|
|
|
|
PDL::PP::Rule::InsertName->new("FreeFuncName", 'pdl_${name}_free'), |
3116
|
|
|
|
|
|
|
PDL::PP::Rule::InsertName->new("RedoDimsFuncName", 'pdl_${name}_redodims'), |
3117
|
|
|
|
|
|
|
|
3118
|
|
|
|
|
|
|
# There used to be a BootStruct rule which just became copied to the XSBootCode |
3119
|
|
|
|
|
|
|
# rule, so it has been removed. |
3120
|
|
|
|
|
|
|
# |
3121
|
|
|
|
|
|
|
PDL::PP::Rule->new("XSBootCode", ["AffinePriv","VTableName"], |
3122
|
|
|
|
|
|
|
sub {return " $_[1].readdata = PDL->readdata_affine;\n" . |
3123
|
|
|
|
|
|
|
" $_[1].writebackdata = PDL->writebackdata_affine;\n"}), |
3124
|
|
|
|
|
|
|
|
3125
|
|
|
|
|
|
|
# Parameters in the form 'parent and child(this)'. |
3126
|
|
|
|
|
|
|
# The names are PARENT and CHILD. |
3127
|
|
|
|
|
|
|
# |
3128
|
|
|
|
|
|
|
# P2Child implicitly means "no data type changes". |
3129
|
|
|
|
|
|
|
|
3130
|
|
|
|
|
|
|
PDL::PP::Rule->new(["USParNames","USParObjs","FOOFOONoConversion","HaveThreading","NewXSName"], |
3131
|
|
|
|
|
|
|
["P2Child","Name","BadFlag"], |
3132
|
|
|
|
|
|
|
\&NewParentChildPars), |
3133
|
|
|
|
|
|
|
|
3134
|
|
|
|
|
|
|
PDL::PP::Rule::InsertName->new("NewXSName", '_${name}_int'), |
3135
|
|
|
|
|
|
|
|
3136
|
|
|
|
|
|
|
PDL::PP::Rule::Returns->new("EquivPThreadIdExpr", "P2Child", |
3137
|
|
|
|
|
|
|
'$CTID-$PARENT(ndims)+$CHILD(ndims)'), |
3138
|
|
|
|
|
|
|
|
3139
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::One->new("HaveThreading"), |
3140
|
|
|
|
|
|
|
|
3141
|
|
|
|
|
|
|
# Parameters in the 'a(x,y); [o]b(y)' format, with |
3142
|
|
|
|
|
|
|
# fixed nos of real, unthreaded-over dims. |
3143
|
|
|
|
|
|
|
# |
3144
|
|
|
|
|
|
|
# XXX |
3145
|
|
|
|
|
|
|
# - the need for BadFlag is due to hacked get_xsdatapdecl() |
3146
|
|
|
|
|
|
|
# in PP/PdlParObj and because the PdlParObjs are created by |
3147
|
|
|
|
|
|
|
# PDL::PP::Signature (Doug Burke 07/08/00) |
3148
|
|
|
|
|
|
|
|
3149
|
|
|
|
|
|
|
PDL::PP::Rule->new(["USParNames","USParObjs","DimmedPars"], ["Pars","BadFlag"], \&Pars_nft), |
3150
|
|
|
|
|
|
|
PDL::PP::Rule->new("DimObjs", ["USParNames","USParObjs"], \&ParObjs_DimObjs), |
3151
|
|
|
|
|
|
|
|
3152
|
|
|
|
|
|
|
# Set CallCopy flag for simple functions (2-arg with 0-dim signatures) |
3153
|
|
|
|
|
|
|
# This will copy the $object->copy method, instead of initialize |
3154
|
|
|
|
|
|
|
# for PDL-subclassed objects |
3155
|
|
|
|
|
|
|
# |
3156
|
|
|
|
|
|
|
PDL::PP::Rule->new("CallCopy", ["DimObjs", "USParNames", "USParObjs", "Name", "_P2Child"], |
3157
|
|
|
|
|
|
|
sub { |
3158
|
|
|
|
|
|
|
my ($dimObj, $USParNames, $USParObjs, $Name, $hasp2c) = @_; |
3159
|
|
|
|
|
|
|
return 0 if $hasp2c; |
3160
|
|
|
|
|
|
|
my $noDimmedArgs = scalar(keys %$dimObj); |
3161
|
|
|
|
|
|
|
my $noArgs = scalar(@$USParNames); |
3162
|
|
|
|
|
|
|
if( $noDimmedArgs == 0 and $noArgs == 2 ){ |
3163
|
|
|
|
|
|
|
# Check for 2-arg functgion with 0-dim signatures |
3164
|
|
|
|
|
|
|
# Check to see if output arg is _not_ explicitly typed: |
3165
|
|
|
|
|
|
|
my $arg2 = $USParNames->[1]; |
3166
|
|
|
|
|
|
|
my $ParObj = $USParObjs->{$arg2}; |
3167
|
|
|
|
|
|
|
if( $ParObj->ctype('generic') eq 'generic'){ |
3168
|
|
|
|
|
|
|
# print "Calling Copy for function '$Name'\n"; |
3169
|
|
|
|
|
|
|
return 1; |
3170
|
|
|
|
|
|
|
} |
3171
|
|
|
|
|
|
|
} |
3172
|
|
|
|
|
|
|
return 0; |
3173
|
|
|
|
|
|
|
}), |
3174
|
|
|
|
|
|
|
|
3175
|
|
|
|
|
|
|
# "Other pars", the parameters which are usually not pdls. |
3176
|
|
|
|
|
|
|
|
3177
|
|
|
|
|
|
|
PDL::PP::Rule->new(["OtherParNames","OtherParTypes"], ["OtherPars","DimObjs"], \&OtherPars_nft), |
3178
|
|
|
|
|
|
|
|
3179
|
|
|
|
|
|
|
PDL::PP::Rule->new(["ParNames","ParObjs"], ["USParNames","USParObjs"], \&sort_pnobjs), |
3180
|
|
|
|
|
|
|
|
3181
|
|
|
|
|
|
|
PDL::PP::Rule->new("DefSyms", "StructName", \&MkDefSyms), |
3182
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSArgs", ["USParNames","USParObjs","OtherParNames","OtherParTypes"], |
3183
|
|
|
|
|
|
|
\&NXArgs), |
3184
|
|
|
|
|
|
|
|
3185
|
|
|
|
|
|
|
PDL::PP::Rule::Returns->new("PMCode", undef), |
3186
|
|
|
|
|
|
|
|
3187
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSSymTab", ["DefSyms","NewXSArgs"], \&AddArgsyms), |
3188
|
|
|
|
|
|
|
|
3189
|
|
|
|
|
|
|
PDL::PP::Rule->new("InplaceCode", ["Name","NewXSArgs","USParObjs","_Inplace"], |
3190
|
|
|
|
|
|
|
'Insert code (just after HdrCode) to ensure the routine can be done inplace', |
3191
|
|
|
|
|
|
|
\&InplaceCode), |
3192
|
|
|
|
|
|
|
|
3193
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::EmptyString->new("HdrCode", [], |
3194
|
|
|
|
|
|
|
'Code that will be inserted at the end of the autogenerated xs argument processing code VargArgsXSHdr'), |
3195
|
|
|
|
|
|
|
|
3196
|
|
|
|
|
|
|
|
3197
|
|
|
|
|
|
|
# Create header for variable argument list. Used if no 'other pars' specified. |
3198
|
|
|
|
|
|
|
# D. Hunt 4/11/00 |
3199
|
|
|
|
|
|
|
# make sure it is not used when the GlobalNew flag is set ; CS 4/15/00 |
3200
|
|
|
|
|
|
|
PDL::PP::Rule->new("VarArgsXSHdr", |
3201
|
|
|
|
|
|
|
["Name","NewXSArgs","USParObjs","OtherParTypes", |
3202
|
|
|
|
|
|
|
"PMCode","HdrCode","InplaceCode","_GlobalNew","_CallCopy","_Bitwise"], |
3203
|
|
|
|
|
|
|
'XS code to process arguments on stack based on supplied Pars argument to pp_def; GlobalNew has implications how/if this is done', |
3204
|
|
|
|
|
|
|
\&VarArgsXSHdr), |
3205
|
|
|
|
|
|
|
|
3206
|
|
|
|
|
|
|
## Added new line for returning (or not returning) variables. D. Hunt 4/7/00 |
3207
|
|
|
|
|
|
|
# make sure it is not used when the GlobalNew flag is set ; CS 4/15/00 |
3208
|
|
|
|
|
|
|
# |
3209
|
|
|
|
|
|
|
PDL::PP::Rule->new("VarArgsXSReturn", |
3210
|
|
|
|
|
|
|
["NewXSArgs","USParObjs","_GlobalNew"], |
3211
|
|
|
|
|
|
|
"Generate XS trailer for returning output variables", |
3212
|
|
|
|
|
|
|
\&VarArgsXSReturn), |
3213
|
|
|
|
|
|
|
|
3214
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSHdr", ["NewXSName","NewXSArgs"], \&XSHdr), |
3215
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSCHdrs", ["NewXSName","NewXSArgs","GlobalNew"], \&XSCHdrs), |
3216
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSLocals", "NewXSSymTab", \&Sym2Loc), |
3217
|
|
|
|
|
|
|
|
3218
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::Zero->new("IsAffineFlag"), |
3219
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::Zero->new("NoPdlThread"), |
3220
|
|
|
|
|
|
|
|
3221
|
|
|
|
|
|
|
# hmm, need to check on conditional check here (or rather, other bits of code prob need |
3222
|
|
|
|
|
|
|
# to include it too; see Ops.xs, PDL::assgn) |
3223
|
|
|
|
|
|
|
## |
3224
|
|
|
|
|
|
|
## sub { return (defined $_[0]) ? "int \$BADFLAGCACHE() = 0;" : ""; } ], |
3225
|
|
|
|
|
|
|
## |
3226
|
|
|
|
|
|
|
## why have I got a "_HandleBad" condition here? it isn't used in the routine |
3227
|
|
|
|
|
|
|
## and isn't required to fire the rule. Or should we actually check the value of |
3228
|
|
|
|
|
|
|
## HandleBad (ie to optimize for code that explicitly doesn't handle bad code)? |
3229
|
|
|
|
|
|
|
## TO DO: Check assgn in ops for this? Not obvious, or at least we need other |
3230
|
|
|
|
|
|
|
## bits of code work with us (eg the checking of $BADFLAGCACHE in some other |
3231
|
|
|
|
|
|
|
## rule) |
3232
|
|
|
|
|
|
|
## |
3233
|
|
|
|
|
|
|
## PDL::PP::Rule->new("CacheBadFlagInitNS", "_HandleBad", |
3234
|
|
|
|
|
|
|
## sub { return $bvalflag ? "\n int \$BADFLAGCACHE() = 0;\n" : ""; }), |
3235
|
|
|
|
|
|
|
PDL::PP::Rule->new("CacheBadFlagInitNS", |
3236
|
|
|
|
|
|
|
sub { PDL::PP::pp_line_numbers(__LINE__, $bvalflag ? "\n int \$BADFLAGCACHE() = 0;\n" : "") }), |
3237
|
|
|
|
|
|
|
# The next rule, if done in place of the above, causes Ops.xs to fail to compile |
3238
|
|
|
|
|
|
|
# PDL::PP::Rule->new("CacheBadFlagInitNS", "BadFlag", |
3239
|
|
|
|
|
|
|
# sub { return $_[0] ? "\n int \$BADFLAGCACHE() = 0;\n" : ""; }), |
3240
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("CacheBadFlagInit", "CacheBadFlagInitNS"), |
3241
|
|
|
|
|
|
|
|
3242
|
|
|
|
|
|
|
# need special cases for |
3243
|
|
|
|
|
|
|
# a) bad values |
3244
|
|
|
|
|
|
|
# b) bad values + GlobalNew |
3245
|
|
|
|
|
|
|
# c) bad values + PMCode |
3246
|
|
|
|
|
|
|
# - perhaps I should have separate rules (but b and c produce the |
3247
|
|
|
|
|
|
|
# same output...) |
3248
|
|
|
|
|
|
|
# |
3249
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSStructInit0", |
3250
|
|
|
|
|
|
|
["NewXSSymTab","VTableName","IsAffineFlag","NoPdlThread"], |
3251
|
|
|
|
|
|
|
"Rule to create and initialise the private trans structure", |
3252
|
|
|
|
|
|
|
\&MkPrivStructInit), |
3253
|
|
|
|
|
|
|
|
3254
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSMakeNow", ["ParNames","NewXSSymTab"], \&MakeNows), |
3255
|
|
|
|
|
|
|
PDL::PP::Rule->new("IgnoreTypesOf", "FTypes", sub {return {map {($_,1)} keys %{$_[0]}}}), |
3256
|
|
|
|
|
|
|
PDL::PP::Rule::Returns->new("IgnoreTypesOf", {}), |
3257
|
|
|
|
|
|
|
|
3258
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSCoerceMustNS", "FTypes", \&make_newcoerce), |
3259
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("NewXSCoerceMust", "NewXSCoerceMustNS"), |
3260
|
|
|
|
|
|
|
|
3261
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("DefaultFlowCode", "DefaultFlowCodeNS"), |
3262
|
|
|
|
|
|
|
|
3263
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSFindDatatypeNS", |
3264
|
|
|
|
|
|
|
["ParNames","ParObjs","IgnoreTypesOf","NewXSSymTab","GenericTypes","_P2Child"], |
3265
|
|
|
|
|
|
|
\&find_datatype), |
3266
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("NewXSFindDatatype", "NewXSFindDatatypeNS"), |
3267
|
|
|
|
|
|
|
|
3268
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::EmptyString->new("NewXSTypeCoerce", "NoConversion"), |
3269
|
|
|
|
|
|
|
|
3270
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSTypeCoerceNS", |
3271
|
|
|
|
|
|
|
["ParNames","ParObjs","IgnoreTypesOf","NewXSSymTab","_P2Child"], |
3272
|
|
|
|
|
|
|
\&coerce_types), |
3273
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("NewXSTypeCoerce", "NewXSTypeCoerceNS"), |
3274
|
|
|
|
|
|
|
|
3275
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::EmptyString->new("NewXSStructInit1", ["ParNames","NewXSSymTab"]), |
3276
|
|
|
|
|
|
|
|
3277
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSSetTrans", ["ParNames","ParObjs","NewXSSymTab"], \&makesettrans), |
3278
|
|
|
|
|
|
|
|
3279
|
|
|
|
|
|
|
PDL::PP::Rule->new("ParsedCode", |
3280
|
|
|
|
|
|
|
["Code","_BadCode","ParNames","ParObjs","DimObjs","GenericTypes", |
3281
|
|
|
|
|
|
|
"ExtraGenericLoops","HaveThreading","Name"], |
3282
|
|
|
|
|
|
|
sub { return PDL::PP::Code->new(@_); }), |
3283
|
|
|
|
|
|
|
PDL::PP::Rule->new("ParsedBackCode", |
3284
|
|
|
|
|
|
|
["BackCode","_BadBackCode","ParNames","ParObjs","DimObjs","GenericTypes", |
3285
|
|
|
|
|
|
|
"ExtraGenericLoops","HaveThreading","Name"], |
3286
|
|
|
|
|
|
|
sub { return PDL::PP::Code->new(@_, undef, undef, 'BackCode2'); }), |
3287
|
|
|
|
|
|
|
|
3288
|
|
|
|
|
|
|
# Compiled representations i.e. what the xsub function leaves |
3289
|
|
|
|
|
|
|
# in the trans structure. By default, copies of the parameters |
3290
|
|
|
|
|
|
|
# but in many cases (e.g. slice) a benefit can be obtained |
3291
|
|
|
|
|
|
|
# by parsing the string in that function. |
3292
|
|
|
|
|
|
|
|
3293
|
|
|
|
|
|
|
# If the user wishes to specify his own code and compiled representation, |
3294
|
|
|
|
|
|
|
# The next two definitions allow this. |
3295
|
|
|
|
|
|
|
# Because of substitutions that will be there, |
3296
|
|
|
|
|
|
|
# makecompiledrepr et al are array refs, 0th element = string, |
3297
|
|
|
|
|
|
|
# 1th element = hashref of translated names |
3298
|
|
|
|
|
|
|
# This makes the objects: type + ... |
3299
|
|
|
|
|
|
|
# |
3300
|
|
|
|
|
|
|
PDL::PP::Rule->new(["CompNames","CompObjs"], "Comp", \&OtherPars_nft), |
3301
|
|
|
|
|
|
|
PDL::PP::Rule->new("CompiledRepr", ["CompNames","CompObjs"], \&NT2Decls_p), |
3302
|
|
|
|
|
|
|
PDL::PP::Rule::MakeComp->new("MakeCompiledRepr", ["MakeComp","CompNames","CompObjs"], |
3303
|
|
|
|
|
|
|
"COMP"), |
3304
|
|
|
|
|
|
|
|
3305
|
|
|
|
|
|
|
PDL::PP::Rule->new("CompCopyCode", ["CompNames","CompObjs","CopyName"], \&NT2Copies_p), |
3306
|
|
|
|
|
|
|
PDL::PP::Rule->new("CompFreeCode", ["CompNames","CompObjs"], \&NT2Free_p), |
3307
|
|
|
|
|
|
|
|
3308
|
|
|
|
|
|
|
# This is the default |
3309
|
|
|
|
|
|
|
# |
3310
|
|
|
|
|
|
|
PDL::PP::Rule->new("MakeCompiledRepr", |
3311
|
|
|
|
|
|
|
["OtherParNames","OtherParTypes","NewXSSymTab"], |
3312
|
|
|
|
|
|
|
\&CopyOtherPars), |
3313
|
|
|
|
|
|
|
PDL::PP::Rule->new("CompiledRepr", |
3314
|
|
|
|
|
|
|
["OtherParNames","OtherParTypes"], |
3315
|
|
|
|
|
|
|
\&NT2Decls), |
3316
|
|
|
|
|
|
|
PDL::PP::Rule->new("CompCopyCode", |
3317
|
|
|
|
|
|
|
["OtherParNames","OtherParTypes","CopyName"], |
3318
|
|
|
|
|
|
|
\&NT2Copies_p), |
3319
|
|
|
|
|
|
|
PDL::PP::Rule->new("CompFreeCode", ["OtherParNames","OtherParTypes"], \&NT2Free_p), |
3320
|
|
|
|
|
|
|
|
3321
|
|
|
|
|
|
|
# Threads |
3322
|
|
|
|
|
|
|
# |
3323
|
|
|
|
|
|
|
PDL::PP::Rule->new(["Priv","PrivIsInc"], |
3324
|
|
|
|
|
|
|
["ParNames","ParObjs","DimObjs","HaveThreading"], |
3325
|
|
|
|
|
|
|
\&make_incsizes), |
3326
|
|
|
|
|
|
|
PDL::PP::Rule->new("PrivCopyCode", |
3327
|
|
|
|
|
|
|
["ParNames","ParObjs","DimObjs","CopyName","HaveThreading"], |
3328
|
|
|
|
|
|
|
\&make_incsize_copy), |
3329
|
|
|
|
|
|
|
PDL::PP::Rule->new("PrivFreeCode", |
3330
|
|
|
|
|
|
|
["ParNames","ParObjs","DimObjs","HaveThreading"], |
3331
|
|
|
|
|
|
|
"Frees the thread", |
3332
|
|
|
|
|
|
|
\&make_incsize_free), |
3333
|
|
|
|
|
|
|
|
3334
|
|
|
|
|
|
|
PDL::PP::Rule::Returns->new("RedoDimsCode", [], |
3335
|
|
|
|
|
|
|
'Code that can be inserted to set the size of output piddles dynamically based on input piddles; is parsed', |
3336
|
|
|
|
|
|
|
'PDL_COMMENT("none")'), |
3337
|
|
|
|
|
|
|
PDL::PP::Rule->new("RedoDimsParsedCode", |
3338
|
|
|
|
|
|
|
["RedoDimsCode","_BadRedoDimsCode","ParNames","ParObjs","DimObjs", |
3339
|
|
|
|
|
|
|
"GenericTypes","ExtraGenericLoops","HaveThreading","Name"], |
3340
|
|
|
|
|
|
|
'makes the parsed representation from the supplied RedoDimsCode', |
3341
|
|
|
|
|
|
|
sub { |
3342
|
|
|
|
|
|
|
return 'PDL_COMMENT("no RedoDimsCode")' |
3343
|
|
|
|
|
|
|
if $_[0] =~ m|^/[*] none [*]/$|; |
3344
|
|
|
|
|
|
|
PDL::PP::Code->new(@_,1); }), |
3345
|
|
|
|
|
|
|
PDL::PP::Rule->new("RedoDims", |
3346
|
|
|
|
|
|
|
["ParNames","ParObjs","DimObjs","DimmedPars","RedoDimsParsedCode", '_NoPthread'], |
3347
|
|
|
|
|
|
|
'makes the redodims function from the various bits and pieces', |
3348
|
|
|
|
|
|
|
\&make_redodims_thread), |
3349
|
|
|
|
|
|
|
|
3350
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::EmptyString->new("Priv"), |
3351
|
|
|
|
|
|
|
|
3352
|
|
|
|
|
|
|
PDL::PP::Rule->new(["PrivNames","PrivObjs"], "Priv", \&OtherPars_nft), |
3353
|
|
|
|
|
|
|
PDL::PP::Rule->new("PrivateRepr", ["PrivNames","PrivObjs"], \&NT2Decls_p), |
3354
|
|
|
|
|
|
|
PDL::PP::Rule->new("PrivCopyCode", ["PrivNames","PrivObjs","CopyName"], \&NT2Copies_p), |
3355
|
|
|
|
|
|
|
|
3356
|
|
|
|
|
|
|
# avoid clash with freecode above? |
3357
|
|
|
|
|
|
|
# |
3358
|
|
|
|
|
|
|
PDL::PP::Rule->new("NTPrivFreeCode", ["PrivNames","PrivObjs"], \&NT2Free_p), |
3359
|
|
|
|
|
|
|
|
3360
|
|
|
|
|
|
|
PDL::PP::Rule->new("IsReversibleCodeNS", "Reversible", \&ToIsReversible), |
3361
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("IsReversibleCode", "IsReversibleCodeNS"), |
3362
|
|
|
|
|
|
|
|
3363
|
|
|
|
|
|
|
# Needs cleaning up. NewXSStructInit2DJB has been added to make use |
3364
|
|
|
|
|
|
|
# of the PDL::PP::Rule::Substitute class. |
3365
|
|
|
|
|
|
|
# |
3366
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute->new("NewXSStructInit2DJB", "MakeCompiledRepr"), |
3367
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSStructInit2", "NewXSStructInit2DJB", |
3368
|
|
|
|
|
|
|
sub { PDL::PP::pp_line_numbers(__LINE__, "{".$_[0]."}") }), |
3369
|
|
|
|
|
|
|
|
3370
|
|
|
|
|
|
|
PDL::PP::Rule->new("CopyCodeNS", |
3371
|
|
|
|
|
|
|
["PrivCopyCode","CompCopyCode","StructName","NoPdlThread"], |
3372
|
|
|
|
|
|
|
sub { |
3373
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, |
3374
|
0
|
|
|
|
|
|
"$_[2] *__copy = malloc(sizeof($_[2])); memset(__copy, 0, sizeof($_[2]));\n" . |
3375
|
0
|
|
|
|
|
|
($_[3] ? "" : "PDL_THR_CLRMAGIC(&__copy->__pdlthread);") . |
3376
|
0
|
|
|
|
|
|
" PDL_TR_CLRMAGIC(__copy); |
3377
|
0
|
|
|
|
|
|
__copy->has_badvalue = \$PRIV(has_badvalue); |
3378
|
0
|
|
|
|
|
|
__copy->badvalue = \$PRIV(badvalue); |
3379
|
0
|
|
|
|
|
|
__copy->flags = \$PRIV(flags); |
3380
|
0
|
|
|
|
|
|
__copy->vtable = \$PRIV(vtable); |
3381
|
0
|
|
|
|
|
|
__copy->__datatype = \$PRIV(__datatype); |
3382
|
0
|
|
|
|
|
|
__copy->freeproc = NULL; |
3383
|
|
|
|
|
|
|
__copy->__ddone = \$PRIV(__ddone); |
3384
|
0
|
0
|
|
|
|
|
{int i; |
3385
|
0
|
|
|
|
|
|
for(i=0; i<__copy->vtable->npdls; i++) |
3386
|
|
|
|
|
|
|
__copy->pdls[i] = \$PRIV(pdls[i]); |
3387
|
|
|
|
|
|
|
} |
3388
|
|
|
|
|
|
|
$_[1] |
3389
|
|
|
|
|
|
|
if(__copy->__ddone) { |
3390
|
|
|
|
|
|
|
$_[0] |
3391
|
|
|
|
|
|
|
} |
3392
|
|
|
|
|
|
|
return (pdl_trans*)__copy;") }), |
3393
|
|
|
|
|
|
|
|
3394
|
|
|
|
|
|
|
PDL::PP::Rule->new("FreeCodeNS", |
3395
|
|
|
|
|
|
|
["PrivFreeCode","CompFreeCode","NTPrivFreeCode"], |
3396
|
|
|
|
|
|
|
sub { |
3397
|
|
|
|
|
|
|
PDL::PP::pp_line_numbers(__LINE__, " |
3398
|
|
|
|
|
|
|
PDL_TR_CLRMAGIC(__privtrans); |
3399
|
8
|
|
|
|
|
|
$_[1] |
3400
|
|
|
|
|
|
|
if(__privtrans->__ddone) { |
3401
|
|
|
|
|
|
|
$_[0] |
3402
|
|
|
|
|
|
|
$_[2] |
3403
|
|
|
|
|
|
|
} |
3404
|
|
|
|
|
|
|
") }), |
3405
|
|
|
|
|
|
|
|
3406
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("CopyCode", "CopyCodeNS"), |
3407
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("FreeCode", "FreeCodeNS"), |
3408
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("FooCodeSub", "FooCode"), |
3409
|
|
|
|
|
|
|
|
3410
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::EmptyString->new("NewXSCoerceMust"), |
3411
|
|
|
|
|
|
|
|
3412
|
|
|
|
|
|
|
PDL::PP::Rule::MakeComp->new("NewXSCoerceMustSub1", "NewXSCoerceMust", "FOO"), |
3413
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute->new("NewXSCoerceMustSub1d", "NewXSCoerceMustSub1"), |
3414
|
|
|
|
|
|
|
|
3415
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSClearThread", "HaveThreading", |
3416
|
|
|
|
|
|
|
sub {$_[0] ? PDL::PP::pp_line_numbers(__LINE__, "__privtrans->__pdlthread.inds = 0;") : ""}), |
3417
|
14
|
|
|
|
|
|
|
3418
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSFindBadStatusNS", |
3419
|
|
|
|
|
|
|
["BadFlag","_FindBadStatusCode","NewXSArgs","USParObjs","OtherParTypes","NewXSSymTab","Name"], |
3420
|
|
|
|
|
|
|
"Rule to find the bad value status of the input piddles", |
3421
|
|
|
|
|
|
|
\&findbadstatus), |
3422
|
|
|
|
|
|
|
|
3423
|
|
|
|
|
|
|
# this can be removed once the default bad values are stored in a C structure |
3424
|
|
|
|
|
|
|
# (rather than as a perl array in PDL::Types) |
3425
|
|
|
|
|
|
|
# which it now is, hence the comments (DJB 07/10/00) |
3426
|
|
|
|
|
|
|
# - left around in case we move to per-piddle bad values |
3427
|
|
|
|
|
|
|
# - NOTE: now we have the experimental per-piddle bad values I need to remember |
3428
|
|
|
|
|
|
|
# what I was doing here |
3429
|
|
|
|
|
|
|
# [[NewXSCopyBadValues], [BadFlag,NewXSSymTab], |
3430
|
|
|
|
|
|
|
# "copybadvalues", |
3431
|
|
|
|
|
|
|
# "Rule to copy the default bad values into the trnas structure"], |
3432
|
|
|
|
|
|
|
|
3433
|
|
|
|
|
|
|
PDL::PP::Rule->new("NewXSCopyBadStatusNS", |
3434
|
|
|
|
|
|
|
["BadFlag","_CopyBadStatusCode","NewXSArgs","USParObjs","NewXSSymTab"], |
3435
|
|
|
|
|
|
|
"Rule to copy the bad value status to the output piddles", |
3436
|
|
|
|
|
|
|
\©badstatus), |
3437
|
|
|
|
|
|
|
|
3438
|
|
|
|
|
|
|
# expand macros in ...BadStatusCode |
3439
|
|
|
|
|
|
|
# |
3440
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("NewXSFindBadStatus", "NewXSFindBadStatusNS"), |
3441
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute::Usual->new("NewXSCopyBadStatus", "NewXSCopyBadStatusNS"), |
3442
|
|
|
|
|
|
|
|
3443
|
|
|
|
|
|
|
# Generates XS code with variable argument list. If this rule succeeds, the next rule |
3444
|
|
|
|
|
|
|
# will not be executed. D. Hunt 4/11/00 |
3445
|
|
|
|
|
|
|
# |
3446
|
|
|
|
|
|
|
PDL::PP::Rule->new(["NewXSCode","BootSetNewXS","NewXSInPrelude"], |
3447
|
|
|
|
|
|
|
["_GlobalNew","_NewXSCHdrs","VarArgsXSHdr","NewXSLocals", |
3448
|
|
|
|
|
|
|
"CacheBadFlagInit", |
3449
|
|
|
|
|
|
|
"NewXSStructInit0", |
3450
|
|
|
|
|
|
|
"NewXSFindBadStatus", |
3451
|
|
|
|
|
|
|
# NewXSCopyBadValues, |
3452
|
|
|
|
|
|
|
# NewXSMakeNow, # this is unnecessary since families never got implemented |
3453
|
|
|
|
|
|
|
"NewXSFindDatatype","NewXSTypeCoerce", |
3454
|
|
|
|
|
|
|
"NewXSStructInit1", |
3455
|
|
|
|
|
|
|
"NewXSStructInit2", |
3456
|
|
|
|
|
|
|
"NewXSCoerceMustSub1d","_IsReversibleCode","DefaultFlowCode", |
3457
|
|
|
|
|
|
|
"NewXSClearThread", |
3458
|
|
|
|
|
|
|
"NewXSSetTrans", |
3459
|
|
|
|
|
|
|
"NewXSCopyBadStatus", |
3460
|
|
|
|
|
|
|
"VarArgsXSReturn" |
3461
|
|
|
|
|
|
|
], |
3462
|
|
|
|
|
|
|
"Rule to print out XS code when variable argument list XS processing is enabled", |
3463
|
|
|
|
|
|
|
\&mkVarArgsxscat), |
3464
|
|
|
|
|
|
|
|
3465
|
|
|
|
|
|
|
# This rule will fail if the preceding rule succeeds |
3466
|
|
|
|
|
|
|
# D. Hunt 4/11/00 |
3467
|
|
|
|
|
|
|
# |
3468
|
|
|
|
|
|
|
PDL::PP::Rule->new(["NewXSCode","BootSetNewXS","NewXSInPrelude"], |
3469
|
|
|
|
|
|
|
["_GlobalNew","_NewXSCHdrs","NewXSHdr","NewXSLocals", |
3470
|
|
|
|
|
|
|
"CacheBadFlagInit", |
3471
|
|
|
|
|
|
|
"NewXSStructInit0", |
3472
|
|
|
|
|
|
|
"NewXSFindBadStatus", |
3473
|
|
|
|
|
|
|
# NewXSCopyBadValues, |
3474
|
|
|
|
|
|
|
# NewXSMakeNow, # this is unnecessary since families never got implemented |
3475
|
|
|
|
|
|
|
"NewXSFindDatatype","NewXSTypeCoerce", |
3476
|
|
|
|
|
|
|
"NewXSStructInit1", |
3477
|
|
|
|
|
|
|
"NewXSStructInit2", |
3478
|
|
|
|
|
|
|
"NewXSCoerceMustSub1d","_IsReversibleCode","DefaultFlowCode", |
3479
|
|
|
|
|
|
|
"NewXSClearThread", |
3480
|
|
|
|
|
|
|
"NewXSSetTrans", |
3481
|
|
|
|
|
|
|
"NewXSCopyBadStatus" |
3482
|
|
|
|
|
|
|
], |
3483
|
|
|
|
|
|
|
"Rule to print out XS code when variable argument list XS processing is disabled", |
3484
|
|
|
|
|
|
|
\&mkxscat), |
3485
|
|
|
|
|
|
|
|
3486
|
|
|
|
|
|
|
PDL::PP::Rule->new("StructDecl", |
3487
|
|
|
|
|
|
|
["ParNames","ParObjs","CompiledRepr","PrivateRepr","StructName"], |
3488
|
|
|
|
|
|
|
\&mkstruct), |
3489
|
|
|
|
|
|
|
|
3490
|
|
|
|
|
|
|
# The RedoDimsSub rule is a bit weird since it takes in the RedoDims target |
3491
|
|
|
|
|
|
|
# twice (directly and via RedoDims-PostComp). Can this be cleaned up? |
3492
|
|
|
|
|
|
|
# [I don't know who put this in, or when -- but I don't understand it. CED 13-April-2015] |
3493
|
|
|
|
|
|
|
PDL::PP::Rule->new("RedoDims-PreComp", "RedoDims", |
3494
|
|
|
|
|
|
|
sub { PDL::PP::pp_line_numbers(__LINE__, $_[0] . ' $PRIV(__ddone) = 1;') }), |
3495
|
|
|
|
|
|
|
PDL::PP::Rule::MakeComp->new("RedoDims-PostComp", |
3496
|
|
|
|
|
|
|
["RedoDims-PreComp", "PrivNames", "PrivObjs"], "PRIV"), |
3497
|
|
|
|
|
|
|
|
3498
|
|
|
|
|
|
|
# RedoDimsSub is supposed to allow you to use $SIZE as an lvalue, to resize things. It hasn't |
3499
|
|
|
|
|
|
|
# worked since I can remember (at least since I started messing around with range). The reason |
3500
|
|
|
|
|
|
|
# appears to be that the SIZE macro was using the redodims argument instead of its own zeroth |
3501
|
|
|
|
|
|
|
# argument. Renaming gone wrong? Anyway I've fixed it to use $_[0] instead of $redodims in the |
3502
|
|
|
|
|
|
|
# SIZE closure. -- CED 13-April-2015 |
3503
|
|
|
|
|
|
|
PDL::PP::Rule->new("RedoDimsSub", |
3504
|
|
|
|
|
|
|
["RedoDims", "RedoDims-PostComp", "_DimObjs"], |
3505
|
|
|
|
|
|
|
sub { |
3506
|
|
|
|
|
|
|
my $redodims = $_[0]; |
3507
|
|
|
|
|
|
|
my $result = $_[1]; |
3508
|
|
|
|
|
|
|
my $dimobjs = $_[2]; |
3509
|
|
|
|
|
|
|
|
3510
|
|
|
|
|
|
|
$result->[1]{"SIZE"} = sub { |
3511
|
|
|
|
|
|
|
eval 'use PDL::IO::Dumper'; |
3512
|
|
|
|
|
|
|
croak "FOO can't get SIZE of undefined dimension (RedoDims=$redodims).\nredodims is $redodims\ndimobjs is ".sdump($dimobjs)."\n" |
3513
|
|
|
|
|
|
|
unless defined $dimobjs->{$_[0]}; # This is the closure's $_[0], not the rule definition's $_[0] |
3514
|
|
|
|
|
|
|
return $dimobjs->{$_[0]}->get_size(); |
3515
|
|
|
|
|
|
|
}; |
3516
|
|
|
|
|
|
|
return $result; |
3517
|
|
|
|
|
|
|
}), |
3518
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute->new("RedoDimsSubd", "RedoDimsSub"), |
3519
|
|
|
|
|
|
|
PDL::PP::Rule->new("RedoDimsFunc", |
3520
|
|
|
|
|
|
|
["RedoDimsSubd","FHdrInfo","RedoDimsFuncName","_P2Child"], |
3521
|
|
|
|
|
|
|
sub {wrap_vfn(@_,"redodims")}), |
3522
|
|
|
|
|
|
|
|
3523
|
|
|
|
|
|
|
PDL::PP::Rule::MakeComp->new("ReadDataSub", "ParsedCode", "FOO"), |
3524
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute->new("ReadDataSubd", "ReadDataSub"), |
3525
|
|
|
|
|
|
|
PDL::PP::Rule->new("ReadDataFunc", |
3526
|
|
|
|
|
|
|
["ReadDataSubd","FHdrInfo","ReadDataFuncName","_P2Child"], |
3527
|
|
|
|
|
|
|
sub {wrap_vfn(@_,"readdata")}), |
3528
|
|
|
|
|
|
|
|
3529
|
|
|
|
|
|
|
PDL::PP::Rule::MakeComp->new("WriteBackDataSub", "ParsedBackCode", "FOO"), |
3530
|
|
|
|
|
|
|
PDL::PP::Rule::Substitute->new("WriteBackDataSubd", "WriteBackDataSub"), |
3531
|
|
|
|
|
|
|
|
3532
|
|
|
|
|
|
|
PDL::PP::Rule::InsertName->new("WriteBackDataFuncName", "BackCode", 'pdl_${name}_writebackdata'), |
3533
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::NULL->new("WriteBackDataFuncName", "Code"), |
3534
|
|
|
|
|
|
|
|
3535
|
|
|
|
|
|
|
PDL::PP::Rule->new("WriteBackDataFunc", |
3536
|
|
|
|
|
|
|
["WriteBackDataSubd","FHdrInfo","WriteBackDataFuncName","_P2Child"], |
3537
|
|
|
|
|
|
|
sub {wrap_vfn(@_,"writebackdata")}),, |
3538
|
|
|
|
|
|
|
|
3539
|
|
|
|
|
|
|
PDL::PP::Rule->new("CopyFunc", |
3540
|
|
|
|
|
|
|
["CopyCode","FHdrInfo","CopyFuncName","_P2Child"], |
3541
|
|
|
|
|
|
|
sub {wrap_vfn(@_,"copy")}), |
3542
|
|
|
|
|
|
|
PDL::PP::Rule->new("FreeFunc", |
3543
|
|
|
|
|
|
|
["FreeCode","FHdrInfo","FreeFuncName","_P2Child"], |
3544
|
|
|
|
|
|
|
sub {wrap_vfn(@_,"free")}), |
3545
|
|
|
|
|
|
|
|
3546
|
|
|
|
|
|
|
PDL::PP::Rule::Returns->new("FoofName", "FooCodeSub", "foomethod"), |
3547
|
|
|
|
|
|
|
PDL::PP::Rule->new("FooFunc", ["FooCodeSub","FHdrInfo","FoofName","_P2Child"], |
3548
|
|
|
|
|
|
|
sub {wrap_vfn(@_,"foo")}), |
3549
|
|
|
|
|
|
|
|
3550
|
|
|
|
|
|
|
PDL::PP::Rule::Returns::NULL->new("FoofName"), |
3551
|
|
|
|
|
|
|
|
3552
|
|
|
|
|
|
|
PDL::PP::Rule->new("VTableDef", |
3553
|
|
|
|
|
|
|
["VTableName","StructName","RedoDimsFuncName","ReadDataFuncName", |
3554
|
|
|
|
|
|
|
"WriteBackDataFuncName","CopyFuncName","FreeFuncName", |
3555
|
|
|
|
|
|
|
"ParNames","ParObjs","Affine_Ok","FoofName"], |
3556
|
|
|
|
|
|
|
\&def_vtable), |
3557
|
|
|
|
|
|
|
|
3558
|
|
|
|
|
|
|
# Maybe accomplish this with an InsertName rule? |
3559
|
|
|
|
|
|
|
PDL::PP::Rule->new('PMFunc', 'Name', |
3560
|
|
|
|
|
|
|
'Sets PMFunc to default symbol table manipulations', |
3561
|
|
|
|
|
|
|
sub { |
3562
|
|
|
|
|
|
|
my ($name) = @_; |
3563
|
|
|
|
|
|
|
$::PDL_IFBEGINWRAP[0].'*'.$name.' = \&'.$::PDLOBJ. |
3564
|
|
|
|
|
|
|
'::'.$name.";\n".$::PDL_IFBEGINWRAP[1] |
3565
|
|
|
|
|
|
|
} |
3566
|
|
|
|
|
|
|
), |
3567
|
|
|
|
|
|
|
|
3568
|
|
|
|
|
|
|
]; |
3569
|
|
|
|
|
|
|
|
3570
|
|
|
|
|
|
|
sub printtrans { |
3571
|
|
|
|
|
|
|
my($bar) = @_; |
3572
|
|
|
|
|
|
|
for (qw/StructDecl RedoDimsFunc ReadDataFunc WriteBackFunc |
3573
|
|
|
|
|
|
|
VTableDef NewXSCode/) { |
3574
|
|
|
|
|
|
|
print "\n\n================================================ |
3575
|
|
|
|
|
|
|
$_ |
3576
|
|
|
|
|
|
|
=========================================\n",$bar->{$_},"\n" if $::PP_VERBOSE; |
3577
|
|
|
|
|
|
|
} |
3578
|
|
|
|
|
|
|
} |
3579
|
|
|
|
|
|
|
|
3580
|
|
|
|
|
|
|
sub translate { |
3581
|
|
|
|
|
|
|
my ($pars,$tbl) = @_; |
3582
|
|
|
|
|
|
|
|
3583
|
|
|
|
|
|
|
foreach my $rule (@$tbl) { |
3584
|
|
|
|
|
|
|
$rule->apply($pars); |
3585
|
|
|
|
|
|
|
} |
3586
|
|
|
|
|
|
|
|
3587
|
|
|
|
|
|
|
# print Dumper($pars); |
3588
|
|
|
|
|
|
|
print "GOING OUT!\n" if $::PP_VERBOSE; |
3589
|
|
|
|
|
|
|
return $pars; |
3590
|
|
|
|
|
|
|
} # sub: translate() |
3591
|
|
|
|
|
|
|
|
3592
|
|
|
|
|
|
|
## End |
3593
|
|
|
|
|
|
|
# |