mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-28 23:49:12 +00:00
ci: Fix check_stdlib_usage.py and run on ci
This commit is contained in:
parent
76f28ea120
commit
80cf3f7c38
2 changed files with 66 additions and 71 deletions
1
.github/workflows/generic.yml
vendored
1
.github/workflows/generic.yml
vendored
|
@ -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') }}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue