line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
=head1 NAME |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
PDL::AutoLoader - MatLab style AutoLoader for PDL |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
=head1 SYNOPSIS |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
use PDL::AutoLoader; |
9
|
|
|
|
|
|
|
$x = func1(...); # Load file func1.pdl |
10
|
|
|
|
|
|
|
$y = func2(...); # Load file func2.pdl |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
$PDL::AutoLoader::Rescan = 1; # Enable re-scanning |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 DESCRIPTION |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
This module implements a MatLab style AutoLoader for PDL. If an unknown |
17
|
|
|
|
|
|
|
function C is called, PDL looks for a file called C. |
18
|
|
|
|
|
|
|
If it finds one, it compiles the file and calls the function C. |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
The list of directories to search in is given by the shell environment |
21
|
|
|
|
|
|
|
variable C. This is a colon-separated list of directories. On |
22
|
|
|
|
|
|
|
MSWindows systems, is it a I -separated list of directories. |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
For example, in csh: |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
setenv PDLLIB "/home/joe/pdllib:/local/pdllib" |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
B: This variable is unrelated to Perl's C. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
If you add a leading '+' on a directory name, PDL will search the |
31
|
|
|
|
|
|
|
entire directory tree below that point. Internally, PDL stores the |
32
|
|
|
|
|
|
|
directory list in the variable C<@PDLLIB>, which can be modified at |
33
|
|
|
|
|
|
|
run time. |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
For example, in csh: |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
setenv PDLLIB "+/home/joe/PDL" |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
will search /home/joe/PDL and all its subdirectories for .pdl files. |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head2 AUTO-SCANNING |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
The variable C<$PDL::AutoLoader::Rescan> controls whether files |
44
|
|
|
|
|
|
|
are automatically re-scanned for changes at the C or |
45
|
|
|
|
|
|
|
C command line. |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
If C<$PDL::AutoLoader::Rescan == 1> and the file is changed |
48
|
|
|
|
|
|
|
then the new definition is reloaded auto-matically before |
49
|
|
|
|
|
|
|
executing the C or C command line. Which means |
50
|
|
|
|
|
|
|
in practice you can edit files, save changes and have C |
51
|
|
|
|
|
|
|
or C see the changes automatically. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
The default is '0' - i.e. to have this feature disabled. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
As this feature is only pertinent to the PDL shell it imposes |
56
|
|
|
|
|
|
|
no overhead on PDL scripts. Yes Bob you can have your cake and |
57
|
|
|
|
|
|
|
eat it too! |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
Note: files are only re-evaled if they are determined to have |
60
|
|
|
|
|
|
|
been changed according to their date/time stamp. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
No doubt this interface could be improved upon some more. :-) |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=head2 Sample file: |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub foo { # file 'foo.pdl' - define the 'foo' function |
67
|
|
|
|
|
|
|
my $x=shift; |
68
|
|
|
|
|
|
|
return sqrt($x**2 + $x**3 + 2); |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
1; # File returns true (i.e. loaded successfully) |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head1 AUTHOR |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Copyright(C) 1997 Karl Glazebrook (kgb@aaoepp.aao.gov.au); |
75
|
|
|
|
|
|
|
several extensions by Craig DeForest (deforest@boulder.swri.edu) |
76
|
|
|
|
|
|
|
All rights reserved. There is no warranty. You are allowed |
77
|
|
|
|
|
|
|
to redistribute this software / documentation under certain |
78
|
|
|
|
|
|
|
conditions. For details, see the file COPYING in the PDL |
79
|
|
|
|
|
|
|
distribution. If this file is separated from the PDL distribution, |
80
|
|
|
|
|
|
|
the copyright notice should be included in the file. |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=head1 BUGS |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
No doubt this interface could be improved upon some more. :-) |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Will probably be quite slow if C<$PDL::AutoLoader::Rescan == 1> |
87
|
|
|
|
|
|
|
and thousands of functions have been autoloaded. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
There could be a race condition in which the file changes |
90
|
|
|
|
|
|
|
while the internal autoloader code is being executed but it |
91
|
|
|
|
|
|
|
should be harmless. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
Probably has not been tested enough! |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=head1 SEE ALSO |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
For an alternative approach to managing a personal collaction of |
98
|
|
|
|
|
|
|
modules and functions, see L. |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=cut |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
BEGIN{ |
103
|
1
|
50
|
|
1
|
|
1800
|
if (defined $ENV{"PDLLIB"}) { |
104
|
0
|
0
|
|
|
|
0
|
if ( $^O eq 'MSWin32' ) { # win32 flavors |
105
|
0
|
|
|
|
|
0
|
@PDLLIB = (".",split(';',$ENV{"PDLLIB"})); |
106
|
0
|
|
|
|
|
0
|
s/"//g for @PDLLIB; |
107
|
|
|
|
|
|
|
} else { # unixen systems |
108
|
0
|
|
|
|
|
0
|
@PDLLIB = (".",split(':',$ENV{"PDLLIB"})); |
109
|
|
|
|
|
|
|
} |
110
|
0
|
|
|
|
|
0
|
@PDLLIB = grep length, @PDLLIB; |
111
|
|
|
|
|
|
|
} |
112
|
1
|
|
|
|
|
3
|
$PDL::AutoLoader::Rescan=0; |
113
|
1
|
|
|
|
|
839
|
%PDL::AutoLoader::FileInfo = (); |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
# Code to reload stuff if changed |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub PDL::AutoLoader::reloader { |
119
|
0
|
0
|
|
0
|
0
|
0
|
return unless $PDL::AutoLoader::Rescan; |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# Now check functions and reload if changed |
122
|
|
|
|
|
|
|
|
123
|
0
|
|
|
|
|
0
|
my ($file, $old_t); |
124
|
0
|
|
|
|
|
0
|
for my $func (keys %PDL::AutoLoader::FileInfo) { |
125
|
0
|
|
|
|
|
0
|
($file, $old_t) = @{ $PDL::AutoLoader::FileInfo{$func} }; |
|
0
|
|
|
|
|
0
|
|
126
|
0
|
0
|
|
|
|
0
|
if ( (stat($file))[9]>$old_t ) { # Reload |
127
|
0
|
0
|
|
|
|
0
|
print "Reloading $file as file changed...\n" if $PDL::verbose; |
128
|
0
|
|
|
|
|
0
|
&PDL::AutoLoader::autoloader_do($file); |
129
|
0
|
|
|
|
|
0
|
$PDL::AutoLoader::FileInfo{$func} = [ $file, (stat($file))[9] ]; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# Used for Beta, and should probably be used generall in this mod |
135
|
|
|
|
|
|
|
#use File::Spec; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub PDL::AutoLoader::import { |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# Beta folder support |
140
|
|
|
|
|
|
|
# foreach (@INC) { |
141
|
|
|
|
|
|
|
# $Beta_dir = File::Spec->catfile($_, 'PDL', 'Beta'); |
142
|
|
|
|
|
|
|
# push @PDLLIB, "+$Beta_dir" if -d $Beta_dir; |
143
|
|
|
|
|
|
|
# } |
144
|
|
|
|
|
|
|
|
145
|
1
|
|
|
1
|
|
13
|
my $pkg = (caller())[0]; |
146
|
1
|
|
|
|
|
3
|
my $toeval = "package $pkg;\n"; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# Make sure that the eval gets NiceSlice if we have it in this level |
149
|
|
|
|
|
|
|
# (it's a drag that preprocessors aren't transitive...) |
150
|
1
|
50
|
|
|
|
6
|
$toeval .= "use PDL::NiceSlice;\n" if(defined $PDL::NiceSlice::VERSION); |
151
|
|
|
|
|
|
|
|
152
|
1
|
|
|
|
|
4
|
$toeval .= <<'EOD'; |
153
|
|
|
|
|
|
|
$PDLLIB_CT = 0; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
push @PERLDL::AUTO, \&PDL::AutoLoader::reloader; |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub AUTOLOAD { |
159
|
|
|
|
|
|
|
local @INC = @INC; |
160
|
|
|
|
|
|
|
my @args = @_; |
161
|
|
|
|
|
|
|
$AUTOLOAD =~ /::([^:]*)$/; |
162
|
|
|
|
|
|
|
my $func = $1; |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# Trap spurious calls from 'use UnknownModule' |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
goto &$AUTOLOAD if ord($func)==0; |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# Check if the PDLLIB needs to be expanded and, if so, expand it. |
169
|
|
|
|
|
|
|
# This only updates when PDLLIB changes size, which should be OK |
170
|
|
|
|
|
|
|
# for most things but doesn't catch new directories in expanded |
171
|
|
|
|
|
|
|
# directory trees. It seems like an OK compromise between never |
172
|
|
|
|
|
|
|
# catching anything and always thrashing through the directories. |
173
|
|
|
|
|
|
|
if($PDLLIB_CT != scalar(@PDLLIB)) { |
174
|
|
|
|
|
|
|
@PDLLIB_EXPANDED = PDL::AutoLoader::expand_path(@PDLLIB); |
175
|
|
|
|
|
|
|
$PDLLIB_CT = scalar(@PDLLIB); |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
print "Loading $func.pdl ..." if $PDL::verbose; |
179
|
|
|
|
|
|
|
my $file; |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
my $s = "PDL AutoLoader: Undefined subroutine $func() cannot be autoloaded.\n"; |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
for my $dir (@PDLLIB_EXPANDED) { |
184
|
|
|
|
|
|
|
$file = $dir . "/" . "$func.pdl"; |
185
|
|
|
|
|
|
|
if (-e $file) { |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
print "found $file\n" if $PDL::verbose; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
&PDL::AutoLoader::autoloader_do($file); |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
# Remember autoloaded functions and do some reasonably |
193
|
|
|
|
|
|
|
# smart cacheing of file/directory change times |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
if ($PDL::AutoLoader::Rescan) { |
196
|
|
|
|
|
|
|
$PDL::AutoLoader::FileInfo{$func} = [ $file, (stat($file))[9] ]; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
# Now go to the autoload function |
200
|
|
|
|
|
|
|
##goto &$AUTOLOAD(@args) unless ($@ || !defined(&{$AUTOLOAD})); |
201
|
|
|
|
|
|
|
return &$AUTOLOAD(@args) unless ($@ || !defined(&{$AUTOLOAD})); |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
die $s."\tWhile parsing file `$file':\n$@\n" if($@); |
204
|
|
|
|
|
|
|
die $s."\tFile `$file' doesn't \n\tdefine ${AUTOLOAD}().\n" |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
die $s."\tNo file `$func.pdl' was found in your \@PDLLIB path.\n"; |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
EOD |
213
|
|
|
|
|
|
|
|
214
|
1
|
50
|
33
|
1
|
|
8
|
eval $toeval; |
|
1
|
50
|
|
1
|
|
2
|
|
|
1
|
50
|
|
|
|
9
|
|
|
1
|
50
|
|
|
|
61
|
|
|
1
|
50
|
|
|
|
58
|
|
|
1
|
50
|
|
|
|
4
|
|
|
1
|
0
|
|
|
|
6
|
|
|
1
|
50
|
|
|
|
3
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
28
|
|
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
6
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
27
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# Simple 'do' doesn't work with preprocessing -- this replaces |
220
|
|
|
|
|
|
|
# "do file" and sticks NiceSlice in manually if it's needed (yuck). |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
sub PDL::AutoLoader::autoloader_do { |
223
|
1
|
|
|
1
|
0
|
4
|
my ($file) = shift; |
224
|
|
|
|
|
|
|
|
225
|
1
|
50
|
|
|
|
4
|
if(defined($PDL::NiceSlice::VERSION)) { |
226
|
|
|
|
|
|
|
|
227
|
1
|
50
|
|
|
|
11
|
print "AutoLoader: NiceSlice enabled...\n" if($PDL::debug); |
228
|
|
|
|
|
|
|
|
229
|
1
|
50
|
|
|
|
42
|
if(open(AUTOLOAD_FILE,"<$file")) { |
230
|
1
|
|
|
|
|
41
|
my($script) = &PDL::NiceSlice::perldlpp("PDL::NiceSlice", join("",)); |
231
|
1
|
|
|
1
|
|
126
|
eval $script; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
126
|
|
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
} else { |
234
|
0
|
0
|
|
|
|
0
|
print "AutoLoader: no NiceSlice...\n" if($PDL::debug); |
235
|
0
|
|
|
|
|
0
|
do $file; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
# Expand directories recursively... |
241
|
|
|
|
|
|
|
sub PDL::AutoLoader::expand_dir { |
242
|
0
|
|
|
0
|
0
|
0
|
local $d; |
243
|
0
|
|
|
|
|
0
|
local @list; |
244
|
0
|
|
|
|
|
0
|
local @subdirs; |
245
|
|
|
|
|
|
|
|
246
|
0
|
|
|
|
|
0
|
local $dir = shift; |
247
|
|
|
|
|
|
|
|
248
|
0
|
0
|
|
|
|
0
|
if(! -d $dir) { return undef; } |
|
0
|
|
|
|
|
0
|
|
249
|
0
|
|
|
|
|
0
|
push(@list,$dir); |
250
|
|
|
|
|
|
|
|
251
|
0
|
|
|
|
|
0
|
opendir(FOO,$dir); |
252
|
|
|
|
|
|
|
|
253
|
0
|
|
0
|
|
|
0
|
@subdirs = grep((!m/^\./ && ($_="$dir/$_") && (-d $_)), readdir(FOO)); |
254
|
0
|
|
|
|
|
0
|
closedir FOO; |
255
|
|
|
|
|
|
|
|
256
|
0
|
|
|
|
|
0
|
while(defined ($d = shift @subdirs)) { |
257
|
0
|
|
|
|
|
0
|
push(@list,&PDL::AutoLoader::expand_dir($d)); |
258
|
|
|
|
|
|
|
} |
259
|
0
|
|
|
|
|
0
|
return @list; |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=head2 PDL::AutoLoader::expand_path |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=for ref |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
Expand a compactified path into a dir list |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
You supply a pathlist and leading '+' and '~' characters get expanded into |
270
|
|
|
|
|
|
|
full directories. Normally you don't want to use this -- it's internal to the |
271
|
|
|
|
|
|
|
autoloader -- but some utilities, like the online documentation searcher, need |
272
|
|
|
|
|
|
|
to be able to use it. |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=cut |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub PDL::AutoLoader::expand_path { |
277
|
2
|
|
|
2
|
1
|
6
|
my @PDLLIB = @_; |
278
|
2
|
|
|
|
|
5
|
my @PDLLIB_EXPANDED; |
279
|
|
|
|
|
|
|
|
280
|
2
|
50
|
|
|
|
56
|
print "AutoLoader: Expanding directories from ".join(':',@PDLLIB)."...\n" |
281
|
|
|
|
|
|
|
if($PDL::debug); |
282
|
2
|
|
|
|
|
9
|
local $_; |
283
|
2
|
|
|
|
|
6
|
foreach $_(@PDLLIB) { |
284
|
|
|
|
|
|
|
# Expand ~{name} and ~ conventions. |
285
|
2
|
100
|
|
|
|
15
|
if(s/^(\+?)\~(\+||[a-zA-Z0-9]*)//) { |
286
|
1
|
50
|
|
|
|
9
|
if($2 eq '+') { |
|
|
50
|
|
|
|
|
|
287
|
|
|
|
|
|
|
# Expand shell '+' to CWD. |
288
|
0
|
|
0
|
|
|
0
|
$_= $1 . ($ENV{'PWD'} || '.'); |
289
|
|
|
|
|
|
|
} elsif(!$2) { |
290
|
|
|
|
|
|
|
# No name mentioned -- use current user. |
291
|
|
|
|
|
|
|
# Ideally would use File::HomeDir->my_home() here |
292
|
1
|
|
33
|
|
|
8
|
$_ = $1 . ( $ENV{'HOME'} || (( getpwnam( getlogin || getpwuid($<) ))[7]) ) . $_; |
293
|
|
|
|
|
|
|
} else { |
294
|
|
|
|
|
|
|
# Name mentioned - try to get that user's home directory. |
295
|
0
|
|
|
|
|
0
|
$_ = $1 . ( (getpwnam($2))[7] ) . $_; |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# If there's a leading '+', include all subdirs too. |
300
|
2
|
50
|
|
|
|
14
|
push(@PDLLIB_EXPANDED, |
301
|
|
|
|
|
|
|
s/^\+// ? &PDL::AutoLoader::expand_dir($_) : $_ |
302
|
|
|
|
|
|
|
); |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
2
|
50
|
|
|
|
23
|
print "AutoLoader: returning ",join(",",@PDLLIB_EXPANDED),"\n" if($PDL::debug); |
306
|
2
|
|
|
|
|
39
|
@PDLLIB_EXPANDED; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
;# Exit with OK status |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
1; |