mirror of https://github.com/zeldaret/mm.git
				
				
				
			
		
			
				
	
	
		
			78 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			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" / "mm.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]))
 |