codegraph 0.7.12 → 0.7.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/bin/codegraph +14 -4
  2. data/gemspec +3 -1
  3. data/lib/codegraph.rb +96 -44
  4. 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.12"
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'
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 = `echo $HOME`.chomp
27
- @@codehomedir = "#{@@home}/.codegraph"
28
- @@matchBeforFuncName = '[^A-z0-9_]\s*'
29
- @@matchAfterFuncName = ' *\('
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 = false
45
+ @debug = false
40
46
  # the following attribute will hold the functionnames and their bodies
41
- @funx = Hash.new
42
- @lock = Mutex.new
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=fsp --php-kinds=f --perl-kinds=f'
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
- basefile = File.basename(file)
59
- temfile = "_" + basefile
60
- case File.extname(file)
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
- cppCommand = "cp #{file} #{codehomedir}/#{temfile}"
70
- grep = "grep -v -e '^$' #{codehomedir}/#{temfile} | grep -v -e '^#' > #{codehomedir}/#{basefile}"
71
- end
72
- gen4ctags = "ctags -x #{ctagsKinds} #{codehomedir}/#{basefile} | sort -n -k 3"
73
- command = [cppCommand,grep].join(";")
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
- puts command if @debug
76
- system(command)
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
- puts "no functions found"
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 << Threads.new(name,body,names) {|name,body|
138
+ # threads=[];threads << Thread.new(name,body,names) {|name,body,names|
112
139
  puts "Add func: #{name}" if @debug
113
- add_vertex(name)
114
- (names - [name] + @adds).each { |func|
115
- puts body if @debug
116
- add_edge("#{name}","#{func}") if/#@@matchBeforFuncName#{func}#@@matchAfterFuncName/.match(body)
117
- }
118
- }
119
- # }
120
- # threads.each {|t| t.join}
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("#{filename}","w") {|f|
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
- private :genFiles
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
- puts "Function #{func} not found."
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
- - 12
9
- version: 0.7.12
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-02-18 09:11:26 +01:00
17
+ date: 2011-10-31 16:30:55 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency