source: buchla-68k/misc/gen-glob.py@ 6aa430b

Last change on this file since 6aa430b was 6aa430b, checked in by Thomas Lopatic <thomas@…>, 7 years ago

More accurate headers.

  • Property mode set to 100755
File size: 5.4 KB
Line 
1#!/usr/bin/env python3
2
3from sys import stdout
4from pycparser import c_ast, parse_file, c_generator
5
6cross_gcc = "/opt/cross-m68k/bin/m68k-none-elf-gcc"
7
8class InclVis(c_ast.NodeVisitor):
9 def __init__(self, path):
10 self.path = path
11 self.typs = set()
12
13 def visit_Typedef(self, node):
14 if node.coord.file == self.path:
15 self.typs.add(node.name)
16
17 self.generic_visit(node)
18
19 def visit_Struct(self, node):
20 if node.coord.file == self.path and \
21 node.name is not None and node.decls is not None:
22 self.typs.add(node.name)
23
24 self.generic_visit(node)
25
26 def get_typs(self):
27 return self.typs
28
29typ_map = {
30 "void": None
31}
32
33with open("misc/c-files.txt", "r") as f:
34 for path in f:
35 path = path.rstrip()
36
37 if len(path) < 8 or path[:8] != "include/":
38 continue
39
40 stdout.write("parsing {} \r".format(path))
41 stdout.flush()
42
43 ast = parse_file(path, use_cpp = True, cpp_path = cross_gcc,
44 cpp_args = ["-E", "-I", "include"])
45 # ast.show()
46
47 vis = InclVis(path)
48 vis.visit(ast)
49
50 for typ in vis.get_typs():
51 if typ in typ_map:
52 raise Exception("redefinition of {}".format(typ))
53
54 typ_map[typ] = path[8:]
55
56class DeclVis(c_ast.NodeVisitor):
57 def __init__(self, typ_map):
58 self.typ_map = typ_map
59 self.typs = set()
60
61 def visit_IdentifierType(self, node):
62 if node.names[0] not in self.typ_map:
63 raise Exception("unknown type {} in {}:{}". \
64 format(node.names[0], node.coord.file, node.coord.line))
65
66 self.typs.add(node.names[0])
67 self.generic_visit(node)
68
69 def visit_Struct(self, node):
70 if node.name not in self.typ_map:
71 raise Exception("unknown struct {} in {}:{}". \
72 format(node.name, node.coord.file, node.coord.line))
73
74 self.typs.add(node.name)
75 self.generic_visit(node)
76
77 def get_typs(self):
78 return self.typs
79
80gen = c_generator.CGenerator()
81
82with open("misc/c-files.txt", "r") as f:
83 for path in f:
84 path = path.rstrip()
85
86 if len(path) >= 8 and path[:8] == "include/":
87 continue
88
89 if path == "ram/wdfield.c": # breaks pycparser
90 continue
91
92 stdout.write("reading {} \r".format(path))
93 stdout.flush()
94
95 ast = parse_file(path, use_cpp = True, cpp_path = cross_gcc,
96 cpp_args = ["-E", "-I", "include"])
97 # ast.show()
98
99 incs = set()
100 funs = {}
101 vars = {}
102
103 for node in ast.ext:
104 if type(node) is c_ast.Decl and \
105 (type(node.type) is c_ast.TypeDecl or \
106 type(node.type) is c_ast.PtrDecl or \
107 type(node.type) is c_ast.ArrayDecl):
108 decl = node
109 dest = vars
110
111 elif type(node) is c_ast.FuncDef:
112 decl = node.decl
113 dest = funs
114
115 else:
116 continue
117
118 if "extern" in decl.storage or \
119 "static" in decl.storage:
120 continue
121
122 vis = DeclVis(typ_map)
123 vis.visit(decl)
124
125 for typ in vis.get_typs():
126 if typ_map[typ] is not None:
127 incs.add(typ_map[typ])
128
129 decl.storage = ["extern"]
130 decl.init = None
131
132 toks = gen.visit(decl).split(" ")
133 alig = ""
134
135 alig += toks[0] + "\t"
136 toks = toks[1:]
137
138 if toks[0] == "struct":
139 if len(toks[1]) > 7:
140 raise Exception("identifier too long: {}".format(toks[1]))
141
142 alig += toks[0] + "\t" + toks[1] + "\t"
143 toks = toks[2:]
144
145 else:
146 alig += toks[0] + ("\t\t" if len(toks[0]) < 8 else "\t")
147 toks = toks[1:]
148
149 dest[decl.name] = alig + " ".join(toks) + ";"
150
151 file = path.split("/")[-1]
152 glob = []
153
154 if len(vars) > 0:
155 glob.append("/*")
156 glob.append(" =============================================================================")
157 glob.append("\t" + file + " -- global variables")
158 glob.append(" =============================================================================")
159 glob.append("*/")
160 glob.append("")
161
162 for _, out in sorted(vars.items()):
163 glob.append(out)
164
165 glob.append("")
166
167 if len(funs) > 0:
168 glob.append("/*")
169 glob.append(" =============================================================================")
170 glob.append("\t" + file + " -- global functions")
171 glob.append(" =============================================================================")
172 glob.append("*/")
173 glob.append("")
174
175 for _, out in sorted(funs.items()):
176 glob.append(out)
177
178 glob.append("")
179
180 if len(glob) == 0:
181 continue
182
183 head = []
184 head.append("#pragma once")
185 head.append("")
186
187 if len(incs) > 0:
188 for inc in sorted(incs):
189 head.append("#include \"{}\"".format(inc))
190
191 head.append("")
192
193 glob = head + glob
194
195 with open(path[:-2] + ".x", "w") as f:
196 f.write("\n".join(glob))
197
198 print("")
Note: See TracBrowser for help on using the repository browser.