Make it easier to mass rename symbols in the SDL API

This commit is contained in:
Sam Lantinga 2022-12-27 07:31:27 -08:00
parent c6969df4d7
commit 59467ff063
2 changed files with 56 additions and 32 deletions

View File

@ -1,14 +1,14 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
#
# WHAT IS THIS? # This script renames symbols in the API, updating SDL_oldnames.h and
# This script renames symbols in the API, updating SDL_oldnames.h and # adding documentation for the change.
# adding documentation for the change.
import argparse import argparse
import os import os
import pathlib import pathlib
import pprint import pprint
import re import re
import sys
from rename_symbols import create_regex_from_replacements, replace_symbols_in_path from rename_symbols import create_regex_from_replacements, replace_symbols_in_path
SDL_ROOT = pathlib.Path(__file__).resolve().parents[1] SDL_ROOT = pathlib.Path(__file__).resolve().parents[1]
@ -17,13 +17,15 @@ SDL_INCLUDE_DIR = SDL_ROOT / "include/SDL3"
def main(): def main():
if len(args.args) == 0 or (len(args.args) % 2) != 0:
print("Usage: %s [-h] [--skip-header-check] header {enum,function,macro,structure,symbol} [old new ...]" % sys.argv[0])
exit(1)
# Check whether we can still modify the ABI # Check whether we can still modify the ABI
version_header = pathlib.Path( SDL_INCLUDE_DIR / "SDL_version.h" ).read_text() version_header = pathlib.Path( SDL_INCLUDE_DIR / "SDL_version.h" ).read_text()
if not re.search("SDL_MINOR_VERSION\s+[01]\s", version_header): if not re.search("SDL_MINOR_VERSION\s+[01]\s", version_header):
raise Exception("ABI is frozen, symbols cannot be renamed") raise Exception("ABI is frozen, symbols cannot be renamed")
pattern = re.compile(r"\b%s\b" % args.oldname)
# Find the symbol in the headers # Find the symbol in the headers
if pathlib.Path(args.header).is_file(): if pathlib.Path(args.header).is_file():
header = pathlib.Path(args.header) header = pathlib.Path(args.header)
@ -33,21 +35,36 @@ def main():
if not header.exists(): if not header.exists():
raise Exception("Couldn't find header %s" % header) raise Exception("Couldn't find header %s" % header)
if not args.skip_header_check and not pattern.search(header.read_text()): header_text = header.read_text()
raise Exception("Couldn't find %s in %s" % (args.oldname, header))
# Replace the symbols in source code
replacements = {}
i = 0
while i < len(args.args):
oldname = args.args[i + 0]
newname = args.args[i + 1]
if not args.skip_header_check and not re.search((r"\b%s\b" % oldname), header_text):
raise Exception("Couldn't find %s in %s" % (oldname, header))
replacements[ oldname ] = newname
replacements[ oldname + "_REAL" ] = newname + "_REAL"
i += 2
# Replace the symbol in source code and documentation
replacements = {
args.oldname: args.newname,
args.oldname + "_REAL": args.newname + "_REAL"
}
regex = create_regex_from_replacements(replacements) regex = create_regex_from_replacements(replacements)
for dir in ["src", "test", "include", "docs", "Xcode-iOS/Demos"]: for dir in ["src", "test", "include", "docs", "Xcode-iOS/Demos"]:
replace_symbols_in_path(SDL_ROOT / dir, regex, replacements) replace_symbols_in_path(SDL_ROOT / dir, regex, replacements)
add_symbol_to_oldnames(header.name, args.oldname, args.newname) # Replace the symbols in documentation
add_symbol_to_migration(header.name, args.type, args.oldname, args.newname) i = 0
add_symbol_to_whatsnew(args.type, args.oldname, args.newname) while i < len(args.args):
oldname = args.args[i + 0]
newname = args.args[i + 1]
add_symbol_to_oldnames(header.name, oldname, newname)
add_symbol_to_migration(header.name, args.type, oldname, newname)
add_symbol_to_whatsnew(args.type, oldname, newname)
i += 2
def add_line(lines, i, section): def add_line(lines, i, section):
@ -207,14 +224,13 @@ def add_symbol_to_whatsnew(symbol_type, oldname, newname):
file.write_text("\r\n".join(lines) + "\r\n") file.write_text("\r\n".join(lines) + "\r\n")
if __name__ == '__main__': if __name__ == "__main__":
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
parser.add_argument('--skip-header-check', action='store_true') parser.add_argument("--skip-header-check", action="store_true")
parser.add_argument('header'); parser.add_argument("header");
parser.add_argument('type', choices=['enum', 'function', 'macro', 'structure']); parser.add_argument("type", choices=["enum", "function", "macro", "structure", "symbol"]);
parser.add_argument('oldname'); parser.add_argument("args", nargs="*")
parser.add_argument('newname');
args = parser.parse_args() args = parser.parse_args()
try: try:

