fragile nodes must be exception or memory pinned
[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, dirs):
21     self.dirs = dirs
22     self.ignore_dirs = { "CVS" : "CVS directory" }
23     self.allowed_suffixes = [ ".c" ]
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     # code of process_dirs
63     for dir in self.dirs:
64       os.path.walk(dir, _visit, self)
65
66   def process_file(self, path):
67     """process a file"""
68     # check, if it has an allowed suffix
69     index = path.rfind(".")
70     if index < 0:
71       return
72     suffix = path[index:]
73     if suffix in self.allowed_suffixes:
74       # we found an allowed suffix
75       self.process_src(path)
76
77   def process_src(self, path):
78     """process a source file"""
79     f = file(path)
80     for line in f.readlines():
81       m = self.reg_string.search(line)
82       if m:
83         fkt = m.group(1)
84         if self._verbose:
85           print "  Found constructor", fkt
86         self.constructors.append((fkt, path))
87     f.close()
88
89   def update_init_func(self, name):
90     """generate the output"""
91     self.process_dirs()
92     s = ""
93     # generate prototypes
94     for fkt,path in self.constructors:
95       s += "/* %s */\n" % path
96       s += "void %s(void);\n" % fkt
97
98     s += self.prolog
99     for fkt,path in self.constructors:
100       s += "\t%s();\n" % fkt
101     s += self.epilog
102
103     if os.access(name, os.F_OK):
104       f = file(name)
105       olds = f.read()
106       f.close()
107     else:
108       olds = ""
109
110     if olds != s:
111       f = file(name, "w")
112       f.write(s)
113       f.close()
114       print name, "updated."
115     else:
116       print name, "unchanged."
117
118 def usage(progname):
119   """Prints the usage"""
120   print "usage: %s [options] outname directory+ " % progname
121   print "Options are:"
122   print "-v   verbose"
123
124 def main(argv):
125   """the main function"""
126   dirs = []
127   gen_name = None
128   verbose = False
129
130   # parse options
131   try:
132     opts, args = getopt.getopt(argv[1:], "?v", ["help", "verbose"])
133   except getopt.GetoptError, msg:
134     print "Error:", msg
135     usage(argv[0])
136     sys.exit(1)
137
138   for opt in opts:
139     option, value = opt
140     if option in ('-?',  '--help'):
141       usage(argv[0])
142       sys.exit(0)
143     elif option in ('-v', '--verbose'):
144       verbose = True
145
146   if len(args) < 2:
147     usage(argv[0])
148     sys.exit(2)
149   else:
150     gen_name = args[0]
151     dirs = args[1:]
152
153   processor = Processor(dirs)
154   processor.verbose(verbose)
155   # process the directory and update the requested file
156   processor.update_init_func(gen_name)
157
158 if __name__ == "__main__":
159   main(sys.argv)