mirror of
https://github.com/encounter/ogws.git
synced 2026-03-30 11:33:37 -07:00
162 lines
5.1 KiB
Python
162 lines
5.1 KiB
Python
#####################################################################
|
|
# NOTE: This is a modified version of decompctx.py. #
|
|
# Originally written by the PrimeDecomp team: #
|
|
# https://github.com/PrimeDecomp/prime/blob/main/tools/decompctx.py #
|
|
#####################################################################
|
|
|
|
from sys import platform, argv
|
|
from subprocess import Popen, PIPE
|
|
from os import walk, path
|
|
from os.path import join, exists, relpath, dirname, abspath, realpath
|
|
from re import compile
|
|
|
|
INCLUDE_DIR = "include/"
|
|
SRC_DIR = "src/"
|
|
STL_INCLUDE_DIR = "include/MSL"
|
|
RVL_INCLUDE_DIR = "include/revolution"
|
|
TYPES_H_PATH = f"{RVL_INCLUDE_DIR}/types.h"
|
|
SCRIPT_DIR = dirname(realpath(__file__))
|
|
ROOT_DIR = abspath(join(SCRIPT_DIR, ".."))
|
|
SRC_DIR = join(ROOT_DIR, "src")
|
|
|
|
INCLUDE_PATTERN = compile(r'^#include\s*[<"](.+?)[>"]$')
|
|
GUARD_PATTERN = compile(r"^#ifndef\s+(.*)$")
|
|
GUARD_IFDEF_PATTERN = compile(r"^#ifdef\s+(.*)$")
|
|
GUARD_ELSE_PATTERN = compile(r"^#else\s*$")
|
|
GUARD_END_PATTERN = compile(r"^#endif\s*$")
|
|
|
|
DEFINES = set()
|
|
|
|
|
|
def main():
|
|
if len(argv) < 2:
|
|
print("[FATAL] Please supply a source file name.")
|
|
exit(0)
|
|
|
|
src_file = resolve_src_name(argv[1])
|
|
|
|
print()
|
|
print("[INFO] Generating context...")
|
|
|
|
# Generate context file
|
|
with open("ctx.c", "w+") as f:
|
|
print(import_c_file(src_file), file=f)
|
|
print("[INFO] Context written to ./ctx.c!")
|
|
|
|
# Copy to clipboard if on Windows
|
|
try:
|
|
with open("ctx.c", "r") as f:
|
|
copy_to_clip("".join(f.readlines()))
|
|
except OSError:
|
|
# Not a big deal really
|
|
pass
|
|
|
|
|
|
def copy_to_clip(text: str):
|
|
if platform == "win32":
|
|
Popen(['CLIP'], stdin=PIPE).communicate(text.encode())
|
|
print("[INFO] Copied to clipboard!")
|
|
|
|
|
|
def resolve_src_name(src_file) -> str:
|
|
# Is the source file an absolute path?
|
|
try:
|
|
with open(src_file, "r") as tmp:
|
|
return src_file
|
|
# Relative path to some directory, try to find that directory
|
|
except OSError:
|
|
print(
|
|
f"[INFO] Source file ({src_file}) appears to be a relative path.")
|
|
print("[INFO] Attempting to resolve to an absolute path...")
|
|
|
|
# Convert any path separators in the source file to what is expected
|
|
src_file = src_file.replace("/", path.sep)
|
|
src_file = src_file.replace("\\", path.sep)
|
|
|
|
for _root, _dirs, _files in walk(SRC_DIR):
|
|
for file in _files:
|
|
p = join(_root, file)
|
|
# Case sensitive check
|
|
found = p.endswith(src_file)
|
|
# Case insensitive check (on Windows)
|
|
if platform == "win32":
|
|
found = found or p.lower().endswith(src_file.lower())
|
|
|
|
if found:
|
|
print(
|
|
f"[INFO] I think you are referring to this file: {p}")
|
|
return p
|
|
print("[FATAL] Sorry, but I don't know what file you want.")
|
|
exit()
|
|
|
|
|
|
def import_h_file(in_file, r_path) -> str:
|
|
# Only non-STL relative include should be types.h
|
|
if in_file == "revolution/types.h" or in_file == "types.h" and exists(TYPES_H_PATH):
|
|
return import_h_file_as_c(TYPES_H_PATH)
|
|
|
|
# Try root directory
|
|
rel_path = join(ROOT_DIR, r_path, in_file)
|
|
if exists(rel_path):
|
|
return import_h_file_as_c(rel_path)
|
|
|
|
# Try root include directory
|
|
inc_path = join(INCLUDE_DIR, in_file)
|
|
if exists(inc_path):
|
|
return import_h_file_as_c(inc_path)
|
|
|
|
# Try root include directory
|
|
inc_path = join(STL_INCLUDE_DIR, in_file)
|
|
if exists(inc_path):
|
|
return import_h_file_as_c(inc_path)
|
|
|
|
print(f"Failed to locate header: {in_file}")
|
|
return ""
|
|
|
|
|
|
def import_h_file_as_c(in_file) -> str:
|
|
in_file = relpath(in_file, ROOT_DIR)
|
|
out_text = ""
|
|
|
|
with open(in_file) as file:
|
|
for idx, line in enumerate(file):
|
|
# Header guard
|
|
guard_match = GUARD_PATTERN.match(line.strip())
|
|
if guard_match:
|
|
# At the beginning of the file = actually a header guard
|
|
if idx == 0:
|
|
if guard_match[1] in DEFINES:
|
|
break
|
|
DEFINES.add(guard_match[1])
|
|
|
|
# Sub-include
|
|
include_match = INCLUDE_PATTERN.match(line.strip())
|
|
if include_match:
|
|
out_text += f'/* "{in_file}" line {idx} "{include_match[1]}" */\n'
|
|
out_text += import_h_file(include_match[1], dirname(in_file))
|
|
out_text += f'/* end "{include_match[1]}" */\n'
|
|
# File text
|
|
else:
|
|
out_text += line
|
|
|
|
return out_text
|
|
|
|
|
|
def import_c_file(in_file) -> str:
|
|
in_file = relpath(in_file, ROOT_DIR)
|
|
out_text = ""
|
|
|
|
with open(in_file) as file:
|
|
for idx, line in enumerate(file):
|
|
# Sub-include
|
|
include_match = INCLUDE_PATTERN.match(line.strip())
|
|
if include_match:
|
|
out_text += f'/* "{in_file}" line {idx} "{include_match[1]}" */\n'
|
|
out_text += import_h_file(include_match[1], dirname(in_file))
|
|
out_text += f'/* end "{include_match[1]}" */\n'
|
|
|
|
return out_text
|
|
|
|
|
|
main()
|