codegraph 0.7.12 → 0.7.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|