Added infrastructure for renaming API functions

You can rename APIs using rename.py and all the code and documentation will be updated, and entries will be added to WhatsNew.txt and docs/README-migration.md.
e.g.
rename.py SDL_foo.h function SDL_CreateFoo SDL_FooCreate

SDL_oldnames.h is included in the SDL header, and if you define SDL_ENABLE_OLD_NAMES, will redefine the old API functions to call the new ones, and if not, will define them as a symbol letting you what the new API function is.
This commit is contained in:
Sam Lantinga 2022-12-22 16:45:43 -08:00
parent 08c45eb37e
commit b5a92406eb
3 changed files with 279 additions and 1 deletions

234
build-scripts/rename.py Executable file
View File

@ -0,0 +1,234 @@
#!/usr/bin/env python3
# WHAT IS THIS?
# This script renames symbols in the API, updating SDL_oldnames.h and
# adding documentation for the change.
import argparse
import os
import pathlib
import pprint
import re
SDL_ROOT = pathlib.Path(__file__).resolve().parents[1]
SDL_INCLUDE_DIR = SDL_ROOT / "include/SDL3"
def main():
# Check whether we can still modify the ABI
version_header = pathlib.Path( SDL_INCLUDE_DIR / "SDL_version.h" ).read_text()
if not re.search("SDL_MINOR_VERSION\s+[01]\s", version_header):
raise Exception("ABI is frozen, symbols cannot be renamed")
pattern = re.compile(r"\b%s\b" % args.oldname)
# Find the symbol in the headers
if pathlib.Path(args.header).is_file():
header = pathlib.Path(args.header)
else:
header = pathlib.Path(SDL_INCLUDE_DIR / args.header)
if not header.exists():
raise Exception("Couldn't find header %s" % header)
if 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', 'docs']:
replace_symbol_recursive(SDL_ROOT / dir, 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)
def add_line(lines, i, section):
lines.insert(i, section)
i += 1
return i
def add_content(lines, i, content, add_trailing_line):
if lines[i - 1] == "":
lines[i - 1] = content
else:
i = add_line(lines, i, content)
if add_trailing_line:
i = add_line(lines, i, "")
return i
def add_symbol_to_oldnames(header, oldname, newname):
file = (SDL_INCLUDE_DIR / "SDL_oldnames.h")
lines = file.read_text().splitlines()
mode = 0
i = 0
while i < len(lines):
line = lines[i]
if line == "#ifdef SDL_ENABLE_OLD_NAMES":
if mode == 0:
mode = 1
section = ("/* ##%s */" % header)
section_added = False
content = ("#define %s %s" % (oldname, newname))
content_added = False
else:
raise Exception("add_symbol_to_oldnames(): expected mode 0")
elif line == "#else /* !SDL_ENABLE_OLD_NAMES */":
if mode == 1:
if not section_added:
i = add_line(lines, i, section)
if not content_added:
i = add_content(lines, i, content, True)
mode = 2
section = ("/* ##%s */" % header)
section_added = False
content = ("#define %s %s_renamed_%s" % (oldname, oldname, newname))
content_added = False
else:
raise Exception("add_symbol_to_oldnames(): expected mode 1")
elif line == "#endif /* SDL_ENABLE_OLD_NAMES */":
if mode == 2:
if not section_added:
i = add_line(lines, i, section)
if not content_added:
i = add_content(lines, i, content, True)
mode = 3
else:
raise Exception("add_symbol_to_oldnames(): expected mode 2")
elif line != "" and (mode == 1 or mode == 2):
if line.startswith("/* ##"):
if section_added:
if not content_added:
i = add_content(lines, i, content, True)
content_added = True
elif line == section:
section_added = True
elif section < line:
i = add_line(lines, i, section)
section_added = True
i = add_content(lines, i, content, True)
content_added = True
elif line != "" and section_added and not content_added:
if content == line:
content_added = True
elif content < line:
i = add_content(lines, i, content, False)
content_added = True
i += 1
file.write_text("\n".join(lines) + "\n")
def add_symbol_to_migration(header, symbol_type, oldname, newname):
file = (SDL_ROOT / "docs/README-migration.md")
lines = file.read_text().splitlines()
section = ("## %s" % header)
section_added = False
note = ("The following %ss have been renamed:" % symbol_type)
note_added = False
content = ("* %s -> %s" % (oldname, newname))
content_added = False
mode = 0
i = 0
while i < len(lines):
line = lines[i]
if line.startswith("##") and line.endswith(".h"):
if line == section:
section_added = True
elif section < line:
break
elif section_added and not note_added:
if note == line:
note_added = True
elif note_added and not content_added:
if content == line:
content_added = True
elif line == "" or content < line:
i = add_line(lines, i, content)
content_added = True
i += 1
if not section_added:
i = add_line(lines, i, section)
i = add_line(lines, i, "")
if not note_added:
i = add_line(lines, i, note)
if not content_added:
i = add_content(lines, i, content, True)
file.write_text("\n".join(lines) + "\n")
def add_symbol_to_whatsnew(symbol_type, oldname, newname):
file = (SDL_ROOT / "WhatsNew.txt")
lines = file.read_text().splitlines()
note = ("* The following %ss have been renamed:" % symbol_type)
note_added = False
content = (" * %s -> %s" % (oldname, newname))
content_added = False
mode = 0
i = 0
while i < len(lines):
line = lines[i]
if not note_added:
if note == line:
note_added = True
elif not content_added:
if content == line:
content_added = True
elif not line.startswith(" *") or content < line:
i = add_line(lines, i, content)
content_added = True
i += 1
if not note_added:
i = add_line(lines, i, note)
if not content_added:
i = add_line(lines, i, content)
file.write_text("\r\n".join(lines) + "\r\n")
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('header');
parser.add_argument('type', choices=['function', 'enum']);
parser.add_argument('oldname');
parser.add_argument('newname');
args = parser.parse_args()
try:
main()
except Exception as e:
print(e)
exit(-1)
exit(0)

View File

@ -46,6 +46,7 @@
#include <SDL3/SDL_haptic.h>
#include <SDL3/SDL_hidapi.h>
#include <SDL3/SDL_hints.h>
#include <SDL3/SDL_init.h>
#include <SDL3/SDL_joystick.h>
#include <SDL3/SDL_keyboard.h>
#include <SDL3/SDL_keycode.h>
@ -75,7 +76,7 @@
#include <SDL3/SDL_touch.h>
#include <SDL3/SDL_version.h>
#include <SDL3/SDL_video.h>
#include <SDL3/SDL_init.h>
#include <SDL3/SDL_oldnames.h>
#endif /* SDL_h_ */

View File

@ -0,0 +1,43 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/**
* \file SDL_oldnames.h
*
* Definitions to ease transition from SDL2 code
*/
#ifndef SDL_oldnames_h_
#define SDL_oldnames_h_
/* The new function names are recommended, but if you want to have the
* old names available while you are in the process of migrating code
* to SDL3, you can define `SDL_ENABLE_OLD_NAMES` in your project.
*/
#ifdef SDL_ENABLE_OLD_NAMES
#else /* !SDL_ENABLE_OLD_NAMES */
#endif /* SDL_ENABLE_OLD_NAMES */
#endif /* SDL_oldnames_h_ */
/* vi: set ts=4 sw=4 expandtab: */