xref: /linux/scripts/lib/kdoc/kdoc_output.py (revision 3e443d167327b10966166c1953631936547b03d0)
11d6fea64SMauro Carvalho Chehab#!/usr/bin/env python3
21d6fea64SMauro Carvalho Chehab# SPDX-License-Identifier: GPL-2.0
31d6fea64SMauro Carvalho Chehab# Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>.
41d6fea64SMauro Carvalho Chehab#
5485f6f79SMauro Carvalho Chehab# pylint: disable=C0301,R0902,R0911,R0912,R0913,R0914,R0915,R0917
61d6fea64SMauro Carvalho Chehab
71d6fea64SMauro Carvalho Chehab"""
81d6fea64SMauro Carvalho ChehabImplement output filters to print kernel-doc documentation.
91d6fea64SMauro Carvalho Chehab
101d6fea64SMauro Carvalho ChehabThe implementation uses a virtual base class (OutputFormat) which
111d6fea64SMauro Carvalho Chehabcontains a dispatches to virtual methods, and some code to filter
121d6fea64SMauro Carvalho Chehabout output messages.
131d6fea64SMauro Carvalho Chehab
141d6fea64SMauro Carvalho ChehabThe actual implementation is done on one separate class per each type
151d6fea64SMauro Carvalho Chehabof output. Currently, there are output classes for ReST and man/troff.
161d6fea64SMauro Carvalho Chehab"""
171d6fea64SMauro Carvalho Chehab
181d6fea64SMauro Carvalho Chehabimport os
191d6fea64SMauro Carvalho Chehabimport re
201d6fea64SMauro Carvalho Chehabfrom datetime import datetime
211d6fea64SMauro Carvalho Chehab
221d6fea64SMauro Carvalho Chehabfrom kdoc_parser import KernelDoc, type_param
23*04a383ceSMauro Carvalho Chehabfrom kdoc_re import KernRe
241d6fea64SMauro Carvalho Chehab
251d6fea64SMauro Carvalho Chehab
26*04a383ceSMauro Carvalho Chehabfunction_pointer = KernRe(r"([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)", cache=False)
271d6fea64SMauro Carvalho Chehab
281d6fea64SMauro Carvalho Chehab# match expressions used to find embedded type information
29*04a383ceSMauro Carvalho Chehabtype_constant = KernRe(r"\b``([^\`]+)``\b", cache=False)
30*04a383ceSMauro Carvalho Chehabtype_constant2 = KernRe(r"\%([-_*\w]+)", cache=False)
31*04a383ceSMauro Carvalho Chehabtype_func = KernRe(r"(\w+)\(\)", cache=False)
32*04a383ceSMauro Carvalho Chehabtype_param_ref = KernRe(r"([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
331d6fea64SMauro Carvalho Chehab
341d6fea64SMauro Carvalho Chehab# Special RST handling for func ptr params
35*04a383ceSMauro Carvalho Chehabtype_fp_param = KernRe(r"\@(\w+)\(\)", cache=False)
361d6fea64SMauro Carvalho Chehab
371d6fea64SMauro Carvalho Chehab# Special RST handling for structs with func ptr params
38*04a383ceSMauro Carvalho Chehabtype_fp_param2 = KernRe(r"\@(\w+->\S+)\(\)", cache=False)
391d6fea64SMauro Carvalho Chehab
40*04a383ceSMauro Carvalho Chehabtype_env = KernRe(r"(\$\w+)", cache=False)
41*04a383ceSMauro Carvalho Chehabtype_enum = KernRe(r"\&(enum\s*([_\w]+))", cache=False)
42*04a383ceSMauro Carvalho Chehabtype_struct = KernRe(r"\&(struct\s*([_\w]+))", cache=False)
43*04a383ceSMauro Carvalho Chehabtype_typedef = KernRe(r"\&(typedef\s*([_\w]+))", cache=False)
44*04a383ceSMauro Carvalho Chehabtype_union = KernRe(r"\&(union\s*([_\w]+))", cache=False)
45*04a383ceSMauro Carvalho Chehabtype_member = KernRe(r"\&([_\w]+)(\.|->)([_\w]+)", cache=False)
46*04a383ceSMauro Carvalho Chehabtype_fallback = KernRe(r"\&([_\w]+)", cache=False)
47*04a383ceSMauro Carvalho Chehabtype_member_func = type_member + KernRe(r"\(\)", cache=False)
481d6fea64SMauro Carvalho Chehab
491d6fea64SMauro Carvalho Chehab
501d6fea64SMauro Carvalho Chehabclass OutputFormat:
51485f6f79SMauro Carvalho Chehab    """
52485f6f79SMauro Carvalho Chehab    Base class for OutputFormat. If used as-is, it means that only
53485f6f79SMauro Carvalho Chehab    warnings will be displayed.
54485f6f79SMauro Carvalho Chehab    """
55485f6f79SMauro Carvalho Chehab
561d6fea64SMauro Carvalho Chehab    # output mode.
571d6fea64SMauro Carvalho Chehab    OUTPUT_ALL          = 0 # output all symbols and doc sections
581d6fea64SMauro Carvalho Chehab    OUTPUT_INCLUDE      = 1 # output only specified symbols
591d6fea64SMauro Carvalho Chehab    OUTPUT_EXPORTED     = 2 # output exported symbols
601d6fea64SMauro Carvalho Chehab    OUTPUT_INTERNAL     = 3 # output non-exported symbols
611d6fea64SMauro Carvalho Chehab
621d6fea64SMauro Carvalho Chehab    # Virtual member to be overriden at the  inherited classes
631d6fea64SMauro Carvalho Chehab    highlights = []
641d6fea64SMauro Carvalho Chehab
651d6fea64SMauro Carvalho Chehab    def __init__(self):
661d6fea64SMauro Carvalho Chehab        """Declare internal vars and set mode to OUTPUT_ALL"""
671d6fea64SMauro Carvalho Chehab
681d6fea64SMauro Carvalho Chehab        self.out_mode = self.OUTPUT_ALL
691d6fea64SMauro Carvalho Chehab        self.enable_lineno = None
701d6fea64SMauro Carvalho Chehab        self.nosymbol = {}
711d6fea64SMauro Carvalho Chehab        self.symbol = None
7216740c29SMauro Carvalho Chehab        self.function_table = None
731d6fea64SMauro Carvalho Chehab        self.config = None
740873e554SMauro Carvalho Chehab        self.no_doc_sections = False
751d6fea64SMauro Carvalho Chehab
764fa5e411SMauro Carvalho Chehab        self.data = ""
774fa5e411SMauro Carvalho Chehab
781d6fea64SMauro Carvalho Chehab    def set_config(self, config):
79485f6f79SMauro Carvalho Chehab        """
80485f6f79SMauro Carvalho Chehab        Setup global config variables used by both parser and output.
81485f6f79SMauro Carvalho Chehab        """
82485f6f79SMauro Carvalho Chehab
831d6fea64SMauro Carvalho Chehab        self.config = config
841d6fea64SMauro Carvalho Chehab
851d6fea64SMauro Carvalho Chehab    def set_filter(self, export, internal, symbol, nosymbol, function_table,
860873e554SMauro Carvalho Chehab                   enable_lineno, no_doc_sections):
871d6fea64SMauro Carvalho Chehab        """
881d6fea64SMauro Carvalho Chehab        Initialize filter variables according with the requested mode.
891d6fea64SMauro Carvalho Chehab
901d6fea64SMauro Carvalho Chehab        Only one choice is valid between export, internal and symbol.
911d6fea64SMauro Carvalho Chehab
921d6fea64SMauro Carvalho Chehab        The nosymbol filter can be used on all modes.
931d6fea64SMauro Carvalho Chehab        """
941d6fea64SMauro Carvalho Chehab
951d6fea64SMauro Carvalho Chehab        self.enable_lineno = enable_lineno
960873e554SMauro Carvalho Chehab        self.no_doc_sections = no_doc_sections
9716740c29SMauro Carvalho Chehab        self.function_table = function_table
981d6fea64SMauro Carvalho Chehab
991d6fea64SMauro Carvalho Chehab        if symbol:
1001d6fea64SMauro Carvalho Chehab            self.out_mode = self.OUTPUT_INCLUDE
1011d6fea64SMauro Carvalho Chehab        elif export:
1021d6fea64SMauro Carvalho Chehab            self.out_mode = self.OUTPUT_EXPORTED
1031d6fea64SMauro Carvalho Chehab        elif internal:
1041d6fea64SMauro Carvalho Chehab            self.out_mode = self.OUTPUT_INTERNAL
1051d6fea64SMauro Carvalho Chehab        else:
1061d6fea64SMauro Carvalho Chehab            self.out_mode = self.OUTPUT_ALL
1071d6fea64SMauro Carvalho Chehab
1081d6fea64SMauro Carvalho Chehab        if nosymbol:
1091d6fea64SMauro Carvalho Chehab            self.nosymbol = set(nosymbol)
1101d6fea64SMauro Carvalho Chehab
1111d6fea64SMauro Carvalho Chehab
1121d6fea64SMauro Carvalho Chehab    def highlight_block(self, block):
1131d6fea64SMauro Carvalho Chehab        """
1141d6fea64SMauro Carvalho Chehab        Apply the RST highlights to a sub-block of text.
1151d6fea64SMauro Carvalho Chehab        """
1161d6fea64SMauro Carvalho Chehab
1171d6fea64SMauro Carvalho Chehab        for r, sub in self.highlights:
1181d6fea64SMauro Carvalho Chehab            block = r.sub(sub, block)
1191d6fea64SMauro Carvalho Chehab
1201d6fea64SMauro Carvalho Chehab        return block
1211d6fea64SMauro Carvalho Chehab
1229cbc2d3bSMauro Carvalho Chehab    def out_warnings(self, args):
123485f6f79SMauro Carvalho Chehab        """
124485f6f79SMauro Carvalho Chehab        Output warnings for identifiers that will be displayed.
125485f6f79SMauro Carvalho Chehab        """
126485f6f79SMauro Carvalho Chehab
1279cbc2d3bSMauro Carvalho Chehab        warnings = args.get('warnings', [])
1289cbc2d3bSMauro Carvalho Chehab
12911afeab6SMauro Carvalho Chehab        for log_msg in warnings:
13016740c29SMauro Carvalho Chehab            self.config.warning(log_msg)
1319cbc2d3bSMauro Carvalho Chehab
1329cbc2d3bSMauro Carvalho Chehab    def check_doc(self, name, args):
1331d6fea64SMauro Carvalho Chehab        """Check if DOC should be output"""
1341d6fea64SMauro Carvalho Chehab
1350873e554SMauro Carvalho Chehab        if self.no_doc_sections:
1360873e554SMauro Carvalho Chehab            return False
1370873e554SMauro Carvalho Chehab
138408269aeSMauro Carvalho Chehab        if name in self.nosymbol:
139408269aeSMauro Carvalho Chehab            return False
140408269aeSMauro Carvalho Chehab
1411d6fea64SMauro Carvalho Chehab        if self.out_mode == self.OUTPUT_ALL:
1429cbc2d3bSMauro Carvalho Chehab            self.out_warnings(args)
1431d6fea64SMauro Carvalho Chehab            return True
1441d6fea64SMauro Carvalho Chehab
1451d6fea64SMauro Carvalho Chehab        if self.out_mode == self.OUTPUT_INCLUDE:
1461d6fea64SMauro Carvalho Chehab            if name in self.function_table:
1479cbc2d3bSMauro Carvalho Chehab                self.out_warnings(args)
1481d6fea64SMauro Carvalho Chehab                return True
1491d6fea64SMauro Carvalho Chehab
1501d6fea64SMauro Carvalho Chehab        return False
1511d6fea64SMauro Carvalho Chehab
1529cbc2d3bSMauro Carvalho Chehab    def check_declaration(self, dtype, name, args):
153485f6f79SMauro Carvalho Chehab        """
154485f6f79SMauro Carvalho Chehab        Checks if a declaration should be output or not based on the
155485f6f79SMauro Carvalho Chehab        filtering criteria.
156485f6f79SMauro Carvalho Chehab        """
157485f6f79SMauro Carvalho Chehab
1581d6fea64SMauro Carvalho Chehab        if name in self.nosymbol:
1591d6fea64SMauro Carvalho Chehab            return False
1601d6fea64SMauro Carvalho Chehab
1611d6fea64SMauro Carvalho Chehab        if self.out_mode == self.OUTPUT_ALL:
1629cbc2d3bSMauro Carvalho Chehab            self.out_warnings(args)
1631d6fea64SMauro Carvalho Chehab            return True
1641d6fea64SMauro Carvalho Chehab
1651d6fea64SMauro Carvalho Chehab        if self.out_mode in [self.OUTPUT_INCLUDE, self.OUTPUT_EXPORTED]:
1661d6fea64SMauro Carvalho Chehab            if name in self.function_table:
1671d6fea64SMauro Carvalho Chehab                return True
1681d6fea64SMauro Carvalho Chehab
1691d6fea64SMauro Carvalho Chehab        if self.out_mode == self.OUTPUT_INTERNAL:
1701d6fea64SMauro Carvalho Chehab            if dtype != "function":
1719cbc2d3bSMauro Carvalho Chehab                self.out_warnings(args)
1721d6fea64SMauro Carvalho Chehab                return True
1731d6fea64SMauro Carvalho Chehab
1741d6fea64SMauro Carvalho Chehab            if name not in self.function_table:
1759cbc2d3bSMauro Carvalho Chehab                self.out_warnings(args)
1761d6fea64SMauro Carvalho Chehab                return True
1771d6fea64SMauro Carvalho Chehab
1781d6fea64SMauro Carvalho Chehab        return False
1791d6fea64SMauro Carvalho Chehab
1801d6fea64SMauro Carvalho Chehab    def msg(self, fname, name, args):
181485f6f79SMauro Carvalho Chehab        """
182485f6f79SMauro Carvalho Chehab        Handles a single entry from kernel-doc parser
183485f6f79SMauro Carvalho Chehab        """
184485f6f79SMauro Carvalho Chehab
1854fa5e411SMauro Carvalho Chehab        self.data = ""
1861d6fea64SMauro Carvalho Chehab
1871d6fea64SMauro Carvalho Chehab        dtype = args.get('type', "")
1881d6fea64SMauro Carvalho Chehab
1891d6fea64SMauro Carvalho Chehab        if dtype == "doc":
1901d6fea64SMauro Carvalho Chehab            self.out_doc(fname, name, args)
1914fa5e411SMauro Carvalho Chehab            return self.data
1921d6fea64SMauro Carvalho Chehab
1939cbc2d3bSMauro Carvalho Chehab        if not self.check_declaration(dtype, name, args):
1944fa5e411SMauro Carvalho Chehab            return self.data
1951d6fea64SMauro Carvalho Chehab
1961d6fea64SMauro Carvalho Chehab        if dtype == "function":
1971d6fea64SMauro Carvalho Chehab            self.out_function(fname, name, args)
1984fa5e411SMauro Carvalho Chehab            return self.data
1991d6fea64SMauro Carvalho Chehab
2001d6fea64SMauro Carvalho Chehab        if dtype == "enum":
2011d6fea64SMauro Carvalho Chehab            self.out_enum(fname, name, args)
2024fa5e411SMauro Carvalho Chehab            return self.data
2031d6fea64SMauro Carvalho Chehab
2041d6fea64SMauro Carvalho Chehab        if dtype == "typedef":
2051d6fea64SMauro Carvalho Chehab            self.out_typedef(fname, name, args)
2064fa5e411SMauro Carvalho Chehab            return self.data
2071d6fea64SMauro Carvalho Chehab
2081d6fea64SMauro Carvalho Chehab        if dtype in ["struct", "union"]:
2091d6fea64SMauro Carvalho Chehab            self.out_struct(fname, name, args)
2104fa5e411SMauro Carvalho Chehab            return self.data
2111d6fea64SMauro Carvalho Chehab
2121d6fea64SMauro Carvalho Chehab        # Warn if some type requires an output logic
2131d6fea64SMauro Carvalho Chehab        self.config.log.warning("doesn't now how to output '%s' block",
2141d6fea64SMauro Carvalho Chehab                                dtype)
2151d6fea64SMauro Carvalho Chehab
2164fa5e411SMauro Carvalho Chehab        return None
2171d6fea64SMauro Carvalho Chehab
2181d6fea64SMauro Carvalho Chehab    # Virtual methods to be overridden by inherited classes
219485f6f79SMauro Carvalho Chehab    # At the base class, those do nothing.
2201d6fea64SMauro Carvalho Chehab    def out_doc(self, fname, name, args):
221485f6f79SMauro Carvalho Chehab        """Outputs a DOC block"""
2221d6fea64SMauro Carvalho Chehab
2231d6fea64SMauro Carvalho Chehab    def out_function(self, fname, name, args):
224485f6f79SMauro Carvalho Chehab        """Outputs a function"""
2251d6fea64SMauro Carvalho Chehab
2261d6fea64SMauro Carvalho Chehab    def out_enum(self, fname, name, args):
227485f6f79SMauro Carvalho Chehab        """Outputs an enum"""
2281d6fea64SMauro Carvalho Chehab
2291d6fea64SMauro Carvalho Chehab    def out_typedef(self, fname, name, args):
230485f6f79SMauro Carvalho Chehab        """Outputs a typedef"""
2311d6fea64SMauro Carvalho Chehab
2321d6fea64SMauro Carvalho Chehab    def out_struct(self, fname, name, args):
233485f6f79SMauro Carvalho Chehab        """Outputs a struct"""
2341d6fea64SMauro Carvalho Chehab
2351d6fea64SMauro Carvalho Chehab
2361d6fea64SMauro Carvalho Chehabclass RestFormat(OutputFormat):
237485f6f79SMauro Carvalho Chehab    """Consts and functions used by ReST output"""
2381d6fea64SMauro Carvalho Chehab
2391d6fea64SMauro Carvalho Chehab    highlights = [
2401d6fea64SMauro Carvalho Chehab        (type_constant, r"``\1``"),
2411d6fea64SMauro Carvalho Chehab        (type_constant2, r"``\1``"),
2421d6fea64SMauro Carvalho Chehab
2431d6fea64SMauro Carvalho Chehab        # Note: need to escape () to avoid func matching later
2441d6fea64SMauro Carvalho Chehab        (type_member_func, r":c:type:`\1\2\3\\(\\) <\1>`"),
2451d6fea64SMauro Carvalho Chehab        (type_member, r":c:type:`\1\2\3 <\1>`"),
2461d6fea64SMauro Carvalho Chehab        (type_fp_param, r"**\1\\(\\)**"),
2471d6fea64SMauro Carvalho Chehab        (type_fp_param2, r"**\1\\(\\)**"),
2481d6fea64SMauro Carvalho Chehab        (type_func, r"\1()"),
2491d6fea64SMauro Carvalho Chehab        (type_enum, r":c:type:`\1 <\2>`"),
2501d6fea64SMauro Carvalho Chehab        (type_struct, r":c:type:`\1 <\2>`"),
2511d6fea64SMauro Carvalho Chehab        (type_typedef, r":c:type:`\1 <\2>`"),
2521d6fea64SMauro Carvalho Chehab        (type_union, r":c:type:`\1 <\2>`"),
2531d6fea64SMauro Carvalho Chehab
2541d6fea64SMauro Carvalho Chehab        # in rst this can refer to any type
2551d6fea64SMauro Carvalho Chehab        (type_fallback, r":c:type:`\1`"),
2561d6fea64SMauro Carvalho Chehab        (type_param_ref, r"**\1\2**")
2571d6fea64SMauro Carvalho Chehab    ]
2581d6fea64SMauro Carvalho Chehab    blankline = "\n"
2591d6fea64SMauro Carvalho Chehab
260*04a383ceSMauro Carvalho Chehab    sphinx_literal = KernRe(r'^[^.].*::$', cache=False)
261*04a383ceSMauro Carvalho Chehab    sphinx_cblock = KernRe(r'^\.\.\ +code-block::', cache=False)
2621d6fea64SMauro Carvalho Chehab
2631d6fea64SMauro Carvalho Chehab    def __init__(self):
2641d6fea64SMauro Carvalho Chehab        """
2651d6fea64SMauro Carvalho Chehab        Creates class variables.
2661d6fea64SMauro Carvalho Chehab
2671d6fea64SMauro Carvalho Chehab        Not really mandatory, but it is a good coding style and makes
2681d6fea64SMauro Carvalho Chehab        pylint happy.
2691d6fea64SMauro Carvalho Chehab        """
2701d6fea64SMauro Carvalho Chehab
2711d6fea64SMauro Carvalho Chehab        super().__init__()
2721d6fea64SMauro Carvalho Chehab        self.lineprefix = ""
2731d6fea64SMauro Carvalho Chehab
2741d6fea64SMauro Carvalho Chehab    def print_lineno(self, ln):
2751d6fea64SMauro Carvalho Chehab        """Outputs a line number"""
2761d6fea64SMauro Carvalho Chehab
277c3597ab2SMauro Carvalho Chehab        if self.enable_lineno and ln is not None:
278c3597ab2SMauro Carvalho Chehab            ln += 1
2794fa5e411SMauro Carvalho Chehab            self.data += f".. LINENO {ln}\n"
2801d6fea64SMauro Carvalho Chehab
2811d6fea64SMauro Carvalho Chehab    def output_highlight(self, args):
282485f6f79SMauro Carvalho Chehab        """
283485f6f79SMauro Carvalho Chehab        Outputs a C symbol that may require being converted to ReST using
284485f6f79SMauro Carvalho Chehab        the self.highlights variable
285485f6f79SMauro Carvalho Chehab        """
286485f6f79SMauro Carvalho Chehab
2871d6fea64SMauro Carvalho Chehab        input_text = args
2881d6fea64SMauro Carvalho Chehab        output = ""
2891d6fea64SMauro Carvalho Chehab        in_literal = False
2901d6fea64SMauro Carvalho Chehab        litprefix = ""
2911d6fea64SMauro Carvalho Chehab        block = ""
2921d6fea64SMauro Carvalho Chehab
2931d6fea64SMauro Carvalho Chehab        for line in input_text.strip("\n").split("\n"):
2941d6fea64SMauro Carvalho Chehab
2951d6fea64SMauro Carvalho Chehab            # If we're in a literal block, see if we should drop out of it.
2961d6fea64SMauro Carvalho Chehab            # Otherwise, pass the line straight through unmunged.
2971d6fea64SMauro Carvalho Chehab            if in_literal:
2981d6fea64SMauro Carvalho Chehab                if line.strip():  # If the line is not blank
2991d6fea64SMauro Carvalho Chehab                    # If this is the first non-blank line in a literal block,
3001d6fea64SMauro Carvalho Chehab                    # figure out the proper indent.
3011d6fea64SMauro Carvalho Chehab                    if not litprefix:
302*04a383ceSMauro Carvalho Chehab                        r = KernRe(r'^(\s*)')
3031d6fea64SMauro Carvalho Chehab                        if r.match(line):
3041d6fea64SMauro Carvalho Chehab                            litprefix = '^' + r.group(1)
3051d6fea64SMauro Carvalho Chehab                        else:
3061d6fea64SMauro Carvalho Chehab                            litprefix = ""
3071d6fea64SMauro Carvalho Chehab
3081d6fea64SMauro Carvalho Chehab                        output += line + "\n"
309*04a383ceSMauro Carvalho Chehab                    elif not KernRe(litprefix).match(line):
3101d6fea64SMauro Carvalho Chehab                        in_literal = False
3111d6fea64SMauro Carvalho Chehab                    else:
3121d6fea64SMauro Carvalho Chehab                        output += line + "\n"
3131d6fea64SMauro Carvalho Chehab                else:
3141d6fea64SMauro Carvalho Chehab                    output += line + "\n"
3151d6fea64SMauro Carvalho Chehab
3161d6fea64SMauro Carvalho Chehab            # Not in a literal block (or just dropped out)
3171d6fea64SMauro Carvalho Chehab            if not in_literal:
3181d6fea64SMauro Carvalho Chehab                block += line + "\n"
3191d6fea64SMauro Carvalho Chehab                if self.sphinx_literal.match(line) or self.sphinx_cblock.match(line):
3201d6fea64SMauro Carvalho Chehab                    in_literal = True
3211d6fea64SMauro Carvalho Chehab                    litprefix = ""
3221d6fea64SMauro Carvalho Chehab                    output += self.highlight_block(block)
3231d6fea64SMauro Carvalho Chehab                    block = ""
3241d6fea64SMauro Carvalho Chehab
3251d6fea64SMauro Carvalho Chehab        # Handle any remaining block
3261d6fea64SMauro Carvalho Chehab        if block:
3271d6fea64SMauro Carvalho Chehab            output += self.highlight_block(block)
3281d6fea64SMauro Carvalho Chehab
3291d6fea64SMauro Carvalho Chehab        # Print the output with the line prefix
3301d6fea64SMauro Carvalho Chehab        for line in output.strip("\n").split("\n"):
3314fa5e411SMauro Carvalho Chehab            self.data += self.lineprefix + line + "\n"
3321d6fea64SMauro Carvalho Chehab
333408269aeSMauro Carvalho Chehab    def out_section(self, args, out_docblock=False):
3341d6fea64SMauro Carvalho Chehab        """
3351d6fea64SMauro Carvalho Chehab        Outputs a block section.
3361d6fea64SMauro Carvalho Chehab
3371d6fea64SMauro Carvalho Chehab        This could use some work; it's used to output the DOC: sections, and
3381d6fea64SMauro Carvalho Chehab        starts by putting out the name of the doc section itself, but that
3391d6fea64SMauro Carvalho Chehab        tends to duplicate a header already in the template file.
3401d6fea64SMauro Carvalho Chehab        """
3411d6fea64SMauro Carvalho Chehab
3421d6fea64SMauro Carvalho Chehab        sectionlist = args.get('sectionlist', [])
3431d6fea64SMauro Carvalho Chehab        sections = args.get('sections', {})
3441d6fea64SMauro Carvalho Chehab        section_start_lines = args.get('section_start_lines', {})
3451d6fea64SMauro Carvalho Chehab
3461d6fea64SMauro Carvalho Chehab        for section in sectionlist:
3471d6fea64SMauro Carvalho Chehab            # Skip sections that are in the nosymbol_table
3481d6fea64SMauro Carvalho Chehab            if section in self.nosymbol:
3491d6fea64SMauro Carvalho Chehab                continue
3501d6fea64SMauro Carvalho Chehab
351408269aeSMauro Carvalho Chehab            if out_docblock:
3529235ec5eSMauro Carvalho Chehab                if not self.out_mode == self.OUTPUT_INCLUDE:
3534fa5e411SMauro Carvalho Chehab                    self.data += f".. _{section}:\n\n"
3549235ec5eSMauro Carvalho Chehab                    self.data += f'{self.lineprefix}**{section}**\n\n'
3559235ec5eSMauro Carvalho Chehab            else:
3564fa5e411SMauro Carvalho Chehab                self.data += f'{self.lineprefix}**{section}**\n\n'
3571d6fea64SMauro Carvalho Chehab
3581d6fea64SMauro Carvalho Chehab            self.print_lineno(section_start_lines.get(section, 0))
3591d6fea64SMauro Carvalho Chehab            self.output_highlight(sections[section])
3604fa5e411SMauro Carvalho Chehab            self.data += "\n"
3614fa5e411SMauro Carvalho Chehab        self.data += "\n"
3621d6fea64SMauro Carvalho Chehab
3631d6fea64SMauro Carvalho Chehab    def out_doc(self, fname, name, args):
3649cbc2d3bSMauro Carvalho Chehab        if not self.check_doc(name, args):
3651d6fea64SMauro Carvalho Chehab            return
366408269aeSMauro Carvalho Chehab        self.out_section(args, out_docblock=True)
3671d6fea64SMauro Carvalho Chehab
3681d6fea64SMauro Carvalho Chehab    def out_function(self, fname, name, args):
3691d6fea64SMauro Carvalho Chehab
3701d6fea64SMauro Carvalho Chehab        oldprefix = self.lineprefix
3711d6fea64SMauro Carvalho Chehab        signature = ""
3721d6fea64SMauro Carvalho Chehab
3731d6fea64SMauro Carvalho Chehab        func_macro = args.get('func_macro', False)
3741d6fea64SMauro Carvalho Chehab        if func_macro:
3751d6fea64SMauro Carvalho Chehab            signature = args['function']
3761d6fea64SMauro Carvalho Chehab        else:
3771d6fea64SMauro Carvalho Chehab            if args.get('functiontype'):
3781d6fea64SMauro Carvalho Chehab                signature = args['functiontype'] + " "
3791d6fea64SMauro Carvalho Chehab            signature += args['function'] + " ("
3801d6fea64SMauro Carvalho Chehab
3811d6fea64SMauro Carvalho Chehab        parameterlist = args.get('parameterlist', [])
3821d6fea64SMauro Carvalho Chehab        parameterdescs = args.get('parameterdescs', {})
3831d6fea64SMauro Carvalho Chehab        parameterdesc_start_lines = args.get('parameterdesc_start_lines', {})
3841d6fea64SMauro Carvalho Chehab
385c3597ab2SMauro Carvalho Chehab        ln = args.get('declaration_start_line', 0)
3861d6fea64SMauro Carvalho Chehab
3871d6fea64SMauro Carvalho Chehab        count = 0
3881d6fea64SMauro Carvalho Chehab        for parameter in parameterlist:
3891d6fea64SMauro Carvalho Chehab            if count != 0:
3901d6fea64SMauro Carvalho Chehab                signature += ", "
3911d6fea64SMauro Carvalho Chehab            count += 1
3921d6fea64SMauro Carvalho Chehab            dtype = args['parametertypes'].get(parameter, "")
3931d6fea64SMauro Carvalho Chehab
3941d6fea64SMauro Carvalho Chehab            if function_pointer.search(dtype):
3951d6fea64SMauro Carvalho Chehab                signature += function_pointer.group(1) + parameter + function_pointer.group(3)
3961d6fea64SMauro Carvalho Chehab            else:
3971d6fea64SMauro Carvalho Chehab                signature += dtype
3981d6fea64SMauro Carvalho Chehab
3991d6fea64SMauro Carvalho Chehab        if not func_macro:
4001d6fea64SMauro Carvalho Chehab            signature += ")"
4011d6fea64SMauro Carvalho Chehab
402c3597ab2SMauro Carvalho Chehab        self.print_lineno(ln)
4031d6fea64SMauro Carvalho Chehab        if args.get('typedef') or not args.get('functiontype'):
4044fa5e411SMauro Carvalho Chehab            self.data += f".. c:macro:: {args['function']}\n\n"
4051d6fea64SMauro Carvalho Chehab
4061d6fea64SMauro Carvalho Chehab            if args.get('typedef'):
4074fa5e411SMauro Carvalho Chehab                self.data += "   **Typedef**: "
4081d6fea64SMauro Carvalho Chehab                self.lineprefix = ""
4091d6fea64SMauro Carvalho Chehab                self.output_highlight(args.get('purpose', ""))
4104fa5e411SMauro Carvalho Chehab                self.data += "\n\n**Syntax**\n\n"
4114fa5e411SMauro Carvalho Chehab                self.data += f"  ``{signature}``\n\n"
4121d6fea64SMauro Carvalho Chehab            else:
4134fa5e411SMauro Carvalho Chehab                self.data += f"``{signature}``\n\n"
4141d6fea64SMauro Carvalho Chehab        else:
4154fa5e411SMauro Carvalho Chehab            self.data += f".. c:function:: {signature}\n\n"
4161d6fea64SMauro Carvalho Chehab
4171d6fea64SMauro Carvalho Chehab        if not args.get('typedef'):
4181d6fea64SMauro Carvalho Chehab            self.print_lineno(ln)
4191d6fea64SMauro Carvalho Chehab            self.lineprefix = "   "
4201d6fea64SMauro Carvalho Chehab            self.output_highlight(args.get('purpose', ""))
4214fa5e411SMauro Carvalho Chehab            self.data += "\n"
4221d6fea64SMauro Carvalho Chehab
4231d6fea64SMauro Carvalho Chehab        # Put descriptive text into a container (HTML <div>) to help set
4241d6fea64SMauro Carvalho Chehab        # function prototypes apart
4251d6fea64SMauro Carvalho Chehab        self.lineprefix = "  "
4261d6fea64SMauro Carvalho Chehab
4271d6fea64SMauro Carvalho Chehab        if parameterlist:
4284fa5e411SMauro Carvalho Chehab            self.data += ".. container:: kernelindent\n\n"
4294fa5e411SMauro Carvalho Chehab            self.data += f"{self.lineprefix}**Parameters**\n\n"
4301d6fea64SMauro Carvalho Chehab
4311d6fea64SMauro Carvalho Chehab        for parameter in parameterlist:
432*04a383ceSMauro Carvalho Chehab            parameter_name = KernRe(r'\[.*').sub('', parameter)
4331d6fea64SMauro Carvalho Chehab            dtype = args['parametertypes'].get(parameter, "")
4341d6fea64SMauro Carvalho Chehab
4351d6fea64SMauro Carvalho Chehab            if dtype:
4364fa5e411SMauro Carvalho Chehab                self.data += f"{self.lineprefix}``{dtype}``\n"
4371d6fea64SMauro Carvalho Chehab            else:
4384fa5e411SMauro Carvalho Chehab                self.data += f"{self.lineprefix}``{parameter}``\n"
4391d6fea64SMauro Carvalho Chehab
4401d6fea64SMauro Carvalho Chehab            self.print_lineno(parameterdesc_start_lines.get(parameter_name, 0))
4411d6fea64SMauro Carvalho Chehab
4421d6fea64SMauro Carvalho Chehab            self.lineprefix = "    "
4431d6fea64SMauro Carvalho Chehab            if parameter_name in parameterdescs and \
4441d6fea64SMauro Carvalho Chehab               parameterdescs[parameter_name] != KernelDoc.undescribed:
4451d6fea64SMauro Carvalho Chehab
4461d6fea64SMauro Carvalho Chehab                self.output_highlight(parameterdescs[parameter_name])
4474fa5e411SMauro Carvalho Chehab                self.data += "\n"
4481d6fea64SMauro Carvalho Chehab            else:
4494fa5e411SMauro Carvalho Chehab                self.data += f"{self.lineprefix}*undescribed*\n\n"
4501d6fea64SMauro Carvalho Chehab            self.lineprefix = "  "
4511d6fea64SMauro Carvalho Chehab
4521d6fea64SMauro Carvalho Chehab        self.out_section(args)
4531d6fea64SMauro Carvalho Chehab        self.lineprefix = oldprefix
4541d6fea64SMauro Carvalho Chehab
4551d6fea64SMauro Carvalho Chehab    def out_enum(self, fname, name, args):
4561d6fea64SMauro Carvalho Chehab
4571d6fea64SMauro Carvalho Chehab        oldprefix = self.lineprefix
4581d6fea64SMauro Carvalho Chehab        name = args.get('enum', '')
4591d6fea64SMauro Carvalho Chehab        parameterlist = args.get('parameterlist', [])
4601d6fea64SMauro Carvalho Chehab        parameterdescs = args.get('parameterdescs', {})
461c3597ab2SMauro Carvalho Chehab        ln = args.get('declaration_start_line', 0)
4621d6fea64SMauro Carvalho Chehab
4634fa5e411SMauro Carvalho Chehab        self.data += f"\n\n.. c:enum:: {name}\n\n"
4641d6fea64SMauro Carvalho Chehab
4651d6fea64SMauro Carvalho Chehab        self.print_lineno(ln)
4661d6fea64SMauro Carvalho Chehab        self.lineprefix = "  "
4671d6fea64SMauro Carvalho Chehab        self.output_highlight(args.get('purpose', ''))
4684fa5e411SMauro Carvalho Chehab        self.data += "\n"
4691d6fea64SMauro Carvalho Chehab
4704fa5e411SMauro Carvalho Chehab        self.data += ".. container:: kernelindent\n\n"
4711d6fea64SMauro Carvalho Chehab        outer = self.lineprefix + "  "
4721d6fea64SMauro Carvalho Chehab        self.lineprefix = outer + "  "
4734fa5e411SMauro Carvalho Chehab        self.data += f"{outer}**Constants**\n\n"
4741d6fea64SMauro Carvalho Chehab
4751d6fea64SMauro Carvalho Chehab        for parameter in parameterlist:
4764fa5e411SMauro Carvalho Chehab            self.data += f"{outer}``{parameter}``\n"
4771d6fea64SMauro Carvalho Chehab
4781d6fea64SMauro Carvalho Chehab            if parameterdescs.get(parameter, '') != KernelDoc.undescribed:
4791d6fea64SMauro Carvalho Chehab                self.output_highlight(parameterdescs[parameter])
4801d6fea64SMauro Carvalho Chehab            else:
4814fa5e411SMauro Carvalho Chehab                self.data += f"{self.lineprefix}*undescribed*\n\n"
4824fa5e411SMauro Carvalho Chehab            self.data += "\n"
4831d6fea64SMauro Carvalho Chehab
4841d6fea64SMauro Carvalho Chehab        self.lineprefix = oldprefix
4851d6fea64SMauro Carvalho Chehab        self.out_section(args)
4861d6fea64SMauro Carvalho Chehab
4871d6fea64SMauro Carvalho Chehab    def out_typedef(self, fname, name, args):
4881d6fea64SMauro Carvalho Chehab
4891d6fea64SMauro Carvalho Chehab        oldprefix = self.lineprefix
4901d6fea64SMauro Carvalho Chehab        name = args.get('typedef', '')
491c3597ab2SMauro Carvalho Chehab        ln = args.get('declaration_start_line', 0)
4921d6fea64SMauro Carvalho Chehab
4934fa5e411SMauro Carvalho Chehab        self.data += f"\n\n.. c:type:: {name}\n\n"
4941d6fea64SMauro Carvalho Chehab
4951d6fea64SMauro Carvalho Chehab        self.print_lineno(ln)
4961d6fea64SMauro Carvalho Chehab        self.lineprefix = "   "
4971d6fea64SMauro Carvalho Chehab
4981d6fea64SMauro Carvalho Chehab        self.output_highlight(args.get('purpose', ''))
4991d6fea64SMauro Carvalho Chehab
5004fa5e411SMauro Carvalho Chehab        self.data += "\n"
5011d6fea64SMauro Carvalho Chehab
5021d6fea64SMauro Carvalho Chehab        self.lineprefix = oldprefix
5031d6fea64SMauro Carvalho Chehab        self.out_section(args)
5041d6fea64SMauro Carvalho Chehab
5051d6fea64SMauro Carvalho Chehab    def out_struct(self, fname, name, args):
5061d6fea64SMauro Carvalho Chehab
5071d6fea64SMauro Carvalho Chehab        name = args.get('struct', "")
5081d6fea64SMauro Carvalho Chehab        purpose = args.get('purpose', "")
5091d6fea64SMauro Carvalho Chehab        declaration = args.get('definition', "")
5101d6fea64SMauro Carvalho Chehab        dtype = args.get('type', "struct")
511c3597ab2SMauro Carvalho Chehab        ln = args.get('declaration_start_line', 0)
5121d6fea64SMauro Carvalho Chehab
5131d6fea64SMauro Carvalho Chehab        parameterlist = args.get('parameterlist', [])
5141d6fea64SMauro Carvalho Chehab        parameterdescs = args.get('parameterdescs', {})
5151d6fea64SMauro Carvalho Chehab        parameterdesc_start_lines = args.get('parameterdesc_start_lines', {})
5161d6fea64SMauro Carvalho Chehab
5174fa5e411SMauro Carvalho Chehab        self.data += f"\n\n.. c:{dtype}:: {name}\n\n"
5181d6fea64SMauro Carvalho Chehab
5191d6fea64SMauro Carvalho Chehab        self.print_lineno(ln)
5201d6fea64SMauro Carvalho Chehab
5211d6fea64SMauro Carvalho Chehab        oldprefix = self.lineprefix
5221d6fea64SMauro Carvalho Chehab        self.lineprefix += "  "
5231d6fea64SMauro Carvalho Chehab
5241d6fea64SMauro Carvalho Chehab        self.output_highlight(purpose)
5254fa5e411SMauro Carvalho Chehab        self.data += "\n"
5261d6fea64SMauro Carvalho Chehab
5274fa5e411SMauro Carvalho Chehab        self.data += ".. container:: kernelindent\n\n"
5284fa5e411SMauro Carvalho Chehab        self.data += f"{self.lineprefix}**Definition**::\n\n"
5291d6fea64SMauro Carvalho Chehab
5301d6fea64SMauro Carvalho Chehab        self.lineprefix = self.lineprefix + "  "
5311d6fea64SMauro Carvalho Chehab
5321d6fea64SMauro Carvalho Chehab        declaration = declaration.replace("\t", self.lineprefix)
5331d6fea64SMauro Carvalho Chehab
5344fa5e411SMauro Carvalho Chehab        self.data += f"{self.lineprefix}{dtype} {name}" + ' {' + "\n"
5354fa5e411SMauro Carvalho Chehab        self.data += f"{declaration}{self.lineprefix}" + "};\n\n"
5361d6fea64SMauro Carvalho Chehab
5371d6fea64SMauro Carvalho Chehab        self.lineprefix = "  "
5384fa5e411SMauro Carvalho Chehab        self.data += f"{self.lineprefix}**Members**\n\n"
5391d6fea64SMauro Carvalho Chehab        for parameter in parameterlist:
5401d6fea64SMauro Carvalho Chehab            if not parameter or parameter.startswith("#"):
5411d6fea64SMauro Carvalho Chehab                continue
5421d6fea64SMauro Carvalho Chehab
5431d6fea64SMauro Carvalho Chehab            parameter_name = parameter.split("[", maxsplit=1)[0]
5441d6fea64SMauro Carvalho Chehab
5451d6fea64SMauro Carvalho Chehab            if parameterdescs.get(parameter_name) == KernelDoc.undescribed:
5461d6fea64SMauro Carvalho Chehab                continue
5471d6fea64SMauro Carvalho Chehab
5481d6fea64SMauro Carvalho Chehab            self.print_lineno(parameterdesc_start_lines.get(parameter_name, 0))
5491d6fea64SMauro Carvalho Chehab
5504fa5e411SMauro Carvalho Chehab            self.data += f"{self.lineprefix}``{parameter}``\n"
5511d6fea64SMauro Carvalho Chehab
5521d6fea64SMauro Carvalho Chehab            self.lineprefix = "    "
5531d6fea64SMauro Carvalho Chehab            self.output_highlight(parameterdescs[parameter_name])
5541d6fea64SMauro Carvalho Chehab            self.lineprefix = "  "
5551d6fea64SMauro Carvalho Chehab
5564fa5e411SMauro Carvalho Chehab            self.data += "\n"
5571d6fea64SMauro Carvalho Chehab
5584fa5e411SMauro Carvalho Chehab        self.data += "\n"
5591d6fea64SMauro Carvalho Chehab
5601d6fea64SMauro Carvalho Chehab        self.lineprefix = oldprefix
5611d6fea64SMauro Carvalho Chehab        self.out_section(args)
5621d6fea64SMauro Carvalho Chehab
5631d6fea64SMauro Carvalho Chehab
5641d6fea64SMauro Carvalho Chehabclass ManFormat(OutputFormat):
5651d6fea64SMauro Carvalho Chehab    """Consts and functions used by man pages output"""
5661d6fea64SMauro Carvalho Chehab
5671d6fea64SMauro Carvalho Chehab    highlights = (
5681d6fea64SMauro Carvalho Chehab        (type_constant, r"\1"),
5691d6fea64SMauro Carvalho Chehab        (type_constant2, r"\1"),
5701d6fea64SMauro Carvalho Chehab        (type_func, r"\\fB\1\\fP"),
5711d6fea64SMauro Carvalho Chehab        (type_enum, r"\\fI\1\\fP"),
5721d6fea64SMauro Carvalho Chehab        (type_struct, r"\\fI\1\\fP"),
5731d6fea64SMauro Carvalho Chehab        (type_typedef, r"\\fI\1\\fP"),
5741d6fea64SMauro Carvalho Chehab        (type_union, r"\\fI\1\\fP"),
5751d6fea64SMauro Carvalho Chehab        (type_param, r"\\fI\1\\fP"),
5761d6fea64SMauro Carvalho Chehab        (type_param_ref, r"\\fI\1\2\\fP"),
5771d6fea64SMauro Carvalho Chehab        (type_member, r"\\fI\1\2\3\\fP"),
5781d6fea64SMauro Carvalho Chehab        (type_fallback, r"\\fI\1\\fP")
5791d6fea64SMauro Carvalho Chehab    )
5801d6fea64SMauro Carvalho Chehab    blankline = ""
5811d6fea64SMauro Carvalho Chehab
58291d00bd5SMauro Carvalho Chehab    date_formats = [
58391d00bd5SMauro Carvalho Chehab        "%a %b %d %H:%M:%S %Z %Y",
58491d00bd5SMauro Carvalho Chehab        "%a %b %d %H:%M:%S %Y",
58591d00bd5SMauro Carvalho Chehab        "%Y-%m-%d",
58691d00bd5SMauro Carvalho Chehab        "%b %d %Y",
58791d00bd5SMauro Carvalho Chehab        "%B %d %Y",
58891d00bd5SMauro Carvalho Chehab        "%m %d %Y",
58991d00bd5SMauro Carvalho Chehab    ]
59091d00bd5SMauro Carvalho Chehab
5912ab867a4SMauro Carvalho Chehab    def __init__(self, modulename):
5921d6fea64SMauro Carvalho Chehab        """
5931d6fea64SMauro Carvalho Chehab        Creates class variables.
5941d6fea64SMauro Carvalho Chehab
5951d6fea64SMauro Carvalho Chehab        Not really mandatory, but it is a good coding style and makes
5961d6fea64SMauro Carvalho Chehab        pylint happy.
5971d6fea64SMauro Carvalho Chehab        """
5981d6fea64SMauro Carvalho Chehab
5991d6fea64SMauro Carvalho Chehab        super().__init__()
6002ab867a4SMauro Carvalho Chehab        self.modulename = modulename
6011d6fea64SMauro Carvalho Chehab
60291d00bd5SMauro Carvalho Chehab        dt = None
60391d00bd5SMauro Carvalho Chehab        tstamp = os.environ.get("KBUILD_BUILD_TIMESTAMP")
60491d00bd5SMauro Carvalho Chehab        if tstamp:
60591d00bd5SMauro Carvalho Chehab            for fmt in self.date_formats:
60691d00bd5SMauro Carvalho Chehab                try:
60791d00bd5SMauro Carvalho Chehab                    dt = datetime.strptime(tstamp, fmt)
60891d00bd5SMauro Carvalho Chehab                    break
60991d00bd5SMauro Carvalho Chehab                except ValueError:
61091d00bd5SMauro Carvalho Chehab                    pass
61191d00bd5SMauro Carvalho Chehab
61291d00bd5SMauro Carvalho Chehab        if not dt:
6131d6fea64SMauro Carvalho Chehab            dt = datetime.now()
6141d6fea64SMauro Carvalho Chehab
6151d6fea64SMauro Carvalho Chehab        self.man_date = dt.strftime("%B %Y")
6161d6fea64SMauro Carvalho Chehab
6171d6fea64SMauro Carvalho Chehab    def output_highlight(self, block):
618485f6f79SMauro Carvalho Chehab        """
619485f6f79SMauro Carvalho Chehab        Outputs a C symbol that may require being highlighted with
620485f6f79SMauro Carvalho Chehab        self.highlights variable using troff syntax
621485f6f79SMauro Carvalho Chehab        """
6221d6fea64SMauro Carvalho Chehab
6231d6fea64SMauro Carvalho Chehab        contents = self.highlight_block(block)
6241d6fea64SMauro Carvalho Chehab
6251d6fea64SMauro Carvalho Chehab        if isinstance(contents, list):
6261d6fea64SMauro Carvalho Chehab            contents = "\n".join(contents)
6271d6fea64SMauro Carvalho Chehab
6281d6fea64SMauro Carvalho Chehab        for line in contents.strip("\n").split("\n"):
629*04a383ceSMauro Carvalho Chehab            line = KernRe(r"^\s*").sub("", line)
630408269aeSMauro Carvalho Chehab            if not line:
631408269aeSMauro Carvalho Chehab                continue
6321d6fea64SMauro Carvalho Chehab
633408269aeSMauro Carvalho Chehab            if line[0] == ".":
6344fa5e411SMauro Carvalho Chehab                self.data += "\\&" + line + "\n"
6351d6fea64SMauro Carvalho Chehab            else:
6364fa5e411SMauro Carvalho Chehab                self.data += line + "\n"
6371d6fea64SMauro Carvalho Chehab
6381d6fea64SMauro Carvalho Chehab    def out_doc(self, fname, name, args):
6391d6fea64SMauro Carvalho Chehab        sectionlist = args.get('sectionlist', [])
6401d6fea64SMauro Carvalho Chehab        sections = args.get('sections', {})
6411d6fea64SMauro Carvalho Chehab
6429cbc2d3bSMauro Carvalho Chehab        if not self.check_doc(name, args):
643408269aeSMauro Carvalho Chehab            return
644408269aeSMauro Carvalho Chehab
6452ab867a4SMauro Carvalho Chehab        self.data += f'.TH "{self.modulename}" 9 "{self.modulename}" "{self.man_date}" "API Manual" LINUX' + "\n"
6461d6fea64SMauro Carvalho Chehab
6471d6fea64SMauro Carvalho Chehab        for section in sectionlist:
6484fa5e411SMauro Carvalho Chehab            self.data += f'.SH "{section}"' + "\n"
6491d6fea64SMauro Carvalho Chehab            self.output_highlight(sections.get(section))
6501d6fea64SMauro Carvalho Chehab
6511d6fea64SMauro Carvalho Chehab    def out_function(self, fname, name, args):
6521d6fea64SMauro Carvalho Chehab        """output function in man"""
6531d6fea64SMauro Carvalho Chehab
6541d6fea64SMauro Carvalho Chehab        parameterlist = args.get('parameterlist', [])
6551d6fea64SMauro Carvalho Chehab        parameterdescs = args.get('parameterdescs', {})
6561d6fea64SMauro Carvalho Chehab        sectionlist = args.get('sectionlist', [])
6571d6fea64SMauro Carvalho Chehab        sections = args.get('sections', {})
6581d6fea64SMauro Carvalho Chehab
65978ea748fSMauro Carvalho Chehab        self.data += f'.TH "{args["function"]}" 9 "{args["function"]}" "{self.man_date}" "Kernel Hacker\'s Manual" LINUX' + "\n"
6601d6fea64SMauro Carvalho Chehab
6614fa5e411SMauro Carvalho Chehab        self.data += ".SH NAME\n"
6624fa5e411SMauro Carvalho Chehab        self.data += f"{args['function']} \\- {args['purpose']}\n"
6631d6fea64SMauro Carvalho Chehab
6644fa5e411SMauro Carvalho Chehab        self.data += ".SH SYNOPSIS\n"
6651d6fea64SMauro Carvalho Chehab        if args.get('functiontype', ''):
66678ea748fSMauro Carvalho Chehab            self.data += f'.B "{args["functiontype"]}" {args["function"]}' + "\n"
6671d6fea64SMauro Carvalho Chehab        else:
66878ea748fSMauro Carvalho Chehab            self.data += f'.B "{args["function"]}' + "\n"
6691d6fea64SMauro Carvalho Chehab
6701d6fea64SMauro Carvalho Chehab        count = 0
6711d6fea64SMauro Carvalho Chehab        parenth = "("
6721d6fea64SMauro Carvalho Chehab        post = ","
6731d6fea64SMauro Carvalho Chehab
6741d6fea64SMauro Carvalho Chehab        for parameter in parameterlist:
6751d6fea64SMauro Carvalho Chehab            if count == len(parameterlist) - 1:
6761d6fea64SMauro Carvalho Chehab                post = ");"
6771d6fea64SMauro Carvalho Chehab
6781d6fea64SMauro Carvalho Chehab            dtype = args['parametertypes'].get(parameter, "")
6791d6fea64SMauro Carvalho Chehab            if function_pointer.match(dtype):
6801d6fea64SMauro Carvalho Chehab                # Pointer-to-function
6814fa5e411SMauro Carvalho Chehab                self.data += f'".BI "{parenth}{function_pointer.group(1)}" " ") ({function_pointer.group(2)}){post}"' + "\n"
6821d6fea64SMauro Carvalho Chehab            else:
683*04a383ceSMauro Carvalho Chehab                dtype = KernRe(r'([^\*])$').sub(r'\1 ', dtype)
6841d6fea64SMauro Carvalho Chehab
6854fa5e411SMauro Carvalho Chehab                self.data += f'.BI "{parenth}{dtype}"  "{post}"' + "\n"
6861d6fea64SMauro Carvalho Chehab            count += 1
6871d6fea64SMauro Carvalho Chehab            parenth = ""
6881d6fea64SMauro Carvalho Chehab
6891d6fea64SMauro Carvalho Chehab        if parameterlist:
6904fa5e411SMauro Carvalho Chehab            self.data += ".SH ARGUMENTS\n"
6911d6fea64SMauro Carvalho Chehab
6921d6fea64SMauro Carvalho Chehab        for parameter in parameterlist:
6931d6fea64SMauro Carvalho Chehab            parameter_name = re.sub(r'\[.*', '', parameter)
6941d6fea64SMauro Carvalho Chehab
6954fa5e411SMauro Carvalho Chehab            self.data += f'.IP "{parameter}" 12' + "\n"
6961d6fea64SMauro Carvalho Chehab            self.output_highlight(parameterdescs.get(parameter_name, ""))
6971d6fea64SMauro Carvalho Chehab
6981d6fea64SMauro Carvalho Chehab        for section in sectionlist:
6994fa5e411SMauro Carvalho Chehab            self.data += f'.SH "{section.upper()}"' + "\n"
7001d6fea64SMauro Carvalho Chehab            self.output_highlight(sections[section])
7011d6fea64SMauro Carvalho Chehab
7021d6fea64SMauro Carvalho Chehab    def out_enum(self, fname, name, args):
7031d6fea64SMauro Carvalho Chehab
7041d6fea64SMauro Carvalho Chehab        name = args.get('enum', '')
7051d6fea64SMauro Carvalho Chehab        parameterlist = args.get('parameterlist', [])
7061d6fea64SMauro Carvalho Chehab        sectionlist = args.get('sectionlist', [])
7071d6fea64SMauro Carvalho Chehab        sections = args.get('sections', {})
7081d6fea64SMauro Carvalho Chehab
7092ab867a4SMauro Carvalho Chehab        self.data += f'.TH "{self.modulename}" 9 "enum {args["enum"]}" "{self.man_date}" "API Manual" LINUX' + "\n"
7101d6fea64SMauro Carvalho Chehab
7114fa5e411SMauro Carvalho Chehab        self.data += ".SH NAME\n"
7124fa5e411SMauro Carvalho Chehab        self.data += f"enum {args['enum']} \\- {args['purpose']}\n"
7131d6fea64SMauro Carvalho Chehab
7144fa5e411SMauro Carvalho Chehab        self.data += ".SH SYNOPSIS\n"
7154fa5e411SMauro Carvalho Chehab        self.data += f"enum {args['enum']}" + " {\n"
7161d6fea64SMauro Carvalho Chehab
7171d6fea64SMauro Carvalho Chehab        count = 0
7181d6fea64SMauro Carvalho Chehab        for parameter in parameterlist:
7194fa5e411SMauro Carvalho Chehab            self.data += f'.br\n.BI "    {parameter}"' + "\n"
7201d6fea64SMauro Carvalho Chehab            if count == len(parameterlist) - 1:
7214fa5e411SMauro Carvalho Chehab                self.data += "\n};\n"
7221d6fea64SMauro Carvalho Chehab            else:
7234fa5e411SMauro Carvalho Chehab                self.data += ", \n.br\n"
7241d6fea64SMauro Carvalho Chehab
7251d6fea64SMauro Carvalho Chehab            count += 1
7261d6fea64SMauro Carvalho Chehab
7274fa5e411SMauro Carvalho Chehab        self.data += ".SH Constants\n"
7281d6fea64SMauro Carvalho Chehab
7291d6fea64SMauro Carvalho Chehab        for parameter in parameterlist:
730*04a383ceSMauro Carvalho Chehab            parameter_name = KernRe(r'\[.*').sub('', parameter)
7314fa5e411SMauro Carvalho Chehab            self.data += f'.IP "{parameter}" 12' + "\n"
7321d6fea64SMauro Carvalho Chehab            self.output_highlight(args['parameterdescs'].get(parameter_name, ""))
7331d6fea64SMauro Carvalho Chehab
7341d6fea64SMauro Carvalho Chehab        for section in sectionlist:
7354fa5e411SMauro Carvalho Chehab            self.data += f'.SH "{section}"' + "\n"
7361d6fea64SMauro Carvalho Chehab            self.output_highlight(sections[section])
7371d6fea64SMauro Carvalho Chehab
7381d6fea64SMauro Carvalho Chehab    def out_typedef(self, fname, name, args):
7392ab867a4SMauro Carvalho Chehab        module = self.modulename
7401d6fea64SMauro Carvalho Chehab        typedef = args.get('typedef')
7411d6fea64SMauro Carvalho Chehab        purpose = args.get('purpose')
7421d6fea64SMauro Carvalho Chehab        sectionlist = args.get('sectionlist', [])
7431d6fea64SMauro Carvalho Chehab        sections = args.get('sections', {})
7441d6fea64SMauro Carvalho Chehab
7454fa5e411SMauro Carvalho Chehab        self.data += f'.TH "{module}" 9 "{typedef}" "{self.man_date}" "API Manual" LINUX' + "\n"
7461d6fea64SMauro Carvalho Chehab
7474fa5e411SMauro Carvalho Chehab        self.data += ".SH NAME\n"
7484fa5e411SMauro Carvalho Chehab        self.data += f"typedef {typedef} \\- {purpose}\n"
7491d6fea64SMauro Carvalho Chehab
7501d6fea64SMauro Carvalho Chehab        for section in sectionlist:
7514fa5e411SMauro Carvalho Chehab            self.data += f'.SH "{section}"' + "\n"
7521d6fea64SMauro Carvalho Chehab            self.output_highlight(sections.get(section))
7531d6fea64SMauro Carvalho Chehab
7541d6fea64SMauro Carvalho Chehab    def out_struct(self, fname, name, args):
7552ab867a4SMauro Carvalho Chehab        module = self.modulename
7561d6fea64SMauro Carvalho Chehab        struct_type = args.get('type')
7571d6fea64SMauro Carvalho Chehab        struct_name = args.get('struct')
7581d6fea64SMauro Carvalho Chehab        purpose = args.get('purpose')
7591d6fea64SMauro Carvalho Chehab        definition = args.get('definition')
7601d6fea64SMauro Carvalho Chehab        sectionlist = args.get('sectionlist', [])
7611d6fea64SMauro Carvalho Chehab        parameterlist = args.get('parameterlist', [])
7621d6fea64SMauro Carvalho Chehab        sections = args.get('sections', {})
7631d6fea64SMauro Carvalho Chehab        parameterdescs = args.get('parameterdescs', {})
7641d6fea64SMauro Carvalho Chehab
7654fa5e411SMauro Carvalho Chehab        self.data += f'.TH "{module}" 9 "{struct_type} {struct_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
7661d6fea64SMauro Carvalho Chehab
7674fa5e411SMauro Carvalho Chehab        self.data += ".SH NAME\n"
7684fa5e411SMauro Carvalho Chehab        self.data += f"{struct_type} {struct_name} \\- {purpose}\n"
7691d6fea64SMauro Carvalho Chehab
7701d6fea64SMauro Carvalho Chehab        # Replace tabs with two spaces and handle newlines
7711d6fea64SMauro Carvalho Chehab        declaration = definition.replace("\t", "  ")
772*04a383ceSMauro Carvalho Chehab        declaration = KernRe(r"\n").sub('"\n.br\n.BI "', declaration)
7731d6fea64SMauro Carvalho Chehab
7744fa5e411SMauro Carvalho Chehab        self.data += ".SH SYNOPSIS\n"
7754fa5e411SMauro Carvalho Chehab        self.data += f"{struct_type} {struct_name} " + "{" + "\n.br\n"
7764fa5e411SMauro Carvalho Chehab        self.data += f'.BI "{declaration}\n' + "};\n.br\n\n"
7771d6fea64SMauro Carvalho Chehab
7784fa5e411SMauro Carvalho Chehab        self.data += ".SH Members\n"
7791d6fea64SMauro Carvalho Chehab        for parameter in parameterlist:
7801d6fea64SMauro Carvalho Chehab            if parameter.startswith("#"):
7811d6fea64SMauro Carvalho Chehab                continue
7821d6fea64SMauro Carvalho Chehab
7831d6fea64SMauro Carvalho Chehab            parameter_name = re.sub(r"\[.*", "", parameter)
7841d6fea64SMauro Carvalho Chehab
7851d6fea64SMauro Carvalho Chehab            if parameterdescs.get(parameter_name) == KernelDoc.undescribed:
7861d6fea64SMauro Carvalho Chehab                continue
7871d6fea64SMauro Carvalho Chehab
7884fa5e411SMauro Carvalho Chehab            self.data += f'.IP "{parameter}" 12' + "\n"
7891d6fea64SMauro Carvalho Chehab            self.output_highlight(parameterdescs.get(parameter_name))
7901d6fea64SMauro Carvalho Chehab
7911d6fea64SMauro Carvalho Chehab        for section in sectionlist:
7924fa5e411SMauro Carvalho Chehab            self.data += f'.SH "{section}"' + "\n"
7931d6fea64SMauro Carvalho Chehab            self.output_highlight(sections.get(section))
794