Skip to content

Commit

Permalink
Restore makectx_m2c
Browse files Browse the repository at this point in the history
  • Loading branch information
SeekyCt committed Sep 17, 2024
1 parent 701ca2b commit 00216ef
Showing 1 changed file with 110 additions and 0 deletions.
110 changes: 110 additions & 0 deletions tools/makectx_m2c.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"""
Creates a context of all headers with the preprocessor ran
"""

from argparse import ArgumentParser
import os
import subprocess
import sys
from tempfile import NamedTemporaryFile
from typing import List, Optional


INCLUDES = [
os.path.join("spm-headers", "include"),
os.path.join("spm-headers", "decomp"),
# include_cpp omitted for m2c compatability
]
CC = os.path.join("build", "compilers", "GC", "3.0a5.2", "mwcceppc")
DEFINES = [
"DECOMP",
"SPM_EU0"
]


def check_wine(command: str, wine_override: Optional[str] = None) -> str:
if wine_override is None:
wine_override = "wine"

if sys.platform != "win32":
return f"{wine_override} {command}"
else:
return command


def get_cmd_stdout(cmd: str, text=True) -> str:
"""Run a command and get the stdout output as a string"""

ret = subprocess.run(cmd.split(), stdout=subprocess.PIPE, text=text)
assert ret.returncode == 0, f"Command '{cmd}' returned {ret.returncode}"
return ret.stdout


def find_headers(dirname: str, base=None) -> List[str]:
"""Returns a list of all headers in a folder recursively"""

if base is None:
base = dirname

ret = []
for name in os.listdir(dirname):
path = dirname + '/' + name
if os.path.isdir(path):
ret.extend(find_headers(path, base))
elif name.endswith('.h'):
ret.append(path[len(base)+1:])

return ret


def make_includes(dirnames: List[str]) -> str:
"""Returns a chain of #includes for all headers in a folder"""

return '\n'.join(
'\n'.join(
f"#include <{header}>"
for header in find_headers(dirname)
)
for dirname in dirnames
)


def preprocess(cc: str, includes: str, defines: List[str]) -> str:
"""Gets the preprocessed text of a C file"""

defines_str = ' '.join(f"-d {define}" for define in defines)
includes_str = ' '.join(f"-i {include}" for include in INCLUDES)

# Run mwcc preprocessor
with NamedTemporaryFile(suffix=".c", delete=False) as tmp:
try:
tmp.write(includes.encode())
tmp.close()

# NOTE: not preprocessed in C++ mode
return get_cmd_stdout(
f"{cc} -I- {includes_str} {defines_str} -d M2C -stderr -E {tmp.name}"
)
finally:
os.unlink(tmp.name)


if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("-d", "--defines", type=str, nargs='+', default=DEFINES,
help="Preprocessor defines")
parser.add_argument("-w", "--wine", type=str, help="Wine override (ignored on Windows)")
parser.add_argument("-o", "--out", type=str, help="Output file path")
args = parser.parse_args()

# Get cc command
cc = check_wine(CC, args.wine)

# Find all headers
includes = make_includes(INCLUDES)

# Preprocess headers
out = preprocess(cc, includes, args.defines)

# Output
print(out)

0 comments on commit 00216ef

Please sign in to comment.