diff options
Diffstat (limited to 'contrib/SDL-3.2.8/build-scripts/rename_api.py')
| -rwxr-xr-x | contrib/SDL-3.2.8/build-scripts/rename_api.py | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/build-scripts/rename_api.py b/contrib/SDL-3.2.8/build-scripts/rename_api.py new file mode 100755 index 0000000..605ffa0 --- /dev/null +++ b/contrib/SDL-3.2.8/build-scripts/rename_api.py | |||
| @@ -0,0 +1,254 @@ | |||
| 1 | #!/usr/bin/env python3 | ||
| 2 | # | ||
| 3 | # This script renames symbols in the API, updating SDL_oldnames.h and | ||
| 4 | # adding documentation for the change. | ||
| 5 | |||
| 6 | import argparse | ||
| 7 | import os | ||
| 8 | import pathlib | ||
| 9 | import pprint | ||
| 10 | import re | ||
| 11 | import sys | ||
| 12 | from rename_symbols import create_regex_from_replacements, replace_symbols_in_path | ||
| 13 | |||
| 14 | SDL_ROOT = pathlib.Path(__file__).resolve().parents[1] | ||
| 15 | |||
| 16 | SDL_INCLUDE_DIR = SDL_ROOT / "include/SDL3" | ||
| 17 | SDL_BUILD_SCRIPTS = SDL_ROOT / "build-scripts" | ||
| 18 | |||
| 19 | |||
| 20 | def main(): | ||
| 21 | if len(args.args) == 0 or (len(args.args) % 2) != 0: | ||
| 22 | print("Usage: %s [-h] [--skip-header-check] header {enum,function,hint,structure,symbol} [old new ...]" % sys.argv[0]) | ||
| 23 | exit(1) | ||
| 24 | |||
| 25 | # Check whether we can still modify the ABI | ||
| 26 | version_header = pathlib.Path( SDL_INCLUDE_DIR / "SDL_version.h" ).read_text() | ||
| 27 | if not re.search(r"SDL_MINOR_VERSION\s+[01]\s", version_header): | ||
| 28 | raise Exception("ABI is frozen, symbols cannot be renamed") | ||
| 29 | |||
| 30 | # Find the symbol in the headers | ||
| 31 | if pathlib.Path(args.header).is_file(): | ||
| 32 | header = pathlib.Path(args.header) | ||
| 33 | else: | ||
| 34 | header = pathlib.Path(SDL_INCLUDE_DIR / args.header) | ||
| 35 | |||
| 36 | if not header.exists(): | ||
| 37 | raise Exception("Couldn't find header %s" % header) | ||
| 38 | |||
| 39 | header_name = header.name | ||
| 40 | if (header.name == "SDL_gamepad.h"): | ||
| 41 | header_name = "SDL_gamecontroller.h" | ||
| 42 | |||
| 43 | header_text = header.read_text() | ||
| 44 | |||
| 45 | # Replace the symbols in source code | ||
| 46 | replacements = {} | ||
| 47 | i = 0 | ||
| 48 | while i < len(args.args): | ||
| 49 | oldname = args.args[i + 0] | ||
| 50 | newname = args.args[i + 1] | ||
| 51 | |||
| 52 | if not args.skip_header_check and not re.search((r"\b%s\b" % oldname), header_text): | ||
| 53 | raise Exception("Couldn't find %s in %s" % (oldname, header)) | ||
| 54 | |||
| 55 | replacements[ oldname ] = newname | ||
| 56 | replacements[ oldname + "_REAL" ] = newname + "_REAL" | ||
| 57 | i += 2 | ||
| 58 | |||
| 59 | regex = create_regex_from_replacements(replacements) | ||
| 60 | for dir in ["src", "test", "examples", "include", "docs", "cmake/test"]: | ||
| 61 | replace_symbols_in_path(SDL_ROOT / dir, regex, replacements) | ||
| 62 | |||
| 63 | # Replace the symbols in documentation | ||
| 64 | i = 0 | ||
| 65 | while i < len(args.args): | ||
| 66 | oldname = args.args[i + 0] | ||
| 67 | newname = args.args[i + 1] | ||
| 68 | |||
| 69 | add_symbol_to_oldnames(header_name, oldname, newname) | ||
| 70 | add_symbol_to_migration(header_name, args.type, oldname, newname) | ||
| 71 | add_symbol_to_coccinelle(args.type, oldname, newname) | ||
| 72 | i += 2 | ||
| 73 | |||
| 74 | |||
| 75 | def add_line(lines, i, section): | ||
| 76 | lines.insert(i, section) | ||
| 77 | i += 1 | ||
| 78 | return i | ||
| 79 | |||
| 80 | |||
| 81 | def add_content(lines, i, content, add_trailing_line): | ||
| 82 | if lines[i - 1] == "": | ||
| 83 | lines[i - 1] = content | ||
| 84 | else: | ||
| 85 | i = add_line(lines, i, content) | ||
| 86 | |||
| 87 | if add_trailing_line: | ||
| 88 | i = add_line(lines, i, "") | ||
| 89 | return i | ||
| 90 | |||
| 91 | |||
| 92 | def add_symbol_to_coccinelle(symbol_type, oldname, newname): | ||
| 93 | file = open(SDL_BUILD_SCRIPTS / "SDL_migration.cocci", "a") | ||
| 94 | # Append-adds at last | ||
| 95 | |||
| 96 | if symbol_type == "function": | ||
| 97 | file.write("@@\n") | ||
| 98 | file.write("@@\n") | ||
| 99 | file.write("- %s\n" % oldname) | ||
| 100 | file.write("+ %s\n" % newname) | ||
| 101 | file.write(" (...)\n") | ||
| 102 | |||
| 103 | if symbol_type == "symbol": | ||
| 104 | file.write("@@\n") | ||
| 105 | file.write("@@\n") | ||
| 106 | file.write("- %s\n" % oldname) | ||
| 107 | file.write("+ %s\n" % newname) | ||
| 108 | |||
| 109 | # double check ? | ||
| 110 | if symbol_type == "hint": | ||
| 111 | file.write("@@\n") | ||
| 112 | file.write("@@\n") | ||
| 113 | file.write("- %s\n" % oldname) | ||
| 114 | file.write("+ %s\n" % newname) | ||
| 115 | |||
| 116 | if symbol_type == "enum" or symbol_type == "structure": | ||
| 117 | file.write("@@\n") | ||
| 118 | file.write("typedef %s, %s;\n" % (oldname, newname)) | ||
| 119 | file.write("@@\n") | ||
| 120 | file.write("- %s\n" % oldname) | ||
| 121 | file.write("+ %s\n" % newname) | ||
| 122 | |||
| 123 | file.close() | ||
| 124 | |||
| 125 | |||
| 126 | def add_symbol_to_oldnames(header, oldname, newname): | ||
| 127 | file = (SDL_INCLUDE_DIR / "SDL_oldnames.h") | ||
| 128 | lines = file.read_text().splitlines() | ||
| 129 | mode = 0 | ||
| 130 | i = 0 | ||
| 131 | while i < len(lines): | ||
| 132 | line = lines[i] | ||
| 133 | if line == "#ifdef SDL_ENABLE_OLD_NAMES": | ||
| 134 | if mode == 0: | ||
| 135 | mode = 1 | ||
| 136 | section = ("/* ##%s */" % header) | ||
| 137 | section_added = False | ||
| 138 | content = ("#define %s %s" % (oldname, newname)) | ||
| 139 | content_added = False | ||
| 140 | else: | ||
| 141 | raise Exception("add_symbol_to_oldnames(): expected mode 0") | ||
| 142 | elif line == "#elif !defined(SDL_DISABLE_OLD_NAMES)": | ||
| 143 | if mode == 1: | ||
| 144 | if not section_added: | ||
| 145 | i = add_line(lines, i, section) | ||
| 146 | |||
| 147 | if not content_added: | ||
| 148 | i = add_content(lines, i, content, True) | ||
| 149 | |||
| 150 | mode = 2 | ||
| 151 | section = ("/* ##%s */" % header) | ||
| 152 | section_added = False | ||
| 153 | content = ("#define %s %s_renamed_%s" % (oldname, oldname, newname)) | ||
| 154 | content_added = False | ||
| 155 | else: | ||
| 156 | raise Exception("add_symbol_to_oldnames(): expected mode 1") | ||
| 157 | elif line == "#endif /* SDL_ENABLE_OLD_NAMES */": | ||
| 158 | if mode == 2: | ||
| 159 | if not section_added: | ||
| 160 | i = add_line(lines, i, section) | ||
| 161 | |||
| 162 | if not content_added: | ||
| 163 | i = add_content(lines, i, content, True) | ||
| 164 | |||
| 165 | mode = 3 | ||
| 166 | else: | ||
| 167 | raise Exception("add_symbol_to_oldnames(): expected mode 2") | ||
| 168 | elif line != "" and (mode == 1 or mode == 2): | ||
| 169 | if line.startswith("/* ##"): | ||
| 170 | if section_added: | ||
| 171 | if not content_added: | ||
| 172 | i = add_content(lines, i, content, True) | ||
| 173 | content_added = True | ||
| 174 | elif line == section: | ||
| 175 | section_added = True | ||
| 176 | elif section < line: | ||
| 177 | i = add_line(lines, i, section) | ||
| 178 | section_added = True | ||
| 179 | i = add_content(lines, i, content, True) | ||
| 180 | content_added = True | ||
| 181 | elif line != "" and section_added and not content_added: | ||
| 182 | if content == line: | ||
| 183 | content_added = True | ||
| 184 | elif content < line: | ||
| 185 | i = add_content(lines, i, content, False) | ||
| 186 | content_added = True | ||
| 187 | i += 1 | ||
| 188 | |||
| 189 | file.write_text("\n".join(lines) + "\n") | ||
| 190 | |||
| 191 | |||
| 192 | def add_symbol_to_migration(header, symbol_type, oldname, newname): | ||
| 193 | file = (SDL_ROOT / "docs/README-migration.md") | ||
| 194 | lines = file.read_text().splitlines() | ||
| 195 | section = ("## %s" % header) | ||
| 196 | section_added = False | ||
| 197 | note = ("The following %ss have been renamed:" % symbol_type) | ||
| 198 | note_added = False | ||
| 199 | if symbol_type == "function": | ||
| 200 | content = ("* %s() => %s()" % (oldname, newname)) | ||
| 201 | else: | ||
| 202 | content = ("* %s => %s" % (oldname, newname)) | ||
| 203 | content_added = False | ||
| 204 | mode = 0 | ||
| 205 | i = 0 | ||
| 206 | while i < len(lines): | ||
| 207 | line = lines[i] | ||
| 208 | if line.startswith("##") and line.endswith(".h"): | ||
| 209 | if line == section: | ||
| 210 | section_added = True | ||
| 211 | elif section < line: | ||
| 212 | break | ||
| 213 | |||
| 214 | elif section_added and not note_added: | ||
| 215 | if note == line: | ||
| 216 | note_added = True | ||
| 217 | elif note_added and not content_added: | ||
| 218 | if content == line: | ||
| 219 | content_added = True | ||
| 220 | elif line == "" or content < line: | ||
| 221 | i = add_line(lines, i, content) | ||
| 222 | content_added = True | ||
| 223 | i += 1 | ||
| 224 | |||
| 225 | if not section_added: | ||
| 226 | i = add_line(lines, i, section) | ||
| 227 | i = add_line(lines, i, "") | ||
| 228 | |||
| 229 | if not note_added: | ||
| 230 | i = add_line(lines, i, note) | ||
| 231 | |||
| 232 | if not content_added: | ||
| 233 | i = add_content(lines, i, content, True) | ||
| 234 | |||
| 235 | file.write_text("\n".join(lines) + "\n") | ||
| 236 | |||
| 237 | |||
| 238 | if __name__ == "__main__": | ||
| 239 | |||
| 240 | parser = argparse.ArgumentParser(fromfile_prefix_chars='@') | ||
| 241 | parser.add_argument("--skip-header-check", action="store_true") | ||
| 242 | parser.add_argument("header") | ||
| 243 | parser.add_argument("type", choices=["enum", "function", "hint", "structure", "symbol"]) | ||
| 244 | parser.add_argument("args", nargs="*") | ||
| 245 | args = parser.parse_args() | ||
| 246 | |||
| 247 | try: | ||
| 248 | main() | ||
| 249 | except Exception as e: | ||
| 250 | print(e) | ||
| 251 | exit(-1) | ||
| 252 | |||
| 253 | exit(0) | ||
| 254 | |||