View File

@ -17,7 +17,7 @@ SDL_INCLUDE_DIR = SDL_ROOT / "include/SDL3"
def main(): def main():
if args.all_symbols: if args.all_symbols:
if len(args.args) < 1: if len(args.args) < 1:
print("Usage: %s --all-symbols files_or_directories ...") print("Usage: %s --all-symbols files_or_directories ..." % sys.argv[0])
exit(1) exit(1)
replacements = get_all_replacements() replacements = get_all_replacements()
@ -25,13 +25,16 @@ def main():
else: else:
if len(args.args) < 3: if len(args.args) < 3:
print("Usage: %s oldname newname files_or_directories ...") print("Usage: %s oldname newname files_or_directories ..." % sys.argv[0])
exit(1) exit(1)
replacements = { args.args[0]: args.args[1] } replacements = { args.args[0]: args.args[1] }
entries = args.args[2:] entries = args.args[2:]
regex = create_regex_from_replacements(replacements) if args.substring:
regex = create_substring_regex_from_replacements(replacements)
else:
regex = create_regex_from_replacements(replacements)
for entry in entries: for entry in entries:
path = pathlib.Path(entry) path = pathlib.Path(entry)
@ -68,11 +71,15 @@ def create_regex_from_replacements(replacements):
return re.compile(r"\b(%s)\b" % "|".join(map(re.escape, replacements.keys()))) return re.compile(r"\b(%s)\b" % "|".join(map(re.escape, replacements.keys())))
def create_substring_regex_from_replacements(replacements):
return re.compile(r"(%s)" % "|".join(map(re.escape, replacements.keys())))
def replace_symbols_in_file(file, regex, replacements): def replace_symbols_in_file(file, regex, replacements):
try: try:
with file.open('r', encoding='UTF-8', newline='') as rfp: with file.open("r", encoding="UTF-8", newline="") as rfp:
contents = regex.sub(lambda mo: replacements[mo.string[mo.start():mo.end()]], rfp.read()) contents = regex.sub(lambda mo: replacements[mo.string[mo.start():mo.end()]], rfp.read())
with file.open('w', encoding='UTF-8', newline='') as wfp: with file.open("w", encoding="UTF-8", newline="") as wfp:
wfp.write(contents) wfp.write(contents)
except UnicodeDecodeError: except UnicodeDecodeError:
print("%s is not text, skipping" % file) print("%s is not text, skipping" % file)
@ -94,11 +101,12 @@ def replace_symbols_in_path(path, regex, replacements):
replace_symbols_in_file(path, regex, replacements) replace_symbols_in_file(path, regex, replacements)
if __name__ == '__main__': if __name__ == "__main__":
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
parser.add_argument('--all-symbols', action='store_true') parser.add_argument("--all-symbols", action="store_true")
parser.add_argument('args', nargs='*') parser.add_argument("--substring", action="store_true")
parser.add_argument("args", nargs="*")
args = parser.parse_args() args = parser.parse_args()
try: try: