
- Always use internal qsort and bsearch implementation. - add "_r" reentrant versions. The reasons for always using the internal versions is that the C runtime versions' callbacks are not mark STDCALL, so we would have add bridge functions for them anyhow, The C runtime qsort_r/qsort_s have different orders of arguments on different platforms, and most importantly: qsort() isn't a stable sort, and isn't guaranteed to give the same ordering for two objects marked as equal by the callback...as such, Visual Studio and glibc can give different sort results for the same data set...in this sense, having one piece of code shared on all platforms makes sense here, for reliabillity. bsearch does not have a standard _r version at all, and suffers from the same SDLCALL concern. Since the code is simple and we would have to work around the C runtime, it's easier to just go with the built-in function and remove all the CMake C runtime tests. Fixes #9159.
264 lines
5.8 KiB
Python
Executable File
264 lines
5.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# Simple DirectMedia Layer
|
|
# Copyright (C) 1997-2024 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.
|
|
#
|
|
# This script detects use of stdlib function in SDL code
|
|
|
|
import argparse
|
|
import os
|
|
import pathlib
|
|
import re
|
|
import sys
|
|
|
|
SDL_ROOT = pathlib.Path(__file__).resolve().parents[1]
|
|
|
|
words = [
|
|
'abs',
|
|
'acos',
|
|
'acosf',
|
|
'asin',
|
|
'asinf',
|
|
'asprintf',
|
|
'atan',
|
|
'atan2',
|
|
'atan2f',
|
|
'atanf',
|
|
'atof',
|
|
'atoi',
|
|
'bsearch',
|
|
'calloc',
|
|
'ceil',
|
|
'ceilf',
|
|
'copysign',
|
|
'copysignf',
|
|
'cos',
|
|
'cosf',
|
|
'crc32',
|
|
'exp',
|
|
'expf',
|
|
'fabs',
|
|
'fabsf',
|
|
'floor',
|
|
'floorf',
|
|
'fmod',
|
|
'fmodf',
|
|
'free',
|
|
'getenv',
|
|
'isalnum',
|
|
'isalpha',
|
|
'isblank',
|
|
'iscntrl',
|
|
'isdigit',
|
|
'isgraph',
|
|
'islower',
|
|
'isprint',
|
|
'ispunct',
|
|
'isspace',
|
|
'isupper',
|
|
'isxdigit',
|
|
'itoa',
|
|
'lltoa',
|
|
'log10',
|
|
'log10f',
|
|
'logf',
|
|
'lround',
|
|
'lroundf',
|
|
'ltoa',
|
|
'malloc',
|
|
'memalign',
|
|
'memcmp',
|
|
'memcpy',
|
|
'memcpy4',
|
|
'memmove',
|
|
'memset',
|
|
'pow',
|
|
'powf',
|
|
'qsort',
|
|
'qsort_r',
|
|
'qsort_s',
|
|
'realloc',
|
|
'round',
|
|
'roundf',
|
|
'scalbn',
|
|
'scalbnf',
|
|
'setenv',
|
|
'sin',
|
|
'sinf',
|
|
'snprintf',
|
|
'sqrt',
|
|
'sqrtf',
|
|
'sscanf',
|
|
'strcasecmp',
|
|
'strchr',
|
|
'strcmp',
|
|
'strdup',
|
|
'strlcat',
|
|
'strlcpy',
|
|
'strlen',
|
|
'strlwr',
|
|
'strncasecmp',
|
|
'strncmp',
|
|
'strrchr',
|
|
'strrev',
|
|
'strstr',
|
|
'strtod',
|
|
'strtokr',
|
|
'strtol',
|
|
'strtoll',
|
|
'strtoul',
|
|
'strupr',
|
|
'tan',
|
|
'tanf',
|
|
'tolower',
|
|
'toupper',
|
|
'trunc',
|
|
'truncf',
|
|
'uitoa',
|
|
'ulltoa',
|
|
'ultoa',
|
|
'utf8strlcpy',
|
|
'utf8strlen',
|
|
'vasprintf',
|
|
'vsnprintf',
|
|
'vsscanf',
|
|
'wcscasecmp',
|
|
'wcscmp',
|
|
'wcsdup',
|
|
'wcslcat',
|
|
'wcslcpy',
|
|
'wcslen',
|
|
'wcsncasecmp',
|
|
'wcsncmp',
|
|
'wcsstr' ]
|
|
|
|
|
|
reg_comment_remove_content = re.compile('\/\*.*\*/')
|
|
reg_comment_remove_content2 = re.compile('".*"')
|
|
reg_comment_remove_content3 = re.compile(':strlen')
|
|
reg_comment_remove_content4 = re.compile('->free')
|
|
|
|
def find_symbols_in_file(file, regex):
|
|
|
|
allowed_extensions = [ ".c", ".cpp", ".m", ".h", ".hpp", ".cc" ]
|
|
|
|
excluded_paths = [
|
|
"src/stdlib",
|
|
"src/libm",
|
|
"src/hidapi",
|
|
"src/video/khronos",
|
|
"include/SDL3",
|
|
"build-scripts/gen_audio_resampler_filter.c",
|
|
"build-scripts/gen_audio_channel_conversion.c" ]
|
|
|
|
filename = pathlib.Path(file)
|
|
|
|
for ep in excluded_paths:
|
|
if ep in filename.as_posix():
|
|
# skip
|
|
return
|
|
|
|
if filename.suffix not in allowed_extensions:
|
|
# skip
|
|
return
|
|
|
|
# print("Parse %s" % file)
|
|
|
|
try:
|
|
with file.open("r", encoding="UTF-8", newline="") as rfp:
|
|
parsing_comment = False
|
|
for l in rfp:
|
|
l = l.strip()
|
|
|
|
# Get the comment block /* ... */ across several lines
|
|
match_start = "/*" in l
|
|
match_end = "*/" in l
|
|
if match_start and match_end:
|
|
continue
|
|
if match_start:
|
|
parsing_comment = True
|
|
continue
|
|
if match_end:
|
|
parsing_comment = False
|
|
continue
|
|
if parsing_comment:
|
|
continue
|
|
|
|
if regex.match(l):
|
|
|
|
# free() allowed here
|
|
if "This should NOT be SDL_" in l:
|
|
continue
|
|
|
|
# double check
|
|
# Remove one line comment /* ... */
|
|
# eg: extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path, int bExclusive /* = false */);
|
|
l = reg_comment_remove_content.sub('', l)
|
|
|
|
# Remove strings " ... "
|
|
l = reg_comment_remove_content2.sub('', l)
|
|
|
|
# :strlen
|
|
l = reg_comment_remove_content3.sub('', l)
|
|
|
|
# ->free
|
|
l = reg_comment_remove_content4.sub('', l)
|
|
|
|
if regex.match(l):
|
|
print("File %s" % filename)
|
|
print(" %s" % l)
|
|
print("")
|
|
|
|
except UnicodeDecodeError:
|
|
print("%s is not text, skipping" % file)
|
|
except Exception as err:
|
|
print("%s" % err)
|
|
|
|
def find_symbols_in_dir(path, regex):
|
|
|
|
for entry in path.glob("*"):
|
|
if entry.is_dir():
|
|
find_symbols_in_dir(entry, regex)
|
|
else:
|
|
find_symbols_in_file(entry, regex)
|
|
|
|
def main():
|
|
str = ".*\\b("
|
|
for w in words:
|
|
str += w + "|"
|
|
str = str[:-1]
|
|
str += ")\("
|
|
regex = re.compile(str)
|
|
find_symbols_in_dir(SDL_ROOT, regex)
|
|
|
|
if __name__ == "__main__":
|
|
|
|
parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
|
|
args = parser.parse_args()
|
|
|
|
try:
|
|
main()
|
|
except Exception as e:
|
|
print(e)
|
|
exit(-1)
|
|
|
|
exit(0)
|
|
|
|
|