Files
libretiny/docs/scripts/write_apis.py
2023-06-22 18:30:14 +02:00

126 lines
3.9 KiB
Python

# Copyright (c) Kuba Szczodrzyński 2023-06-22.
import re
from glob import glob
from os.path import dirname, join
import colorama
from colorama import Fore, Style
from markdown import Markdown
if __name__ == "__main__":
colorama.init()
api_path = join(dirname(__file__), "..", "..", "cores/common/base/api/lt_*.*")
out_path = join(dirname(__file__), "..", "contrib")
declaration = ""
implementation = ""
for file in glob(api_path):
with open(file, "r") as f:
data = f.read()
if file.endswith(".h"):
declaration += data
elif file.endswith(".c"):
implementation += data
block_comment_regex = r"\/\*[\d\D]+?\*\/"
line_comment_regex = r"\/\/.+?$"
macro_regex = r"#(?:[^\n\\]|\\\n)+$"
line_regex = r"\n+"
declaration = re.sub(block_comment_regex, "", declaration)
declaration = re.sub(line_comment_regex, "", declaration, flags=re.MULTILINE)
declaration = re.sub(macro_regex, "", declaration, flags=re.MULTILINE)
declaration = re.sub(line_regex, "\n", declaration)
implementation = re.sub(block_comment_regex, "", implementation)
implementation = re.sub(line_comment_regex, "", implementation, flags=re.MULTILINE)
implementation = re.sub(macro_regex, "", implementation, flags=re.MULTILINE)
implementation = re.sub(line_regex, "\n", implementation)
declaration_regex = r"^([\d\w\s]+ \*?)([\S]+?)\(.*?\);$"
implementation_regex = r"^(__attribute__\(\(weak\)\) )?([\w\d* ]+?)([\w\d]+)\(.+?{"
function_types = {}
decl_functions = set()
impl_functions = set()
weak_functions = set()
for match in re.finditer(
pattern=declaration_regex,
string=declaration,
flags=re.DOTALL | re.MULTILINE,
):
function_type = match[1].strip()
function_name = match[2].strip()
if function_types.get(function_name, function_type) != function_type:
print(
Fore.YELLOW
+ "WARNING: Wrong return type: "
+ f"'{function_types[function_name]} {function_name}'"
+ f"vs '{function_type} {function_name}'"
+ Style.RESET_ALL
)
function_types[function_name] = function_type
decl_functions.add(function_name)
for match in re.finditer(
pattern=implementation_regex,
string=implementation,
flags=re.DOTALL | re.MULTILINE,
):
is_weak = match[1]
function_type = match[2].strip()
function_name = match[3].strip()
function_types[function_name] = function_type
if function_types.get(function_name, function_type) != function_type:
print(
Fore.YELLOW
+ "WARNING: Wrong return type: "
+ f"'{function_types[function_name]} {function_name}'"
+ f"vs '{function_type} {function_name}'"
+ Style.RESET_ALL
)
if is_weak:
weak_functions.add(function_name)
else:
impl_functions.add(function_name)
common_functions = impl_functions.union(weak_functions)
family_functions = decl_functions - common_functions
undecl_functions = common_functions - decl_functions
if undecl_functions:
print(Fore.RED + "ERROR: Undeclared functions: " + ", ".join(undecl_functions))
exit(1)
md = Markdown(out_path, "lt-api-functions")
header = [
"Type",
"Function",
"Common",
"Weak",
"Family",
]
rows = []
for function in (
sorted(family_functions) + sorted(weak_functions) + sorted(impl_functions)
):
rows.append(
[
f"`{function_types[function]}`",
f"{function}()",
"✔️" if function in impl_functions else "",
"✔️" if function in weak_functions else "",
"✔️" if function not in common_functions else "",
]
)
md.add_table(header, *rows)
md.write()