-
Notifications
You must be signed in to change notification settings - Fork 0
/
finddep_all.pro
173 lines (144 loc) · 5.27 KB
/
finddep_all.pro
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
;+
; PURPOSE:
; Recursively searches for all of the dependencies contained a file
; of IDL code. Useful for determing what files to include in a
; self-contained bundle of IDL code.
;
; INPUTS:
; start: The name of a file to find dependencies for.
; count: On output, will hold the number of found dependencies.
;
; KEYWORD PARAMETERS:
; only_source: If set, only return dependencies for which
; corresponding source code is found. This will filter out
; dependencies to IDL built in functions (like print), but will also
; ignore potentially problematic missing dependencies.
;
; no_source: If set, only return dependencies for which corresponding
; source code is not found. This will return calls to built-in
; functions, as well as missing dependencies.
;
; no_builtin: If set, this will remove entries corresponding
; to calls to built-in IDL calls/procedures like print. This keyword
; can be used in addition to only_source and no_source.
;
; OUTPUTS:
; A structure array corresponding to each time a function/procedure
; call was detected. The structure has the following tags:
; func: The name of a function/procedure recognized as a dependency
; source: The path of the IDL file that was found to contain the
; code for func, if found. Otherwise, the empty string
;
; RESTRICTIONS:
; This code inherits all the restrictions in finddep_line. Please see
; that file for details. Caveat emptor.
;
; MODIFICATION HISTORY:
; January 2011: Written by Chris Beaumont
;-
function finddep_all, start, count, only_source = only_source, no_source = no_source, $
no_builtin = no_builtin
compile_opt idl2
on_error, 2
count = 0
if n_params() eq 0 || n_params() gt 2 then begin
print, 'Calling sequence:'
print, 'result = finddep_all(start, [count, /only_source, /no_source])'
return, !values.f_nan
endif
if keyword_set(only_source) && keyword_set(no_source) then $
message, 'Cannot set /only_source and /no_source'
todo = obj_new('stack') ;- holds list of dependencies to resolve
result_hash = obj_new('hashtable') ;- hold structure list of dependencies
done = obj_new('hashtable') ;- holds list of already-processed deps
rec={func:'', source:''}
;- find dependencies, schedule them for processing
dep = finddep_file(start, count, definition = d, defct = dct)
if count ne 0 then todo->push, dep
;- for each dependency, create an empty entry in result_hash
for i = 0, count - 1, 1 do $
result_hash->add, dep[i], {func:dep[i], source:''}, /replace
;- for each definition, create a full entry in result_hash
for i = 0, dct - 1, 1 do begin
result_hash->add, d[i], {func:d[i], source:start}, /replace
done->add, d[i]
endfor
;- process the next dependency
while ~todo->isEmpty() do begin
func = todo->pop()
func = func[0]
;- skip case 1-- already visited
if done->iscontained(func) then continue
done->add, func, 1
entry = result_hash->get(func)
;- sanity check -- can't get here if we've already
;- resolved the dependency
assert, entry.source eq '', 'Already processed dependency'
;- guess at file
file = (file_which(func+'.pro'))[0]
;- skip case 2-- can't find source code
if ~file_test(file) then continue
;- process depdendencies for new file
dep = finddep_file(file, count, definition = d, defct = dct)
assert, size(dep, /type) eq 7
;- schedule new dependencies
if count ne 0 then todo->push, dep
for i = 0, count - 1, 1 do begin
if result_hash->iscontained(dep[i]) then continue
result_hash->add, dep[i], {func:dep[i], source:''}, /replace
endfor
;- process new file definitions
for i = 0, dct - 1, 1 do begin
result_hash->add, d[i], {func:d[i], source:file}, /replace
done->add, d[i], 1
endfor
endwhile
obj_destroy, [todo, done]
;- convert hashtable to structure array
k = result_hash->keys()
count = n_elements(k)
if count eq 0 then begin
obj_destroy, result_hash
return, rec
endif
result = replicate(rec, count)
for i = 0, n_elements(k)-1 do result[i] = result_hash->get(k[i])
obj_destroy, result_hash
s = sort(result.func)
result = result[s]
if keyword_set(only_source) then begin
good = where(result.source ne '', count)
if count ne 0 then result = result[good] $
else result = rec
endif
if keyword_set(no_source) then begin
good = where(result.source eq '', count)
if count ne 0 then result = result[good] $
else result = rec
endif
if keyword_set(no_builtin) then begin
builtin = finddep_builtin()
builtin = builtin[sort(builtin)]
ind = value_locate(builtin, result.func) > 0
good = builtin[ind] ne result.func
hit = where(good, count)
if count ne 0 then result = result[hit] $
else result = rec
endif
;- some blank entries have been creeping in.
;- remove them.
good = where(result.func ne '', count)
if count ne 0 then result = result[good] $
else result = rec
return, result
end
pro test
d = finddep_all('finddep_all.pro')
s = sort(d.func)
d = d[s]
for i = 0, n_elements(d) - 1, 1 do begin
p = strsplit(d[i].source, '/', /extract)
p = p[n_elements(p)-1]
print, d[i].func, p, format='(a15, 5x, a25)'
endfor
end