10f6c4d8bSMichael Flanders# ====- Information about standard headers used by docgen ----*- python -*--==# 20f6c4d8bSMichael Flanders# 30f6c4d8bSMichael Flanders# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40f6c4d8bSMichael Flanders# See https://llvm.org/LICENSE.txt for license information. 50f6c4d8bSMichael Flanders# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60f6c4d8bSMichael Flanders# 70f6c4d8bSMichael Flanders# ==-------------------------------------------------------------------------==# 80f6c4d8bSMichael Flandersfrom pathlib import Path 90f6c4d8bSMichael Flandersfrom typing import Generator 100f6c4d8bSMichael Flanders 110f6c4d8bSMichael Flanders 120f6c4d8bSMichael Flandersclass Header: 130f6c4d8bSMichael Flanders """ 140f6c4d8bSMichael Flanders Maintains implementation information about a standard header file: 150f6c4d8bSMichael Flanders * where does its implementation dir live 160f6c4d8bSMichael Flanders * where is its macros file 17*88bcf728SNick Desaulniers * where is its docgen yaml file 180f6c4d8bSMichael Flanders 190f6c4d8bSMichael Flanders By convention, the macro-only part of a header file is in a header-specific 200f6c4d8bSMichael Flanders file somewhere in the directory tree with root at 210f6c4d8bSMichael Flanders ``$LLVM_PROJECT_ROOT/libc/include/llvm-libc-macros``. Docgen expects that 220f6c4d8bSMichael Flanders if a macro is implemented, that it appears in a string 230f6c4d8bSMichael Flanders ``#define MACRO_NAME`` in some ``*-macros.h`` file in the directory tree. 240f6c4d8bSMichael Flanders Docgen searches for this string in the file to set the implementation status 250f6c4d8bSMichael Flanders shown in the generated rst docs rendered as html for display at 260f6c4d8bSMichael Flanders <libc.llvm.org>. 270f6c4d8bSMichael Flanders 280f6c4d8bSMichael Flanders By convention, each function for a header is implemented in a function-specific 290f6c4d8bSMichael Flanders cpp file somewhere in the directory tree with root at, e.g, 300f6c4d8bSMichael Flanders ``$LLVM_PROJECT_ROOT/libc/src/fenv``. Some headers have architecture-specific 310f6c4d8bSMichael Flanders implementations, like ``math``, and some don't, like ``fenv``. Docgen uses the 320f6c4d8bSMichael Flanders presence of this function-specific cpp file to set the implementation status 330f6c4d8bSMichael Flanders shown in the generated rst docs rendered as html for display at 340f6c4d8bSMichael Flanders <libc.llvm.org>. 350f6c4d8bSMichael Flanders """ 360f6c4d8bSMichael Flanders 370f6c4d8bSMichael Flanders def __init__(self, header_name: str): 380f6c4d8bSMichael Flanders """ 390f6c4d8bSMichael Flanders :param header_name: e.g., ``"threads.h"`` or ``"signal.h"`` 400f6c4d8bSMichael Flanders """ 410f6c4d8bSMichael Flanders self.name = header_name 420f6c4d8bSMichael Flanders self.stem = header_name.rstrip(".h") 430f6c4d8bSMichael Flanders self.docgen_root = Path(__file__).parent 440f6c4d8bSMichael Flanders self.libc_root = self.docgen_root.parent.parent 45*88bcf728SNick Desaulniers self.docgen_yaml = self.docgen_root / Path(header_name).with_suffix(".yaml") 460f6c4d8bSMichael Flanders self.fns_dir = Path(self.libc_root, "src", self.stem) 470f6c4d8bSMichael Flanders self.macros_dir = Path(self.libc_root, "include", "llvm-libc-macros") 480f6c4d8bSMichael Flanders 490f6c4d8bSMichael Flanders def macro_file_exists(self) -> bool: 500f6c4d8bSMichael Flanders for _ in self.__get_macro_files(): 510f6c4d8bSMichael Flanders return True 520f6c4d8bSMichael Flanders 530f6c4d8bSMichael Flanders return False 540f6c4d8bSMichael Flanders 550f6c4d8bSMichael Flanders def fns_dir_exists(self) -> bool: 560f6c4d8bSMichael Flanders return self.fns_dir.exists() and self.fns_dir.is_dir() 570f6c4d8bSMichael Flanders 580f6c4d8bSMichael Flanders def implements_fn(self, fn_name: str) -> bool: 590f6c4d8bSMichael Flanders for _ in self.fns_dir.glob(f"**/{fn_name}.cpp"): 600f6c4d8bSMichael Flanders return True 610f6c4d8bSMichael Flanders 620f6c4d8bSMichael Flanders return False 630f6c4d8bSMichael Flanders 640f6c4d8bSMichael Flanders def implements_macro(self, m_name: str) -> bool: 650f6c4d8bSMichael Flanders """ 660f6c4d8bSMichael Flanders Some macro files are in, e.g., 670f6c4d8bSMichael Flanders ``$LLVM_PROJECT_ROOT/libc/include/llvm-libc-macros/fenv-macros.h``, 680f6c4d8bSMichael Flanders but others are in subdirectories, e.g., ``signal.h`` has the macro 690f6c4d8bSMichael Flanders definitions in 700f6c4d8bSMichael Flanders ``$LLVM_PROJECT_ROOT/libc/include/llvm-libc-macros/linux/signal-macros.h``. 710f6c4d8bSMichael Flanders 720f6c4d8bSMichael Flanders :param m_name: name of macro, e.g., ``FE_ALL_EXCEPT`` 730f6c4d8bSMichael Flanders """ 740f6c4d8bSMichael Flanders for f in self.__get_macro_files(): 750f6c4d8bSMichael Flanders if f"#define {m_name}" in f.read_text(): 760f6c4d8bSMichael Flanders return True 770f6c4d8bSMichael Flanders 780f6c4d8bSMichael Flanders return False 790f6c4d8bSMichael Flanders 800f6c4d8bSMichael Flanders def __get_macro_files(self) -> Generator[Path, None, None]: 810f6c4d8bSMichael Flanders """ 820f6c4d8bSMichael Flanders This function uses a glob on, e.g., ``"**/fcntl.macros.h"`` because the 830f6c4d8bSMichael Flanders macro file might be located in a subdirectory: 840f6c4d8bSMichael Flanders libc/include/llvm-libc-macros/fcntl-macros.h 850f6c4d8bSMichael Flanders libc/include/llvm-libc-macros/linux/fcntl-macros.h 86e17d2b58SNick Desaulniers 87e17d2b58SNick Desaulniers When a header would be nested in a dir (such as arpa/, sys/, etc) we 88e17d2b58SNick Desaulniers instead use a hyphen in the name. 89e17d2b58SNick Desaulniers libc/include/llvm-libc-macros/sys-mman-macros.h 900f6c4d8bSMichael Flanders """ 91e17d2b58SNick Desaulniers stem = self.stem.replace("/", "-") 92e17d2b58SNick Desaulniers return self.macros_dir.glob(f"**/{stem}-macros.h") 93