source: buchla-68k/misc/gen-x.py@ 526a993

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

Wording change.

  • Property mode set to 100755
File size: 5.7 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 if len(vars) == 0 and len(funs) == 0:
152 continue
153
154 file = path.split("/")[-1]
155 glob = []
156
157 glob.append("/*")
158 glob.append(" =============================================================================")
159 glob.append("\t" + file + " -- external declarations")
160 glob.append(" =============================================================================")
161 glob.append("*/")
162 glob.append("")
163
164 glob.append("#pragma once")
165 glob.append("")
166
167 if len(incs) > 0:
168 for inc in sorted(incs):
169 glob.append("#include \"{}\"".format(inc))
170
171 glob.append("")
172
173 if len(vars) > 0:
174 glob.append("/*")
175 glob.append(" =============================================================================")
176 glob.append("\texternal variables")
177 glob.append(" =============================================================================")
178 glob.append("*/")
179 glob.append("")
180
181 for _, out in sorted(vars.items()):
182 glob.append(out)
183
184 glob.append("")
185
186 if len(funs) > 0:
187 glob.append("/*")
188 glob.append(" =============================================================================")
189 glob.append("\texternal functions")
190 glob.append(" =============================================================================")
191 glob.append("*/")
192 glob.append("")
193
194 for _, out in sorted(funs.items()):
195 glob.append(out)
196
197 glob.append("")
198
199 with open(path[:-2] + ".x", "w") as f:
200 f.write("\n".join(glob))
201
202 print("")
Note: See TracBrowser for help on using the repository browser.