mm/tools/sort_actor_funcs.py
Derek Hensley 471d86f530
Build Sync (#1600)
* Rename outputs

* Makefile target renames

* Add run target

* yeet z64compress

* venv

* baserom_uncompressed -> baserom-decompressed

* input rom name to baserom.z64

* Add BUILD_DIR makefile variable

* Move built roms to build dir

* Move baserom to baseroms folder

* Add version to map file name

* Makefile cleanup

* Rename ldscript to include version

* Multiversion build

* n64-us version name

* Remove venv as dependency of setup

* Readme wording

* extract_baserom.py suggestion

* Readd checksums

* Make .venv work with windows

* missed an endif

* Cleaner windows venv implementation

* Remove duplciate process

* Build process steps

* Move make_options back

* Fix schedule build directory

* Fix schedule includes

* Makefile NON_MATCHING check -> != 0

* OOT 1704 changes

* Small cleanups

* Missed 1 thing

* UNSET -> SYMS

* Update extract_baserom.py

* dmadata.py

* Small cleanup

* dmadata_start

* Format

* dmadata files

* Fix makefile comment

* Jenkins report fix

* extracted dir

* Python dependencies order in readme
2024-04-06 11:07:58 -07:00

78 lines
2.5 KiB
Python
Executable File

#!/usr/bin/env python3
from pathlib import Path
import argparse
parser = argparse.ArgumentParser(description="Script to sort forward-declared functions and extern'd symbols in actors")
parser.add_argument("file", type=str, help="Path to c file to sort")
args = parser.parse_args()
file_path = Path(args.file).resolve()
if not file_path.suffix == ".c":
print(f"Should only be run on a .c file!")
exit()
if "/overlays/actors/" not in str(file_path):
print(f"This should only be run on actors, are you sure you gave it the right file?")
exit()
map_path = file_path.parent.parent.parent.parent.parent
map_lines = (map_path / "build" / "n64-us" / "mm-n64-us.map").read_text().splitlines()[10000:]
i = 0
while not f"{file_path.stem}.o(.text)" in map_lines[i]:
i += 1
i += 2
assert map_lines[i-1].startswith(" .text")
orig_funcs = set()
while map_lines[i].startswith(" "):
func = map_lines[i].split(" ")[-1]
if not (func.endswith("_Init") or func.endswith("_Destroy") or func.endswith("_Update") or func.endswith("_Draw")):
orig_funcs.add(func)
i += 1
lines = file_path.read_text().splitlines()
start_func_line = 0
end_func_line = 0
func_list = set()
externs = []
extern_set = set()
i = 0
while (not (lines[i].startswith("const") or lines[i].startswith("static") or lines[i].startswith("typedef"))):
line = lines[i]
if line.startswith("extern"):
extern_type = line.rsplit(" ",1)[0]
extern_name = line.split(" ",2)[2][:-1]
if extern_name not in extern_set:
externs.append({"type":extern_type, "name":extern_name})
extern_set.add(extern_name)
i += 1
declares_needed = set()
funcs_seen = set()
funcs_types = []
for count, line in enumerate(lines):
if not line.startswith(" ") and "(" in line and "{" in line and "static" not in line:
func_ret = line.split(" ",1)[0]
func_name = line.split(" ",1)[1].split("(",1)[0]
func_args = line.split("(",1)[1].split(")",1)[0]
funcs_seen.add(func_name)
funcs_types.append({"ret":func_ret, "name":func_name, "args":func_args})
else:
for func in orig_funcs:
if func in line and func not in funcs_seen:
declares_needed.add(func)
externs.sort(key=lambda x: x["name"])
declares = []
for func in funcs_types:
if func["name"] in declares_needed:
declares.append(f"{func['ret']} {func['name']}({func['args']});")
print("\n".join(declares))
print()
print("\n".join([f"{x['type']} {x['name']};" for x in externs]))