tags:

views:

91

answers:

5

I need to search all the *.c source files in the path to find a reference to a *.h header to find unused C headers. I wrote a ruby script but it feel very clumsy.

I create an array with all C files and an array with all the H files. I iterate over the header file array. For each header I open each C file and look for a reference to the header.

Is there a easier or better way?

require 'ftools'
require 'find'

# add a file search
class File
  def self.find(dir, filename="*.*", subdirs=true)
    Dir[ subdirs ? File.join(dir.split(/\\/), "**", filename) : File.join(dir.split(/\\/), filename) ]
  end
end

files = File.find(".", "*.c", true)
headers = File.find(".", "*.h", true)

headers.each do |file|

  #puts "Searching for #{file}(#{File.basename(file)})"
  found = 0

  files.each do |cfile|
    #puts "searching in #{cfile}"
    if File.read(cfile).downcase.include?(File.basename(file).downcase)
        found += 1
    end
  end

  puts "#{file} used #{found} times"

end
A: 

grep ...........

Kin
+1  A: 

To search *.c and *.h files, you could use Dir.glob

irb(main):012:0> Dir.glob("*.[ch]")
=> ["test.c", "test.h"]

To search across any subdirectory, you can pass **/*

irb(main):013:0> Dir.glob("**/*.[ch]")
=> ["src/Python-2.6.2/Demo/embed/demo.c", "src/Python-2.6.2/Demo/embed/importexc.c",
.........
S.Mark
+2  A: 

As already pointed out, you can use Dir#glob to simplify your file-finding. You could also consider switching your loops, which would mean opening each C file once, instead of once per H file.

I'd consider going with something like the following, which ran on the Ruby source in 3 seconds:

# collect the File.basename for all h files in tree
hfile_names = Dir.glob("**/*.h").collect{|hfile| File.basename(hfile) }

h_counts = Hash.new(0) # somewhere to store the counts

Dir.glob("**/*.c").each do |cfile| # enumerate the C files
  file_text = File.read(cfile) # downcase here if necessary
  hfile_names.each do |hfile|
    h_counts[hfile] += 1 if file_text.include?(hfile)
  end
end

h_counts.each { |file, found| puts "#{file} used #{found} times" }

EDIT: That won't list H files not referenced in any C files. To be certain to catch those, the hash would have to be explicitly initialised:

h_counts = {}
hfile_names.each { |hfile| h_counts[hfile] = 0 }
Mike Woodhouse
+1 for having same idea, and also for detail codes.
S.Mark
A: 

Well, once you've found your .c files, you can do this to them:

1) open the file and store the text in a variable 2) use 'grep' : http://ruby-doc.org/core/classes/Enumerable.html#M003121

Trevoke
A: 

FileList in the Rake API is very useful for this. Just be aware of the list size growing larger than you have memory to handle. :)

http://rake.rubyforge.org/

sam