ci: Fix check_stdlib_usage.py and run on ci

This commit is contained in:
Anonymous Maarten 2024-09-25 21:18:37 +02:00 committed by Anonymous Maarten
parent 76f28ea120
commit 80cf3f7c38
2 changed files with 66 additions and 71 deletions

View file

@ -358,6 +358,7 @@ jobs:
set -e set -e
build-scripts/test-versioning.sh build-scripts/test-versioning.sh
python build-scripts/check_android_jni.py python build-scripts/check_android_jni.py
python build-scripts/check_stdlib_usage.py
- name: 'Upload binary package' - name: 'Upload binary package'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
if: ${{ always() && matrix.platform.artifact != '' && (steps.package.outcome == 'success' || steps.cpactions.outcome == 'success') && (matrix.platform.enable-artifacts || steps.tests.outcome == 'failure') }} if: ${{ always() && matrix.platform.artifact != '' && (steps.package.outcome == 'success' || steps.cpactions.outcome == 'success') && (matrix.platform.enable-artifacts || steps.tests.outcome == 'failure') }}

View file

@ -29,7 +29,7 @@ import sys
SDL_ROOT = pathlib.Path(__file__).resolve().parents[1] SDL_ROOT = pathlib.Path(__file__).resolve().parents[1]
words = [ STDLIB_SYMBOLS = [
'abs', 'abs',
'acos', 'acos',
'acosf', 'acosf',
@ -146,15 +146,13 @@ words = [
'wcslen', 'wcslen',
'wcsncasecmp', 'wcsncasecmp',
'wcsncmp', 'wcsncmp',
'wcsstr' ] 'wcsstr',
]
RE_STDLIB_SYMBOL = re.compile(rf"\b(?P<symbol>{'|'.join(STDLIB_SYMBOLS)})\b\(")
reg_comment_remove_content = re.compile(r'\/\*.*\*/') def find_symbols_in_file(file: pathlib.Path) -> int:
reg_comment_remove_content2 = re.compile('".*"') match_count = 0
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" ] allowed_extensions = [ ".c", ".cpp", ".m", ".h", ".hpp", ".cc" ]
@ -174,94 +172,90 @@ def find_symbols_in_file(file, regex):
for ep in excluded_paths: for ep in excluded_paths:
if ep in filename.as_posix(): if ep in filename.as_posix():
# skip # skip
return return 0
if filename.suffix not in allowed_extensions: if filename.suffix not in allowed_extensions:
# skip # skip
return return 0
# print("Parse %s" % file) # print("Parse %s" % file)
try: try:
with file.open("r", encoding="UTF-8", newline="") as rfp: with file.open("r", encoding="UTF-8", newline="") as rfp:
parsing_comment = False parsing_comment = False
for l in rfp: for line_i, original_line in enumerate(rfp, start=1):
l = l.strip() line = original_line.strip()
line_comment = ""
# Get the comment block /* ... */ across several lines # Get the comment block /* ... */ across several lines
match_start = "/*" in l while True:
match_end = "*/" in l if parsing_comment:
if match_start and match_end: pos_end_comment = line.find("*/")
continue if pos_end_comment >= 0:
if match_start: line = line[pos_end_comment+2:]
parsing_comment = True parsing_comment = False
continue else:
if match_end: break
parsing_comment = False else:
continue pos_start_comment = line.find("/*")
if pos_start_comment >= 0:
pos_end_comment = line.find("*/", pos_start_comment+2)
if pos_end_comment >= 0:
line_comment += line[pos_start_comment:pos_end_comment+2]
line = line[:pos_start_comment] + line[pos_end_comment+2:]
else:
line_comment += line[pos_start_comment:]
line = line[:pos_start_comment]
parsing_comment = True
break
else:
break
if parsing_comment: if parsing_comment:
continue continue
if "//" in l: pos_line_comment = line.find("//")
l = l[:l.find("//")] if pos_line_comment >= 0:
line_comment += line[pos_line_comment:]
line = line[:pos_line_comment]
if regex.match(l): if m := RE_STDLIB_SYMBOL.match(line):
override_string = f"This should NOT be SDL_{m['symbol']}()"
# free() allowed here if override_string not in line_comment:
if "This should NOT be SDL_" in l: print(f"{filename}:{line_i}")
continue print(f" {line}")
print(f"")
# double check match_count += 1
# 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: except UnicodeDecodeError:
print("%s is not text, skipping" % file) print(f"{file} is not text, skipping", file=sys.stderr)
except Exception as err:
print("%s" % err)
def find_symbols_in_dir(path, regex): return match_count
def find_symbols_in_dir(path: pathlib.Path) -> int:
match_count = 0
for entry in path.glob("*"): for entry in path.glob("*"):
if entry.is_dir(): if entry.is_dir():
find_symbols_in_dir(entry, regex) match_count += find_symbols_in_dir(entry)
else: else:
find_symbols_in_file(entry, regex) match_count += find_symbols_in_file(entry)
return match_count
def main(): def main():
str = ".*\\b(" parser = argparse.ArgumentParser(fromfile_prefix_chars="@")
for w in words: parser.add_argument("path", default=SDL_ROOT, nargs="?", type=pathlib.Path, help="Path to look for stdlib symbols")
str += w + "|"
str = str[:-1]
str += r")\("
regex = re.compile(str)
find_symbols_in_dir(SDL_ROOT, regex)
if __name__ == "__main__":
parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
args = parser.parse_args() args = parser.parse_args()
try: print(f"Looking for stdlib usage in {args.path}...")
main()
except Exception as e:
print(e)
exit(-1)
exit(0) match_count = find_symbols_in_dir(args.path)
if match_count:
print("If the stdlib usage is intentional, add a '// This should NOT be SDL_<symbol>()' line comment.")
print("")
print("NOT OK")
else:
print("OK")
return 1 if match_count else 0
if __name__ == "__main__":
raise SystemExit(main())