Files
coven/modules/ufbx/misc/macro_expander.py

76 lines
2.3 KiB
Python

import argparse
import re
parser = argparse.ArgumentParser(usage="macro_expander.py macro files")
parser.add_argument("macro")
parser.add_argument("files", nargs="*")
argv = parser.parse_args()
macro_lines = []
macro_params = []
RE_NEWLINE = re.compile(r"\n")
RE_DEF = re.compile(f"\n\s*#define\\s+{re.escape(argv.macro)}\s*\\(([^)]*)\\)\s*(.*)\\\\\s*\r?\n", re.M)
RE_LINE = re.compile(r"\t?(.*?)\s*(\\?)\r?\n", re.M)
RE_USE = re.compile(f"{re.escape(argv.macro)}\s*\\(", re.M)
for path in argv.files:
with open(path, "rt") as f:
text = f.read()
lineno = 1
linestart = 0
pos = 0
while True:
if not macro_lines:
m = RE_DEF.search(text, pos)
if m:
macro_params = [a.strip() for a in m.group(1).split(",")]
first_line = m.group(2).strip()
if first_line:
macro_lines.append(first_line)
pos = m.end()
while True:
m = RE_LINE.match(text, pos)
if not m: break
pos = m.end()
macro_lines.append(m.group(1))
if not m.group(2): break
else:
m = RE_USE.search(text, pos)
if not m: break
lineno += sum(1 for _ in RE_NEWLINE.finditer(text, linestart, m.start()))
linestart = m.start()
tlen = len(text)
args = [[]]
level = 0
pos = m.end()
while pos < tlen:
c = text[pos]
if c == "(":
level += 1
args[-1].append(c)
elif c == ")":
level -= 1
if level < 0: break
args[-1].append(c)
elif c == "," and level == 0:
args.append([])
else:
args[-1].append(c)
pos += 1
args = ["".join(a).strip() for a in args]
print()
print(f"-- {path}:{lineno}")
for param, arg in zip(macro_params, args):
print(f"#define {param} {arg}")
for line in macro_lines:
print(line)
for param in macro_params:
print(f"#undef {param}")