Initial version of the automatic module init creator
[libfirm] / scripts / gen_init.py
1 #!/usr/bin/python -O
2 #
3 # Automatically parse all directories and create the module
4 # initialization function
5 #
6 # author: Michael Beck
7 #
8 # $Id$
9
10 import sys
11 import os
12 import os.path
13 import getopt
14 import string
15 import re
16
17 class Processor:
18   """This class processes all source files and create the init module."""
19
20   def __init__(self, dir):
21     self.dir = dir
22     self.ignore_dirs = { "CVS" : "CVS directory" }
23     self.allowed_sfx = [ ".c", ".h" ]
24     self.reg_string = re.compile(r"BE_REGISTER_MODULE_CONSTRUCTOR\((\w+)\)")
25     self._verbose = False
26     self.constructors = []
27     self.prolog = "\n"
28     self.prolog += "void be_init_modules(void)\n"
29     self.prolog += "{\n"
30     self.prolog += "\tstatic int run_once = 0;\n"
31     self.prolog += "\n"
32     self.prolog += "\tif (run_once)\n"
33     self.prolog += "\t\treturn;\n"
34     self.prolog += "\trun_once = 1;\n"
35     self.epilog = "}\n\n"
36
37   def verbose(self, flag):
38     """enables/disables verbose mode"""
39     self._verbose = flag
40
41   def process_dirs(self):
42     """process all directories and collect the data"""
43
44     def _visit(self, dirname, names):
45       """called for every directory entry"""
46
47       basename = os.path.basename(dirname)
48       # check if this directory must be ignored
49       if self.ignore_dirs.has_key(basename):
50         if self._verbose:
51           print "Ignoring",  self.ignore_dirs[basename]
52         return
53
54       if self._verbose:
55         print "Parsing",  dirname, "..."
56
57       for name in names:
58         path = dirname + "/" + name
59         if os.path.isfile(path):
60           self.process_file(path)
61
62     os.path.walk(self.dir, _visit, self)
63
64   def process_file(self, path):
65     """process a file"""
66     # check, if it has an allowed suffix
67     index = path.rfind(".")
68     if index < 0:
69       return
70     suffix = path[index:]
71     if  suffix in self.allowed_sfx:
72       # we found an allowed suffix
73       self.process_src(path)
74
75   def process_src(self, path):
76     """process a source file"""
77     f = file(path)
78     for line in f.readlines():
79       m = self.reg_string.search(line)
80       if m:
81         fkt = m.group(1)
82         if self._verbose:
83           print "  Found constructor", fkt
84         self.constructors.append(fkt)
85     f.close()
86
87   def gen_output(self, name):
88     """generate the output"""
89     self.process_dirs()
90     s = ""
91     # generate prototypes
92     for fkt in self.constructors:
93       s += "void %s(void);\n" % fkt
94
95     s += self.prolog
96     for fkt in self.constructors:
97       s += "\t%s();\n" % fkt
98     s += self.epilog
99
100     if os.access(name, os.F_OK):
101       f = file(name)
102       olds = f.read()
103       f.close()
104     else:
105       olds = ""
106
107     if olds != s:
108       f = file(name, "w")
109       f.write(s)
110       f.close()
111       print name, "updated."
112     else:
113       print name, "unchanged."
114
115 def usage(progname):
116   """Prints the usage"""
117   print "usage: %s [options] directory outname" % progname
118   print "Options are:"
119   print "-v   verbose"
120
121 def main(argv):
122   """the main function"""
123   dir = None
124   gen_name = None
125   verbose = False
126
127   # parse options
128   try:
129     opts, args = getopt.getopt(argv[1:], "?v", ["help", "verbose"])
130   except getopt.GetoptError, msg:
131     print "Error:", msg
132     usage(argv[0])
133     sys.exit(1)
134
135   for opt in opts:
136     option, value = opt
137     if option in ('-?',  '--help'):
138       usage(argv[0])
139       sys.exit(0)
140     elif option in ('-v', '--verbose'):
141       verbose = True
142
143   if len(args) != 2:
144     usage(argv[0])
145     sys.exit(2)
146   else:
147     gen_name = args[0]
148     dir = args[1]
149
150   processor = Processor(dir)
151   processor.verbose(verbose)
152   processor.gen_output(gen_name)
153
154 if __name__ == "__main__":
155   main(sys.argv)