diff options
author | 3gg <3gg@shellblade.net> | 2025-08-30 16:53:58 -0700 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2025-08-30 16:53:58 -0700 |
commit | 6aaedb813fa11ba0679c3051bc2eb28646b9506c (patch) | |
tree | 34acbfc9840e02cb4753e6306ea7ce978bf8b58e /src/contrib/SDL-3.2.20/build-scripts/rename_api.py | |
parent | 8f228ade99dd3d4c8da9b78ade1815c9adf85c8f (diff) |
Update to SDL3
Diffstat (limited to 'src/contrib/SDL-3.2.20/build-scripts/rename_api.py')
-rwxr-xr-x | src/contrib/SDL-3.2.20/build-scripts/rename_api.py | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/build-scripts/rename_api.py b/src/contrib/SDL-3.2.20/build-scripts/rename_api.py new file mode 100755 index 0000000..605ffa0 --- /dev/null +++ b/src/contrib/SDL-3.2.20/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 | |||