blob: 8755ebf8da9da6799ea38098775a2f698bea6827 [file] [log] [blame]
#!/usr/bin/env vpython3
# Copyright 2025 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Checks files in Zephyr code for references to EC symbols."""
from pathlib import Path
import re
import sys
from typing import Dict, List, Optional
import preupload.lib
EC_FUNCTIONS: Dict[str, str] = {
"clock": "k_uptime_get_32",
"crec_msleep": "k_msleep",
"crec_sleep": "k_sleep(K_SECONDS(sec))",
"crec_usleep": "k_usleep",
"force_time": "",
"time_after": "",
"time_until": "",
"udelay": "k_busy_wait",
"sec_to_date": "gmtime_r",
"date_to_sec": "timeutil_timegm or timeutil_timegm64",
}
EC_MACROS: Dict[str, str] = {
"MSEC": "USEC_PER_MSEC",
"SECOND": "USEC_PER_SEC",
"SEC_UL": "USEC_PER_SEC",
"MINUTE": "USEC_PER_SEC * SEC_PER_MIN",
"HOUR": "USEC_PER_SEC * SEC_PER_HOUR",
}
EC_FUNCTION_REGEXES: Dict[str, re.Pattern] = {
func: re.compile(rf"\b{func}\b\(") for func in EC_FUNCTIONS
}
EC_MACRO_REGEXES: Dict[str, re.Pattern] = {
macro: re.compile(rf"\b{macro}\b") for macro in EC_MACROS
}
# Skip checking lines that have // NOLINT_EC_SYMBOL or /* NOLINT_EC_SYMBOL */ comments.
NOLINT_REGEX = re.compile(r"//.*NOLINT_EC_SYMBOL.*|/\*.*NOLINT_EC_SYMBOL.*\*/")
ZEPHYR_PATH = Path("zephyr")
def main(argv: Optional[List[str]] = None) -> Optional[int]:
"""Look at all the zephyr files in passed in on the commandline for EC symbols."""
return_code = 0
args = preupload.lib.parse_args(argv)
for filename in args.filename:
try:
filename.relative_to(ZEPHYR_PATH)
except ValueError:
# Not a subdirectory of ZEPHYR_PATH.
continue
if not filename.is_file():
continue
if not (
filename.suffix
in [
".c",
".h",
".cc",
".inc",
]
):
continue
lines = preupload.lib.cat_file(args, filename).splitlines()
for linenum, line in enumerate(lines, start=1):
if NOLINT_REGEX.search(line):
continue
for func, replacement in EC_FUNCTIONS.items():
if EC_FUNCTION_REGEXES[func].search(line):
message = (
f"Function '{func}' should not be used in Zephyr code."
)
if replacement:
message += f" Use '{replacement}'."
print(
f"error: {message}\n" f"{filename}:{linenum}: {line}",
file=sys.stderr,
)
return_code = 1
for macro, replacement in EC_MACROS.items():
if EC_MACRO_REGEXES[macro].search(line):
message = (
f"Macro '{macro}' should not be used in Zephyr code."
)
if replacement:
message += f" Use '{replacement}'."
print(
f"error: {message}\n" f"{filename}:{linenum}: {line}",
file=sys.stderr,
)
return_code = 1
return return_code
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))