DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Destroy C Code Which Is Not In #ifdef Symbol

12.01.2010
| 2821 views |
  • submit to reddit
        Here is (not-so-simple) script for purify a C source code .

Purpose is transform a code like
okcode1
#ifdef XXX
  ..goodcode...
#else
  ..oldcode...
#endif
okcode2

to

okcode1
  ..goodcode...
okcode2

if symbol XXX is defined.
Warning : comment is not specialy traited !

if ARGV.size<2 || ARGV[0].size<2
 puts "Usage: >ruby  ifdef.rb   name-macro dir_sources/source1.c  ..."
 exit!
end
$macro=ARGV.shift
ARGV.each { |filename|
  raise"Error! file #{filename} not exist !" unless File.exists?(filename) 
}


#===========  stack machine tools

def push_state(nv,ret) $stack.unshift($state); $state=nv ; ret  end
def pop_state(ret)     $state=$stack.shift; ret  end
def set_state(v,ret)   $state=v ; ret end

#====================================================
#   do_<transition>_<state>()
#      return true if current line must be keep in source
#
#   transition is line type ( #ifdef #ifndef #else ...)
#====================================================
def do_def_main(line)
 ismacro= line =~ /#\s*ifdef\s+#{$macro}( |$)/
 ismacro ?  push_state(:if_display,false) : push_state(:display,true)
end
def do_ndef_main(line)
 ismacro= line =~ /#\s*ifndef\s+#{$macro}( |$)/
 ismacro ?  push_state(:else_nodisplay,false) : push_state(:display,true)
end
def do_free_main(line) true end

def do_else_main(line) false end
def do_end_main(line)  pop_state(false) end


#======= state= code in #else or #ifdef

def do_else_if_display(line)      set_state(:else_nodisplay,false) end
def do_else_else_nodisplay(line)  set_state(:if_display,false) end
def do_free_if_display(line)      true  end
def do_free_else_nodisplay(line)  false end
def do_end_if_display(line)       pop_state(false)   end
def do_end_else_nodisplay(line)   pop_state(false) end

def do_def_if_display(line)       push_state(:display,true) end
def do_def_else_nodisplay(line)   push_state(:nodisplay,false) end

#========== state = display 

def do_else_display(line)  true end
def do_free_display(line)  true  end
def do_end_display(line)   pop_state(true) end
def do_def_display(line)   do_def_main(line) end
def do_ndef_display(line)  do_ndef_main(line) end

#========== state = nodisplay 

def do_else_nodisplay(line) false end
def do_free_nodisplay(line)  false  end
def do_end_nodisplay(line)  pop_state(false) end

def do_def_nodisplay(line)  push_state(:nodisplay,false)  end
def do_ndef_nodisplay(line)  push_state(:nodisplay,false)  end


ARGV.each { |filename|
  filenameOut = filename.split(".",2)[0]+"_new."+filename.split(".",2)[1]
  $state=:main
  $stack=[]
  out=[]
  oldsrc=File.read(filename)
  oldsrc.each_line do |line|
    type = case line 
      when /^#\s*ifdef\s+/ then :def
      when /^#\s*ifndef\s+/ then :ndef
      when /^#\s*else/  then :else
      when /^#\s*endif/ then :end
      else
	:free
    end
    method_name= "do_"+type.to_s+"_"+$state.to_s
    toprint = send(method_name,line)
    out <<  line.chomp.rstrip if toprint
  end
  content=out.join("\n")
  File.open(filenameOut,"w") { |f| f.puts content }
  puts " #{filenameOut} is generated : size=#{content.size} / #{oldsrc.size}" 
}