123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- #!/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 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)
|