From c309a92034b6839ae328ca49b7bc3570583be3c9 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 23 Dec 2022 15:07:21 -0800 Subject: [PATCH] Added rename_symbols.py to mass rename symbols in an SDL2 codebase --- build-scripts/{rename.py => rename_api.py} | 37 +++---- build-scripts/rename_symbols.py | 111 +++++++++++++++++++++ 2 files changed, 123 insertions(+), 25 deletions(-) rename build-scripts/{rename.py => rename_api.py} (83%) create mode 100755 build-scripts/rename_symbols.py diff --git a/build-scripts/rename.py b/build-scripts/rename_api.py similarity index 83% rename from build-scripts/rename.py rename to build-scripts/rename_api.py index 9939a8c18..5c7b09cd6 100755 --- a/build-scripts/rename.py +++ b/build-scripts/rename_api.py @@ -9,7 +9,7 @@ import os import pathlib import pprint import re - +from rename_symbols import create_regex_from_replacements, replace_symbols_in_path SDL_ROOT = pathlib.Path(__file__).resolve().parents[1] @@ -33,31 +33,18 @@ def main(): if not header.exists(): raise Exception("Couldn't find header %s" % header) - if not pattern.search(header.read_text()): + if not args.skip_header_check and not pattern.search(header.read_text()): raise Exception("Couldn't find %s in %s" % (args.oldname, header)) # Replace the symbol in source code and documentation - for dir in ['src', 'test', 'include']: - replace_symbol_recursive(SDL_ROOT / dir, pattern, args.newname) + replacements = { args.oldname: args.newname } + regex = create_regex_from_replacements(replacements) + for dir in ['src', 'test', 'include', 'docs']: + replace_symbols_in_path(SDL_ROOT / dir, regex, replacements) - if not args.code_only: - replace_symbol_recursive(SDL_ROOT / 'docs', pattern, args.newname) - add_symbol_to_oldnames(header.name, args.oldname, args.newname) - add_symbol_to_migration(header.name, args.type, args.oldname, args.newname) - add_symbol_to_whatsnew(args.type, args.oldname, args.newname) - - -def replace_symbol_recursive(path, pattern, replacement): - for entry in path.glob("*"): - if entry.is_dir(): - replace_symbol_recursive(entry, pattern, replacement) - elif not entry.name.endswith((".bmp", ".cur", ".dat", ".icns", ".png", ".strings", ".swp", ".wav")) and \ - entry.name != "utf8.txt": - print("Processing %s" % entry) - with entry.open('r', encoding='UTF-8', newline='') as rfp: - contents = pattern.sub(replacement, rfp.read()) - with entry.open('w', encoding='UTF-8', newline='') as wfp: - wfp.write(contents) + add_symbol_to_oldnames(header.name, args.oldname, args.newname) + add_symbol_to_migration(header.name, args.type, args.oldname, args.newname) + add_symbol_to_whatsnew(args.type, args.oldname, args.newname) def add_line(lines, i, section): @@ -150,7 +137,7 @@ def add_symbol_to_migration(header, symbol_type, oldname, newname): section_added = False note = ("The following %ss have been renamed:" % symbol_type) note_added = False - content = ("* %s -> %s" % (oldname, newname)) + content = ("* %s => %s" % (oldname, newname)) content_added = False mode = 0 i = 0 @@ -191,7 +178,7 @@ def add_symbol_to_whatsnew(symbol_type, oldname, newname): lines = file.read_text().splitlines() note = ("* The following %ss have been renamed:" % symbol_type) note_added = False - content = (" * %s -> %s" % (oldname, newname)) + content = (" * %s => %s" % (oldname, newname)) content_added = False mode = 0 i = 0 @@ -220,7 +207,7 @@ def add_symbol_to_whatsnew(symbol_type, oldname, newname): if __name__ == '__main__': parser = argparse.ArgumentParser() - parser.add_argument('--code-only', action='store_true') + parser.add_argument('--skip-header-check', action='store_true') parser.add_argument('header'); parser.add_argument('type', choices=['enum', 'function', 'macro', 'structure']); parser.add_argument('oldname'); diff --git a/build-scripts/rename_symbols.py b/build-scripts/rename_symbols.py new file mode 100755 index 000000000..90e584407 --- /dev/null +++ b/build-scripts/rename_symbols.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +# +# This script renames symbols in the specfied paths + +import argparse +import os +import pathlib +import re +import sys + + +SDL_ROOT = pathlib.Path(__file__).resolve().parents[1] + +SDL_INCLUDE_DIR = SDL_ROOT / "include/SDL3" + + +def main(): + if args.all_symbols: + if len(args.args) < 1: + print("Usage: %s --all-symbols files_or_directories ...") + exit(1) + + replacements = get_all_replacements() + entries = args.args + + else: + if len(args.args) < 3: + print("Usage: %s oldname newname files_or_directories ...") + exit(1) + + replacements = { args.args[0]: args.args[1] } + entries = args.args[2:] + + regex = create_regex_from_replacements(replacements) + + for entry in entries: + path = pathlib.Path(entry) + if not path.exists(): + print("%s doesn't exist, skipping" % entry) + continue + + replace_symbols_in_path(path, regex, replacements) + + +def get_all_replacements(): + replacements = {} + file = (SDL_INCLUDE_DIR / "SDL_oldnames.h") + mode = 0 + for line in file.read_text().splitlines(): + if line == "#ifdef SDL_ENABLE_OLD_NAMES": + if mode == 0: + mode = 1 + else: + raise Exception("get_all_replacements(): expected mode 0") + elif line == "#else /* !SDL_ENABLE_OLD_NAMES */": + if mode == 1: + mode = 2 + else: + raise Exception("get_all_replacements(): expected mode 1") + elif mode == 1 and line.startswith("#define "): + words = line.split() + replacements[words[1]] = words[2] + + return replacements + + +def create_regex_from_replacements(replacements): + return re.compile(r"\b(%s)\b" % "|".join(map(re.escape, replacements.keys()))) + + +def replace_symbols_in_file(file, regex, replacements): + try: + with file.open('r', encoding='UTF-8', newline='') as rfp: + contents = regex.sub(lambda mo: replacements[mo.string[mo.start():mo.end()]], rfp.read()) + with file.open('w', encoding='UTF-8', newline='') as wfp: + wfp.write(contents) + except UnicodeDecodeError: + print("%s is not text, skipping" % file) + + +def replace_symbols_in_dir(path, regex, replacements): + for entry in path.glob("*"): + if entry.is_dir(): + replace_symbols_in_dir(entry, regex, replacements) + else: + print("Processing %s" % entry) + replace_symbols_in_file(entry, regex, replacements) + + +def replace_symbols_in_path(path, regex, replacements): + if path.is_dir(): + replace_symbols_in_dir(path, regex, replacements) + else: + replace_symbols_in_file(path, regex, replacements) + + +if __name__ == '__main__': + + parser = argparse.ArgumentParser() + parser.add_argument('--all-symbols', action='store_true') + parser.add_argument('args', nargs='*') + args = parser.parse_args() + + try: + main() + except Exception as e: + print(e) + exit(-1) + + exit(0) +