gen_docu: fix missing attributes, show generation time at the end
[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 import sys
9 import os
10 import os.path
11 import getopt
12 import string
13 import re
14
15 class Processor:
16   """This class processes all source files and create the init module."""
17
18   def __init__(self, dirs):
19     self.dirs = dirs
20     self.ignore_dirs = { "CVS" : "CVS directory" }
21     self.allowed_suffixes = [ ".c" ]
22     self.reg_string = re.compile(r"BE_REGISTER_MODULE_CONSTRUCTOR\((\w+)\)")
23     self._verbose = False
24     self.constructors = []
25     self.prolog = "\n"
26     self.prolog += "void be_init_modules(void)\n"
27     self.prolog += "{\n"
28     self.prolog += "\tstatic int run_once = 0;\n"
29     self.prolog += "\n"
30     self.prolog += "\tif (run_once)\n"
31     self.prolog += "\t\treturn;\n"
32     self.prolog += "\trun_once = 1;\n"
33     self.epilog = "}\n\n"
34
35   def verbose(self, flag):
36     """enables/disables verbose mode"""
37     self._verbose = flag
38
39   def process_dirs(self):
40     """process all directories and collect the data"""
41
42     def _visit(self, dirname, names):
43       """called for every directory entry"""
44
45       basename = os.path.basename(dirname)
46       # check if this directory must be ignored
47       if self.ignore_dirs.has_key(basename):
48         if self._verbose:
49           print "Ignoring",  self.ignore_dirs[basename]
50         return
51
52       if self._verbose:
53         print "Parsing",  dirname, "..."
54
55       for name in names:
56         path = dirname + "/" + name
57         if os.path.isfile(path):
58           self.process_file(path)
59
60     # code of process_dirs
61     for dir in self.dirs:
62       os.path.walk(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_suffixes:
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, path))
85     f.close()
86
87   def update_init_func(self, name):
88     """generate the output"""
89     self.process_dirs()
90     s = ""
91     # generate prototypes
92     for fkt,path in self.constructors:
93       s += "/* %s */\n" % path
94       s += "void %s(void);\n" % fkt
95
96     s += self.prolog
97     for fkt,path in self.constructors:
98       s += "\t%s();\n" % fkt
99     s += self.epilog
100
101     if os.access(name, os.F_OK):
102       f = file(name)
103       olds = f.read()
104       f.close()
105     else:
106       olds = ""
107
108     if olds != s:
109       f = file(name, "w")
110       f.write(s)
111       f.close()
112       print name, "updated."
113     else:
114       print name, "unchanged."
115
116 def usage(progname):
117   """Prints the usage"""
118   print "usage: %s [options] outname directory+ " % progname
119   print "Options are:"
120   print "-v   verbose"
121
122 def main(argv):
123   """the main function"""
124   dirs = []
125   gen_name = None
126   verbose = False
127
128   # parse options
129   try:
130     opts, args = getopt.getopt(argv[1:], "?v", ["help", "verbose"])
131   except getopt.GetoptError, msg:
132     print "Error:", msg
133     usage(argv[0])
134     sys.exit(1)
135
136   for opt in opts:
137     option, value = opt
138     if option in ('-?',  '--help'):
139       usage(argv[0])
140       sys.exit(0)
141     elif option in ('-v', '--verbose'):
142       verbose = True
143
144   if len(args) < 2:
145     usage(argv[0])
146     sys.exit(2)
147   else:
148     gen_name = args[0]
149     dirs = args[1:]
150
151   processor = Processor(dirs)
152   processor.verbose(verbose)
153   # process the directory and update the requested file
154   processor.update_init_func(gen_name)
155
156 if __name__ == "__main__":
157   main(sys.argv)