Script to detect use of stdlib function
parent
937f5d0059
commit
70ccf34587
|
@ -0,0 +1,259 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Simple DirectMedia Layer
|
||||
# Copyright (C) 1997-2023 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',
|
||||
'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',
|
||||
'memcmp',
|
||||
'memcpy',
|
||||
'memcpy4',
|
||||
'memmove',
|
||||
'memset',
|
||||
'pow',
|
||||
'powf',
|
||||
'qsort',
|
||||
'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_free" 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)
|
||||
|
||||
|
Loading…
Reference in New Issue