Closes #88066. Compared to before, the function names in the stdbit table are sorted by function name, not order-of-appearance in the standard. Since macros aren't printed by docgen.py and are still a TODO in the code, they are also not printed in the new stdbit.h docs. Adds some checks to docgen.py for conditions that tripped me up. Add code to docgen.py to add the include of the `|check|` rewriter, since all other generated files need it.
94 lines
2.6 KiB
Python
Executable File
94 lines
2.6 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# ====- Generate documentation for libc functions ------------*- python -*--==#
|
|
#
|
|
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
# See https://llvm.org/LICENSE.txt for license information.
|
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
#
|
|
# ==-------------------------------------------------------------------------==#
|
|
from argparse import ArgumentParser, Namespace
|
|
from pathlib import Path
|
|
from typing import Dict
|
|
import sys
|
|
import json
|
|
|
|
|
|
def load_api(hname: str) -> Dict:
|
|
p = Path(__file__).parent / Path(hname).with_suffix(".json")
|
|
api = p.read_text(encoding="utf-8")
|
|
return json.loads(api)
|
|
|
|
|
|
# TODO: we may need to get more sophisticated for less generic implementations.
|
|
# Does libc/src/{hname minus .h suffix}/{fname}.cpp exist?
|
|
def is_implemented(hname: str, fname: str) -> bool:
|
|
path = Path(
|
|
Path(__file__).parent.parent.parent,
|
|
"src",
|
|
hname.rstrip(".h")
|
|
)
|
|
|
|
if not path.exists():
|
|
raise FileNotFoundError(f"implementation dir does not exist: {path}")
|
|
|
|
if not path.is_dir():
|
|
raise NotADirectoryError(f"implementation dir is not a dir: {path}")
|
|
|
|
# Recursively search for the target source file in the subdirectories under
|
|
# libc/src/{hname}.
|
|
for _ in path.glob("**/" + fname + ".cpp"):
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def print_functions(header: str, functions: Dict):
|
|
for key in sorted(functions.keys()):
|
|
print(f" * - {key}")
|
|
|
|
if is_implemented(header, key):
|
|
print(" - |check|")
|
|
else:
|
|
print(" -")
|
|
|
|
# defined is optional. Having any content is optional.
|
|
if functions[key] is not None and "defined" in functions[key]:
|
|
print(f' - {functions[key]["defined"]}')
|
|
else:
|
|
print(" -")
|
|
|
|
|
|
def print_header(header: str, api: Dict):
|
|
print(".. include:: check.rst\n")
|
|
fns = f"{header} Functions"
|
|
print(fns)
|
|
print("=" * (len(fns)))
|
|
print(
|
|
f"""
|
|
.. list-table::
|
|
:widths: auto
|
|
:align: center
|
|
:header-rows: 1
|
|
|
|
* - Function
|
|
- Implemented
|
|
- Standard"""
|
|
)
|
|
# TODO: how do we want to signal implementation of macros?
|
|
print_functions(header, api["functions"])
|
|
|
|
|
|
def parse_args() -> Namespace:
|
|
parser = ArgumentParser()
|
|
choices = [p.with_suffix(".h").name for p in Path(__file__).parent.glob("*.json")]
|
|
parser.add_argument("header_name", choices=choices)
|
|
return parser.parse_args()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
args = parse_args()
|
|
api = load_api(args.header_name)
|
|
|
|
print_header(args.header_name, api)
|