codegraph 0.7.12 → 0.7.16
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/codegraph +14 -4
- data/gemspec +3 -1
- data/lib/codegraph.rb +96 -44
- metadata +3 -3
data/bin/codegraph
CHANGED
@@ -1,7 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require "codegraph"
|
3
|
-
require "optparse"
|
4
|
-
|
5
2
|
# Which options are availabile ------------------------------------------------
|
6
3
|
# Default settings
|
7
4
|
$options = {
|
@@ -14,6 +11,10 @@ require "optparse"
|
|
14
11
|
:excludes => [],
|
15
12
|
:debug => false
|
16
13
|
}
|
14
|
+
|
15
|
+
require "codegraph"
|
16
|
+
require "optparse"
|
17
|
+
|
17
18
|
def parse(args)
|
18
19
|
OptionParser.new do |opts|
|
19
20
|
opts.banner = "Usage: codegraph [options]"
|
@@ -38,6 +39,15 @@ def parse(args)
|
|
38
39
|
$options[:function] = func
|
39
40
|
$options[:mode] = 8
|
40
41
|
end
|
42
|
+
opts.on("-C", "--ctags-opts KIND",String) do |opts|
|
43
|
+
$options[:ctagsopts] = opts
|
44
|
+
end
|
45
|
+
opts.on("--match-before REGEXP",String) do |regexp|
|
46
|
+
$options[:matchBefore] = regexp
|
47
|
+
end
|
48
|
+
opts.on("--match-after REGEXP",String) do |regexp|
|
49
|
+
$options[:matchAfter] = regexp
|
50
|
+
end
|
41
51
|
opts.on("-F", "--file-list file0,file1,file3", Array,"List of files (alternative \"file0 file1 file3\")") do |filelist|
|
42
52
|
filelist.each do |filedesc|
|
43
53
|
unless File.exist?(filedesc)
|
@@ -86,7 +96,7 @@ def parse(args)
|
|
86
96
|
|
87
97
|
if $options[:files].flatten.empty?
|
88
98
|
warn 'Please use -F do define input files! Use -h for further help.'
|
89
|
-
exit
|
99
|
+
exit -1
|
90
100
|
end
|
91
101
|
$options
|
92
102
|
end
|
data/gemspec
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
|
+
|
4
|
+
|
3
5
|
spec = Gem::Specification.new do |s|
|
4
6
|
s.name = "codegraph"
|
5
|
-
s.version = "0.
|
7
|
+
s.version = File.open("lib/codegraph.rb").readlines.grep(/VERSION/)[0].split('=').last.chomp.strip.tr("'",'')
|
6
8
|
s.date = Time.new.to_s
|
7
9
|
s.platform = Gem::Platform::RUBY
|
8
10
|
s.bindir = 'bin'
|
data/lib/codegraph.rb
CHANGED
@@ -4,10 +4,12 @@ require 'rgl/dot'
|
|
4
4
|
require 'rgl/rdot'
|
5
5
|
require 'rgl/traversal'
|
6
6
|
require 'thread'
|
7
|
+
require 'digest'
|
7
8
|
require 'asciify'
|
9
|
+
require 'json'
|
8
10
|
|
9
11
|
module Codegraph
|
10
|
-
VERSION = '0.7.
|
12
|
+
VERSION = '0.7.16'
|
11
13
|
end
|
12
14
|
|
13
15
|
class FunctionGraph < RGL::DirectedAdjacencyGraph
|
@@ -23,10 +25,14 @@ class FunctionGraph < RGL::DirectedAdjacencyGraph
|
|
23
25
|
'label' => '',
|
24
26
|
'fontsize' => '12'}
|
25
27
|
|
26
|
-
@@home
|
27
|
-
@@codehomedir
|
28
|
-
@@
|
29
|
-
@@
|
28
|
+
@@home = ENV['HOME']
|
29
|
+
@@codehomedir = "#{@@home}/.codegraph"
|
30
|
+
@@filesDB = @@codehomedir+'/filesDB.json'
|
31
|
+
@@funxDB = @@codehomedir+'/funxDB.json'
|
32
|
+
|
33
|
+
@@matchBeforFuncName = $options[:matchBefor].nil? ? '[^A-z0-9_]\s*': $options[:matchBefor]
|
34
|
+
@@matchAfterFuncName = $options[:matchAfter].nil? ? '( *\(| |$)' : $options[:matchAfter]
|
35
|
+
|
30
36
|
@@map = Asciify::Mapping.new(:default)
|
31
37
|
|
32
38
|
# Generate the codegraph storage directory
|
@@ -36,10 +42,16 @@ class FunctionGraph < RGL::DirectedAdjacencyGraph
|
|
36
42
|
|
37
43
|
def initialize
|
38
44
|
super
|
39
|
-
@debug
|
45
|
+
@debug = false
|
40
46
|
# the following attribute will hold the functionnames and their bodies
|
41
|
-
@funx
|
42
|
-
@lock
|
47
|
+
@funx = Hash.new
|
48
|
+
@lock = Mutex.new
|
49
|
+
@filesDB = File.exist?(@@filesDB) ? JSON.parse(File.open(@@filesDB).read) : Hash.new
|
50
|
+
@filesCk = @db.hash
|
51
|
+
@funxDB = File.exist?(@@funxDB) ? JSON.parse(File.open(@@funxDB).read) : Hash.new
|
52
|
+
@funxCk = @funxDB.hash
|
53
|
+
|
54
|
+
@adds, @excludes = [],[]
|
43
55
|
end
|
44
56
|
|
45
57
|
# Generates the necessary files:
|
@@ -52,31 +64,43 @@ class FunctionGraph < RGL::DirectedAdjacencyGraph
|
|
52
64
|
filelist.each {|file|
|
53
65
|
threads << Thread.new(file, @@codehomedir) {|file,codehomedir|
|
54
66
|
funxFile = "funxnames"
|
55
|
-
ctagsKinds = '--c-kinds=f --fortran-kinds=
|
67
|
+
ctagsKinds = $options[:ctagsopts].nil? ? '--c-kinds=f --fortran-kinds=fsip --php-kinds=f --perl-kinds=f' : $options[:ctagsopts]
|
56
68
|
|
57
69
|
puts "Processing #{file} ..." if @debug
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
when '.c','.h'
|
62
|
-
cppCommand = "cpp -w -fpreprocessed -E -fdirectives-only #{file} -o #{codehomedir}/#{temfile} 2>/dev/null"
|
63
|
-
cppCommand = "cpp -fpreprocessed #{file} -o #{codehomedir}/#{temfile} 2>/dev/null"
|
64
|
-
grep = "grep -v -e '^$' #{codehomedir}/#{temfile} | grep -v -e '^#' > #{codehomedir}/#{basefile}"
|
65
|
-
when '.f','.f77','.f90','.f95'
|
66
|
-
cppCommand = "cp #{file} #{codehomedir}/#{temfile}"
|
67
|
-
grep = "grep -v -e '^$' #{codehomedir}/#{temfile} | grep -v -e '^ *!' > #{codehomedir}/#{basefile}"
|
70
|
+
checksum = Digest::SHA256.file(file).hexdigest
|
71
|
+
if @filesDB.has_key?(checksum)
|
72
|
+
code,funxLocations = @filesDB[checksum]
|
68
73
|
else
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
+
basefile = File.basename(file)
|
75
|
+
tempfile = "_" + basefile
|
76
|
+
case File.extname(file)
|
77
|
+
when '.c','.h'
|
78
|
+
cppCommand = "cpp -w -fpreprocessed -E -fdirectives-only #{file} -o #{codehomedir}/#{tempfile} 2>/dev/null"
|
79
|
+
cppCommand = "cpp -fpreprocessed #{file} -o #{codehomedir}/#{tempfile} 2>/dev/null"
|
80
|
+
grep = "grep -v -e '^$' #{codehomedir}/#{tempfile} | grep -v -e '^#' > #{codehomedir}/#{basefile}"
|
81
|
+
when '.f','.f77','.f90','.f95'
|
82
|
+
cppCommand = "cp #{file} #{codehomedir}/#{tempfile}"
|
83
|
+
grep = "grep -v -e '^$' #{codehomedir}/#{tempfile} | grep -v -e '^ *!' > #{codehomedir}/#{basefile}"
|
84
|
+
else
|
85
|
+
cppCommand = "cp #{file} #{codehomedir}/#{tempfile}"
|
86
|
+
grep = "grep -v -e '^$' #{codehomedir}/#{tempfile} | grep -v -e '^#' > #{codehomedir}/#{basefile}"
|
87
|
+
end
|
88
|
+
gen4ctags = "ctags -x #{ctagsKinds} #{codehomedir}/#{basefile} | sort -n -k 3"
|
89
|
+
command = [cppCommand,grep].join(";")
|
74
90
|
|
75
|
-
|
76
|
-
|
91
|
+
puts gen4ctags if @debug
|
92
|
+
puts command if @debug
|
93
|
+
system(command)
|
94
|
+
|
95
|
+
code = open(codehomedir+'/'+ File.basename(file)).readlines
|
96
|
+
funxLocations = IO.popen(gen4ctags).readlines.map {|l| l.split[0,4]}
|
97
|
+
@lock.synchronize { @filesDB[checksum] = [code,funxLocations] }
|
98
|
+
|
99
|
+
# cleanup
|
100
|
+
FileUtils.rm("#{codehomedir}/#{tempfile}")
|
101
|
+
FileUtils.rm("#{codehomedir}/#{basefile}")
|
102
|
+
end
|
77
103
|
|
78
|
-
code = open(codehomedir+'/'+ File.basename(file)).readlines
|
79
|
-
funxLocations = IO.popen(gen4ctags).readlines.map {|l| l.split[0,4]}
|
80
104
|
funxLocations.each_with_index {|ary,i|
|
81
105
|
name, kind, line, file = ary
|
82
106
|
puts name if @debug
|
@@ -92,9 +116,12 @@ class FunctionGraph < RGL::DirectedAdjacencyGraph
|
|
92
116
|
}
|
93
117
|
threads.each {|t| t.join}
|
94
118
|
|
119
|
+
# update the code database in case of anything new
|
120
|
+
updateFilesDB
|
121
|
+
|
95
122
|
if @funx.empty?
|
96
|
-
|
97
|
-
exit
|
123
|
+
warn "no functions found"
|
124
|
+
exit -1
|
98
125
|
end
|
99
126
|
end
|
100
127
|
|
@@ -108,16 +135,34 @@ class FunctionGraph < RGL::DirectedAdjacencyGraph
|
|
108
135
|
# scan functions for the function names
|
109
136
|
names = @funx.keys
|
110
137
|
@funx.each_pair {|name,body|
|
111
|
-
# threads <<
|
138
|
+
# threads=[];threads << Thread.new(name,body,names) {|name,body,names|
|
112
139
|
puts "Add func: #{name}" if @debug
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
140
|
+
# Check if this body is in the funx DB
|
141
|
+
bodyCk = Digest::SHA256.hexdigest(body)
|
142
|
+
if @funxDB.has_key?(bodyCk) and @funxDB[name] == body
|
143
|
+
edges = @funxDB[bodyCk]
|
144
|
+
edges.each {|edge| add_edge(*edge)}
|
145
|
+
else
|
146
|
+
edges = []
|
147
|
+
add_vertex(name)
|
148
|
+
(names - [name] + @adds).each { |func|
|
149
|
+
puts body if @debug and false
|
150
|
+
puts func
|
151
|
+
if/#@@matchBeforFuncName#{func}#@@matchAfterFuncName/.match(body)
|
152
|
+
edge = ["#{name}","#{func}"]
|
153
|
+
add_edge(*edge)
|
154
|
+
edges << edge
|
155
|
+
end
|
156
|
+
}
|
157
|
+
# @lock.synchronize {
|
158
|
+
@funxDB[bodyCk] = edges
|
159
|
+
@funxDB[name] = body
|
160
|
+
# }
|
161
|
+
end
|
162
|
+
# }
|
163
|
+
}
|
164
|
+
threads.each {|t| t.join}
|
165
|
+
updateFunxDB
|
121
166
|
end
|
122
167
|
|
123
168
|
def limit(depth)
|
@@ -134,7 +179,7 @@ class FunctionGraph < RGL::DirectedAdjacencyGraph
|
|
134
179
|
# Creates a simple dot file according to the above <Params>.
|
135
180
|
# Parameters for the nodes are not supported by rgl.
|
136
181
|
def to_dot(filename)
|
137
|
-
File.open(
|
182
|
+
File.open(filename,"w") {|f|
|
138
183
|
print_dotted_on(Params,f)
|
139
184
|
}
|
140
185
|
end
|
@@ -165,7 +210,14 @@ class FunctionGraph < RGL::DirectedAdjacencyGraph
|
|
165
210
|
dotty(Params)
|
166
211
|
system("rm graph.dot") if File.exist?("graph.dot")
|
167
212
|
end
|
168
|
-
|
213
|
+
|
214
|
+
def updateFilesDB
|
215
|
+
File.open(@@filesDB,"w") {|f| f << JSON.generate(@filesDB)} unless @filesCk == @filesDB.hash
|
216
|
+
end
|
217
|
+
def updateFunxDB
|
218
|
+
File.open(@@funxDB,"w") {|f| f << JSON.generate(@funxDB)} unless @funxCk == @filesDB.hash
|
219
|
+
end
|
220
|
+
private :genFiles,:updateFilesDB,:updateFunxDB
|
169
221
|
end
|
170
222
|
|
171
223
|
class SingleFunctionGraph < FunctionGraph
|
@@ -194,8 +246,8 @@ class SingleFunctionGraph < FunctionGraph
|
|
194
246
|
else
|
195
247
|
names = graph.funx.keys
|
196
248
|
if not names.include?(func)
|
197
|
-
|
198
|
-
exit
|
249
|
+
warn "Function #{func} not found."
|
250
|
+
exit -1
|
199
251
|
end
|
200
252
|
@scannednames << f
|
201
253
|
body = graph.funx[f]
|
@@ -222,7 +274,7 @@ class UpperFunctionGraph < SingleFunctionGraph
|
|
222
274
|
warn "Function '#{func}' not found. If this is an internal function, " +
|
223
275
|
"please try again with the '-w' option to include the internal " +
|
224
276
|
"funx before scanning."
|
225
|
-
exit
|
277
|
+
exit -1
|
226
278
|
end
|
227
279
|
@scannednames << func
|
228
280
|
graph.funx.each_pair {|g,gbody|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 7
|
8
|
-
-
|
9
|
-
version: 0.7.
|
8
|
+
- 16
|
9
|
+
version: 0.7.16
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ralf Mueller
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-10-31 16:30:55 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|