mirror of
https://github.com/HarbourMasters/Starship.git
synced 2025-02-09 03:37:49 +03:00
Fixed and imported sym_info and name_fixer tools (#73)
This commit is contained in:
parent
3036b48338
commit
40af0ffc3d
29
sym_info.py
Normal file
29
sym_info.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
try:
|
||||||
|
import mapfile_parser
|
||||||
|
except ImportError:
|
||||||
|
print("Missing dependency mapfile_parser, install it with `python3 -m pip install 'mapfile-parser>=1.2.1,<2.0.0'`")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def symInfoMain():
|
||||||
|
parser = argparse.ArgumentParser(description="Display various information about a symbol or address.")
|
||||||
|
parser.add_argument("symname", help="symbol name or VROM/VRAM address to lookup")
|
||||||
|
parser.add_argument("-e", "--expected", dest="use_expected", action="store_true", help="use the map file in expected/build/ instead of build/")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
BUILTMAP = Path(f"build") / f"starfox64.us.map"
|
||||||
|
|
||||||
|
mapPath = BUILTMAP
|
||||||
|
if args.use_expected:
|
||||||
|
mapPath = "expected" / BUILTMAP
|
||||||
|
|
||||||
|
mapfile_parser.frontends.sym_info.doSymInfo(mapPath, args.symname)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
symInfoMain()
|
147
tools/name_fixer.py
Normal file
147
tools/name_fixer.py
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
# all occurrences of keys will be replaced by associated value
|
||||||
|
simpleReplace = {}
|
||||||
|
|
||||||
|
# all occurrences of keys will be replaced by associated value,
|
||||||
|
# if the occurence is the whole word
|
||||||
|
# for example, if there is a space before and an open parenthesis after,
|
||||||
|
# like for a function call: ` func_8002E4B4(`
|
||||||
|
#
|
||||||
|
# Custom behaviour can be enabled by using a tuple as the value (see
|
||||||
|
# explanation in replace_single below)
|
||||||
|
wordReplace = {
|
||||||
|
"func_80086B30": "new_func_naame",
|
||||||
|
"var": "new_var_name",
|
||||||
|
}
|
||||||
|
|
||||||
|
# [a-zA-Z0-9_]
|
||||||
|
def is_word_char(c):
|
||||||
|
return (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z') or (c >= '0' and c <= '9') or c == '_'
|
||||||
|
|
||||||
|
def replace_single(file):
|
||||||
|
with open(file, 'r', encoding = 'utf-8') as infile:
|
||||||
|
srcdata = infile.read()
|
||||||
|
|
||||||
|
changesCount = 0
|
||||||
|
|
||||||
|
for old, new in simpleReplace.items():
|
||||||
|
# replace `old` with `new`
|
||||||
|
if old in srcdata:
|
||||||
|
changesCount += 1
|
||||||
|
print(old, "->", new)
|
||||||
|
srcdata = srcdata.replace(old, new)
|
||||||
|
|
||||||
|
for old, new in wordReplace.items():
|
||||||
|
# `new` can be a tuple where the first element is what to replace `old` with,
|
||||||
|
# and the second element is a dict containing "custom behavior" properties.
|
||||||
|
if isinstance(new, tuple):
|
||||||
|
custom_behavior = True
|
||||||
|
new, custom_behavior_data = new
|
||||||
|
# The "ignore" data is a tuple where the first element is an offset relative to
|
||||||
|
# where `old` was found, and the string from that index must differ from the
|
||||||
|
# tuple's second element for the replacement to be done.
|
||||||
|
custom_behavior_ignore_data = custom_behavior_data.get("ignore")
|
||||||
|
custom_behavior_ignore = custom_behavior_ignore_data is not None
|
||||||
|
if custom_behavior_ignore:
|
||||||
|
custom_behavior_ignore_offset, custom_behavior_ignore_match = custom_behavior_ignore_data
|
||||||
|
else:
|
||||||
|
custom_behavior = False
|
||||||
|
# replace `old` with `new` if the occurence of `old` is the whole word
|
||||||
|
oldStartIdx = srcdata.find(old)
|
||||||
|
if oldStartIdx >= 0:
|
||||||
|
old_start_as_word = is_word_char(old[0])
|
||||||
|
old_end_as_word = is_word_char(old[-1])
|
||||||
|
replaceCount = 0
|
||||||
|
while oldStartIdx >= 0:
|
||||||
|
replace = True
|
||||||
|
if old_start_as_word:
|
||||||
|
if oldStartIdx == 0:
|
||||||
|
pass
|
||||||
|
elif is_word_char(srcdata[oldStartIdx-1]):
|
||||||
|
replace = False
|
||||||
|
if old_end_as_word:
|
||||||
|
oldEndIdx = oldStartIdx + len(old)
|
||||||
|
if oldEndIdx >= len(srcdata):
|
||||||
|
pass
|
||||||
|
elif is_word_char(srcdata[oldEndIdx]):
|
||||||
|
replace = False
|
||||||
|
if replace and custom_behavior and custom_behavior_ignore:
|
||||||
|
if srcdata[oldStartIdx + custom_behavior_ignore_offset:].startswith(custom_behavior_ignore_match):
|
||||||
|
replace = False
|
||||||
|
if replace:
|
||||||
|
srcdata = srcdata[:oldStartIdx] + new + srcdata[oldEndIdx:]
|
||||||
|
replaceCount += 1
|
||||||
|
oldStartIdx = srcdata.find(old, oldStartIdx + len(new))
|
||||||
|
if replaceCount > 0:
|
||||||
|
changesCount += 1
|
||||||
|
print(old, "->", new)
|
||||||
|
|
||||||
|
if changesCount > 0:
|
||||||
|
print('Changed', changesCount, 'entry' if changesCount == 1 else 'entries', 'in', file)
|
||||||
|
with open(file, 'w', encoding = 'utf-8', newline = '\n') as outfile:
|
||||||
|
outfile.write(srcdata)
|
||||||
|
|
||||||
|
def replace_all(repo):
|
||||||
|
for subdir, dirs, files in os.walk(os.path.join(repo,'src')):
|
||||||
|
for filename in files:
|
||||||
|
if filename.endswith('.c') or filename.endswith('.h'):
|
||||||
|
file = os.path.join(subdir,filename)
|
||||||
|
replace_single(file)
|
||||||
|
|
||||||
|
for subdir, dirs, files in os.walk(os.path.join(repo,'asm')):
|
||||||
|
for filename in files:
|
||||||
|
if filename.endswith('.s'):
|
||||||
|
file = os.path.join(subdir,filename)
|
||||||
|
replace_single(file)
|
||||||
|
|
||||||
|
for subdir, dirs, files in os.walk(os.path.join(repo,'data')):
|
||||||
|
for filename in files:
|
||||||
|
if filename.endswith('.s'):
|
||||||
|
file = os.path.join(subdir,filename)
|
||||||
|
replace_single(file)
|
||||||
|
|
||||||
|
for subdir, dirs, files in os.walk(os.path.join(repo,'docs')):
|
||||||
|
for filename in files:
|
||||||
|
if filename.endswith('.md'):
|
||||||
|
file = os.path.join(subdir,filename)
|
||||||
|
replace_single(file)
|
||||||
|
|
||||||
|
|
||||||
|
def dictSanityCheck():
|
||||||
|
keys = wordReplace.keys()
|
||||||
|
values = wordReplace.values()
|
||||||
|
for k in keys:
|
||||||
|
if k in values:
|
||||||
|
print(f"Key '{k}' found in values")
|
||||||
|
print(f"This would produce unintended renames")
|
||||||
|
print(f"Fix this by removing said key from the dictionary")
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
keys = simpleReplace.keys()
|
||||||
|
values = {*wordReplace.values(), *simpleReplace.values()}
|
||||||
|
for k in keys:
|
||||||
|
for value in values:
|
||||||
|
if k in value:
|
||||||
|
print(f"Key '{k}' found in values")
|
||||||
|
print(f"This would produce unintended renames")
|
||||||
|
print(f"Fix this by removing said key from the dictionary")
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Apply function renames to a file')
|
||||||
|
parser.add_argument('file', help="source file to be processed. use . to process the whole repo")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
dictSanityCheck()
|
||||||
|
|
||||||
|
if args.file == '.':
|
||||||
|
replace_all(os.curdir)
|
||||||
|
else:
|
||||||
|
replace_single(args.file)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user