#!/usr/bin/env python3 # # Simple DirectMedia Layer # Copyright (C) 1997-2024 Sam Lantinga # # 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 SDL_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)