93 lines
2.9 KiB
Python
93 lines
2.9 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""Split a handler source file into one file per UMCPHandler class.
|
||
|
|
|
||
|
|
Usage: python3 tools/split-handlers.py <source_file>
|
||
|
|
|
||
|
|
Reads the #include block from the top of the file, then splits at the
|
||
|
|
closing }; (column 0) of each UMCPHandler class. Each output file is
|
||
|
|
named after the handler class and placed in the same directory. The
|
||
|
|
shared #include block is prepended to every output file.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import sys
|
||
|
|
import re
|
||
|
|
import os
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
if len(sys.argv) != 2:
|
||
|
|
print(f"Usage: {sys.argv[0]} <source_file>")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
filepath = sys.argv[1]
|
||
|
|
with open(filepath) as f:
|
||
|
|
lines = f.readlines()
|
||
|
|
|
||
|
|
# Extract the #include block from the top of the file.
|
||
|
|
# Collect #pragma, #include, blank lines, and // comment lines
|
||
|
|
# until we hit something else.
|
||
|
|
include_block = []
|
||
|
|
body_start = 0
|
||
|
|
for i, line in enumerate(lines):
|
||
|
|
stripped = line.strip()
|
||
|
|
if (stripped == '' or stripped.startswith('#pragma') or
|
||
|
|
stripped.startswith('#include') or stripped.startswith('//')):
|
||
|
|
include_block.append(line)
|
||
|
|
else:
|
||
|
|
body_start = i
|
||
|
|
break
|
||
|
|
|
||
|
|
# Strip trailing blank/comment lines from include block
|
||
|
|
while include_block and include_block[-1].strip() in ('', ) or (
|
||
|
|
include_block and include_block[-1].strip().startswith('//')):
|
||
|
|
body_start -= 1
|
||
|
|
include_block.pop()
|
||
|
|
if not include_block:
|
||
|
|
break
|
||
|
|
|
||
|
|
# Remove the .generated.h include from the shared block (each output
|
||
|
|
# file gets its own).
|
||
|
|
include_block = [l for l in include_block if '.generated.h' not in l]
|
||
|
|
|
||
|
|
body_lines = lines[body_start:]
|
||
|
|
|
||
|
|
# Find split points in the body: after each }; that closes a UMCPHandler.
|
||
|
|
handler_name = None
|
||
|
|
splits = [] # list of (end_index_exclusive_in_body, class_name)
|
||
|
|
|
||
|
|
for i, line in enumerate(body_lines):
|
||
|
|
m = re.match(r'class (UMCPHandler_\w+)', line)
|
||
|
|
if m:
|
||
|
|
handler_name = m.group(1)
|
||
|
|
if line.startswith('};') and handler_name:
|
||
|
|
splits.append((i + 1, handler_name))
|
||
|
|
handler_name = None
|
||
|
|
|
||
|
|
if not splits:
|
||
|
|
print("No UMCPHandler classes found.")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
dirname = os.path.dirname(filepath)
|
||
|
|
start = 0
|
||
|
|
for end, name in splits:
|
||
|
|
outpath = os.path.join(dirname, name + '.h')
|
||
|
|
with open(outpath, 'w') as f:
|
||
|
|
f.writelines(include_block)
|
||
|
|
f.write(f'#include "{name}.generated.h"\n')
|
||
|
|
f.write('\n')
|
||
|
|
f.writelines(body_lines[start:end])
|
||
|
|
print(f" {name}.h ({end - start} lines)")
|
||
|
|
start = end
|
||
|
|
|
||
|
|
# Warn about trailing content
|
||
|
|
if start < len(body_lines):
|
||
|
|
remaining = ''.join(body_lines[start:]).strip()
|
||
|
|
if remaining:
|
||
|
|
print(f"Warning: {len(body_lines) - start} trailing lines not included in any output file:")
|
||
|
|
for line in body_lines[start:]:
|
||
|
|
print(f" | {line}", end='')
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
main()
|