xref: /linux/tools/lib/python/kdoc/kdoc_output.py (revision 72c395024dac5e215136cbff793455f065603b06)
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"""
8*245f1ab2SMauro Carvalho ChehabClasses to implement output filters to print kernel-doc documentation.
91d6fea64SMauro Carvalho Chehab
10*245f1ab2SMauro Carvalho ChehabThe implementation uses a virtual base class ``OutputFormat``. It
115f88f44dSRandy Dunlapcontains 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
15*245f1ab2SMauro Carvalho Chehabof output, e.g. ``RestFormat`` and ``ManFormat`` classes.
16*245f1ab2SMauro Carvalho Chehab
17*245f1ab2SMauro Carvalho ChehabCurrently, there are output classes for ReST and man/troff.
181d6fea64SMauro Carvalho Chehab"""
191d6fea64SMauro Carvalho Chehab
201d6fea64SMauro Carvalho Chehabimport os
211d6fea64SMauro Carvalho Chehabimport re
221d6fea64SMauro Carvalho Chehabfrom datetime import datetime
231d6fea64SMauro Carvalho Chehab
24992a9df4SJonathan Corbetfrom kdoc.kdoc_parser import KernelDoc, type_param
25992a9df4SJonathan Corbetfrom kdoc.kdoc_re import KernRe
261d6fea64SMauro Carvalho Chehab
271d6fea64SMauro Carvalho Chehab
2804a383ceSMauro Carvalho Chehabfunction_pointer = KernRe(r"([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)", cache=False)
291d6fea64SMauro Carvalho Chehab
301d6fea64SMauro Carvalho Chehab# match expressions used to find embedded type information
3104a383ceSMauro Carvalho Chehabtype_constant = KernRe(r"\b``([^\`]+)``\b", cache=False)
3204a383ceSMauro Carvalho Chehabtype_constant2 = KernRe(r"\%([-_*\w]+)", cache=False)
3304a383ceSMauro Carvalho Chehabtype_func = KernRe(r"(\w+)\(\)", cache=False)
3404a383ceSMauro Carvalho Chehabtype_param_ref = KernRe(r"([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
351d6fea64SMauro Carvalho Chehab
361d6fea64SMauro Carvalho Chehab# Special RST handling for func ptr params
3704a383ceSMauro Carvalho Chehabtype_fp_param = KernRe(r"\@(\w+)\(\)", cache=False)
381d6fea64SMauro Carvalho Chehab
391d6fea64SMauro Carvalho Chehab# Special RST handling for structs with func ptr params
4004a383ceSMauro Carvalho Chehabtype_fp_param2 = KernRe(r"\@(\w+->\S+)\(\)", cache=False)
411d6fea64SMauro Carvalho Chehab
4204a383ceSMauro Carvalho Chehabtype_env = KernRe(r"(\$\w+)", cache=False)
4304a383ceSMauro Carvalho Chehabtype_enum = KernRe(r"\&(enum\s*([_\w]+))", cache=False)
4404a383ceSMauro Carvalho Chehabtype_struct = KernRe(r"\&(struct\s*([_\w]+))", cache=False)
4504a383ceSMauro Carvalho Chehabtype_typedef = KernRe(r"\&(typedef\s*([_\w]+))", cache=False)
4604a383ceSMauro Carvalho Chehabtype_union = KernRe(r"\&(union\s*([_\w]+))", cache=False)
4704a383ceSMauro Carvalho Chehabtype_member = KernRe(r"\&([_\w]+)(\.|->)([_\w]+)", cache=False)
4804a383ceSMauro Carvalho Chehabtype_fallback = KernRe(r"\&([_\w]+)", cache=False)
4904a383ceSMauro Carvalho Chehabtype_member_func = type_member + KernRe(r"\(\)", cache=False)
501d6fea64SMauro Carvalho Chehab
511d6fea64SMauro Carvalho Chehab
521d6fea64SMauro Carvalho Chehabclass OutputFormat:
53485f6f79SMauro Carvalho Chehab    """
54485f6f79SMauro Carvalho Chehab    Base class for OutputFormat. If used as-is, it means that only
55485f6f79SMauro Carvalho Chehab    warnings will be displayed.
56485f6f79SMauro Carvalho Chehab    """
57485f6f79SMauro Carvalho Chehab
581d6fea64SMauro Carvalho Chehab    # output mode.
59*245f1ab2SMauro Carvalho Chehab    OUTPUT_ALL          = 0 #: Output all symbols and doc sections.
60*245f1ab2SMauro Carvalho Chehab    OUTPUT_INCLUDE      = 1 #: Output only specified symbols.
61*245f1ab2SMauro Carvalho Chehab    OUTPUT_EXPORTED     = 2 #: Output exported symbols.
62*245f1ab2SMauro Carvalho Chehab    OUTPUT_INTERNAL     = 3 #: Output non-exported symbols.
631d6fea64SMauro Carvalho Chehab
64*245f1ab2SMauro Carvalho Chehab    #: Highlights to be used in ReST format.
651d6fea64SMauro Carvalho Chehab    highlights = []
661d6fea64SMauro Carvalho Chehab
67*245f1ab2SMauro Carvalho Chehab    #: Blank line character.
68*245f1ab2SMauro Carvalho Chehab    blankline = ""
69*245f1ab2SMauro Carvalho Chehab
701d6fea64SMauro Carvalho Chehab    def __init__(self):
71*245f1ab2SMauro Carvalho Chehab        """Declare internal vars and set mode to ``OUTPUT_ALL``."""
721d6fea64SMauro Carvalho Chehab
731d6fea64SMauro Carvalho Chehab        self.out_mode = self.OUTPUT_ALL
741d6fea64SMauro Carvalho Chehab        self.enable_lineno = None
751d6fea64SMauro Carvalho Chehab        self.nosymbol = {}
761d6fea64SMauro Carvalho Chehab        self.symbol = None
7716740c29SMauro Carvalho Chehab        self.function_table = None
781d6fea64SMauro Carvalho Chehab        self.config = None
790873e554SMauro Carvalho Chehab        self.no_doc_sections = False
801d6fea64SMauro Carvalho Chehab
814fa5e411SMauro Carvalho Chehab        self.data = ""
824fa5e411SMauro Carvalho Chehab
831d6fea64SMauro Carvalho Chehab    def set_config(self, config):
84485f6f79SMauro Carvalho Chehab        """
85485f6f79SMauro Carvalho Chehab        Setup global config variables used by both parser and output.
86485f6f79SMauro Carvalho Chehab        """
87485f6f79SMauro Carvalho Chehab
881d6fea64SMauro Carvalho Chehab        self.config = config
891d6fea64SMauro Carvalho Chehab
901d6fea64SMauro Carvalho Chehab    def set_filter(self, export, internal, symbol, nosymbol, function_table,
910873e554SMauro Carvalho Chehab                   enable_lineno, no_doc_sections):
921d6fea64SMauro Carvalho Chehab        """
935f88f44dSRandy Dunlap        Initialize filter variables according to the requested mode.
941d6fea64SMauro Carvalho Chehab
951d6fea64SMauro Carvalho Chehab        Only one choice is valid between export, internal and symbol.
961d6fea64SMauro Carvalho Chehab
971d6fea64SMauro Carvalho Chehab        The nosymbol filter can be used on all modes.
981d6fea64SMauro Carvalho Chehab        """
991d6fea64SMauro Carvalho Chehab
1001d6fea64SMauro Carvalho Chehab        self.enable_lineno = enable_lineno
1010873e554SMauro Carvalho Chehab        self.no_doc_sections = no_doc_sections
10216740c29SMauro Carvalho Chehab        self.function_table = function_table
1031d6fea64SMauro Carvalho Chehab
1041d6fea64SMauro Carvalho Chehab        if symbol:
1051d6fea64SMauro Carvalho Chehab            self.out_mode = self.OUTPUT_INCLUDE
1061d6fea64SMauro Carvalho Chehab        elif export:
1071d6fea64SMauro Carvalho Chehab            self.out_mode = self.OUTPUT_EXPORTED
1081d6fea64SMauro Carvalho Chehab        elif internal:
1091d6fea64SMauro Carvalho Chehab            self.out_mode = self.OUTPUT_INTERNAL
1101d6fea64SMauro Carvalho Chehab        else:
1111d6fea64SMauro Carvalho Chehab            self.out_mode = self.OUTPUT_ALL
1121d6fea64SMauro Carvalho Chehab
1131d6fea64SMauro Carvalho Chehab        if nosymbol:
1141d6fea64SMauro Carvalho Chehab            self.nosymbol = set(nosymbol)
1151d6fea64SMauro Carvalho Chehab
1161d6fea64SMauro Carvalho Chehab
1171d6fea64SMauro Carvalho Chehab    def highlight_block(self, block):
1181d6fea64SMauro Carvalho Chehab        """
1191d6fea64SMauro Carvalho Chehab        Apply the RST highlights to a sub-block of text.
1201d6fea64SMauro Carvalho Chehab        """
1211d6fea64SMauro Carvalho Chehab
1221d6fea64SMauro Carvalho Chehab        for r, sub in self.highlights:
1231d6fea64SMauro Carvalho Chehab            block = r.sub(sub, block)
1241d6fea64SMauro Carvalho Chehab
1251d6fea64SMauro Carvalho Chehab        return block
1261d6fea64SMauro Carvalho Chehab
1279cbc2d3bSMauro Carvalho Chehab    def out_warnings(self, args):
128485f6f79SMauro Carvalho Chehab        """
129485f6f79SMauro Carvalho Chehab        Output warnings for identifiers that will be displayed.
130485f6f79SMauro Carvalho Chehab        """
131485f6f79SMauro Carvalho Chehab
132bd5628bfSJonathan Corbet        for log_msg in args.warnings:
13316740c29SMauro Carvalho Chehab            self.config.warning(log_msg)
1349cbc2d3bSMauro Carvalho Chehab
1359cbc2d3bSMauro Carvalho Chehab    def check_doc(self, name, args):
136*245f1ab2SMauro Carvalho Chehab        """Check if DOC should be output."""
1371d6fea64SMauro Carvalho Chehab
1380873e554SMauro Carvalho Chehab        if self.no_doc_sections:
1390873e554SMauro Carvalho Chehab            return False
1400873e554SMauro Carvalho Chehab
141408269aeSMauro Carvalho Chehab        if name in self.nosymbol:
142408269aeSMauro Carvalho Chehab            return False
143408269aeSMauro Carvalho Chehab
1441d6fea64SMauro Carvalho Chehab        if self.out_mode == self.OUTPUT_ALL:
1459cbc2d3bSMauro Carvalho Chehab            self.out_warnings(args)
1461d6fea64SMauro Carvalho Chehab            return True
1471d6fea64SMauro Carvalho Chehab
1481d6fea64SMauro Carvalho Chehab        if self.out_mode == self.OUTPUT_INCLUDE:
1491d6fea64SMauro Carvalho Chehab            if name in self.function_table:
1509cbc2d3bSMauro Carvalho Chehab                self.out_warnings(args)
1511d6fea64SMauro Carvalho Chehab                return True
1521d6fea64SMauro Carvalho Chehab
1531d6fea64SMauro Carvalho Chehab        return False
1541d6fea64SMauro Carvalho Chehab
1559cbc2d3bSMauro Carvalho Chehab    def check_declaration(self, dtype, name, args):
156485f6f79SMauro Carvalho Chehab        """
157485f6f79SMauro Carvalho Chehab        Checks if a declaration should be output or not based on the
158485f6f79SMauro Carvalho Chehab        filtering criteria.
159485f6f79SMauro Carvalho Chehab        """
160485f6f79SMauro Carvalho Chehab
1611d6fea64SMauro Carvalho Chehab        if name in self.nosymbol:
1621d6fea64SMauro Carvalho Chehab            return False
1631d6fea64SMauro Carvalho Chehab
1641d6fea64SMauro Carvalho Chehab        if self.out_mode == self.OUTPUT_ALL:
1659cbc2d3bSMauro Carvalho Chehab            self.out_warnings(args)
1661d6fea64SMauro Carvalho Chehab            return True
1671d6fea64SMauro Carvalho Chehab
1681d6fea64SMauro Carvalho Chehab        if self.out_mode in [self.OUTPUT_INCLUDE, self.OUTPUT_EXPORTED]:
1691d6fea64SMauro Carvalho Chehab            if name in self.function_table:
1701d6fea64SMauro Carvalho Chehab                return True
1711d6fea64SMauro Carvalho Chehab
1721d6fea64SMauro Carvalho Chehab        if self.out_mode == self.OUTPUT_INTERNAL:
1731d6fea64SMauro Carvalho Chehab            if dtype != "function":
1749cbc2d3bSMauro Carvalho Chehab                self.out_warnings(args)
1751d6fea64SMauro Carvalho Chehab                return True
1761d6fea64SMauro Carvalho Chehab
1771d6fea64SMauro Carvalho Chehab            if name not in self.function_table:
1789cbc2d3bSMauro Carvalho Chehab                self.out_warnings(args)
1791d6fea64SMauro Carvalho Chehab                return True
1801d6fea64SMauro Carvalho Chehab
1811d6fea64SMauro Carvalho Chehab        return False
1821d6fea64SMauro Carvalho Chehab
1831d6fea64SMauro Carvalho Chehab    def msg(self, fname, name, args):
184485f6f79SMauro Carvalho Chehab        """
185*245f1ab2SMauro Carvalho Chehab        Handles a single entry from kernel-doc parser.
186485f6f79SMauro Carvalho Chehab        """
187485f6f79SMauro Carvalho Chehab
1884fa5e411SMauro Carvalho Chehab        self.data = ""
1891d6fea64SMauro Carvalho Chehab
190bd5628bfSJonathan Corbet        dtype = args.type
1911d6fea64SMauro Carvalho Chehab
1921d6fea64SMauro Carvalho Chehab        if dtype == "doc":
1931d6fea64SMauro Carvalho Chehab            self.out_doc(fname, name, args)
1944fa5e411SMauro Carvalho Chehab            return self.data
1951d6fea64SMauro Carvalho Chehab
1969cbc2d3bSMauro Carvalho Chehab        if not self.check_declaration(dtype, name, args):
1974fa5e411SMauro Carvalho Chehab            return self.data
1981d6fea64SMauro Carvalho Chehab
1991d6fea64SMauro Carvalho Chehab        if dtype == "function":
2001d6fea64SMauro Carvalho Chehab            self.out_function(fname, name, args)
2014fa5e411SMauro Carvalho Chehab            return self.data
2021d6fea64SMauro Carvalho Chehab
2031d6fea64SMauro Carvalho Chehab        if dtype == "enum":
2041d6fea64SMauro Carvalho Chehab            self.out_enum(fname, name, args)
2054fa5e411SMauro Carvalho Chehab            return self.data
2061d6fea64SMauro Carvalho Chehab
2071045ec38SMauro Carvalho Chehab        if dtype == "var":
2081045ec38SMauro Carvalho Chehab            self.out_var(fname, name, args)
2091045ec38SMauro Carvalho Chehab            return self.data
2101045ec38SMauro Carvalho Chehab
2111d6fea64SMauro Carvalho Chehab        if dtype == "typedef":
2121d6fea64SMauro Carvalho Chehab            self.out_typedef(fname, name, args)
2134fa5e411SMauro Carvalho Chehab            return self.data
2141d6fea64SMauro Carvalho Chehab
2151d6fea64SMauro Carvalho Chehab        if dtype in ["struct", "union"]:
2161d6fea64SMauro Carvalho Chehab            self.out_struct(fname, name, args)
2174fa5e411SMauro Carvalho Chehab            return self.data
2181d6fea64SMauro Carvalho Chehab
2191d6fea64SMauro Carvalho Chehab        # Warn if some type requires an output logic
2205f88f44dSRandy Dunlap        self.config.log.warning("doesn't know how to output '%s' block",
2211d6fea64SMauro Carvalho Chehab                                dtype)
2221d6fea64SMauro Carvalho Chehab
2234fa5e411SMauro Carvalho Chehab        return None
2241d6fea64SMauro Carvalho Chehab
2251d6fea64SMauro Carvalho Chehab    # Virtual methods to be overridden by inherited classes
226485f6f79SMauro Carvalho Chehab    # At the base class, those do nothing.
227104e0a68SMauro Carvalho Chehab    def set_symbols(self, symbols):
228*245f1ab2SMauro Carvalho Chehab        """Get a list of all symbols from kernel_doc."""
229104e0a68SMauro Carvalho Chehab
2301d6fea64SMauro Carvalho Chehab    def out_doc(self, fname, name, args):
231*245f1ab2SMauro Carvalho Chehab        """Outputs a DOC block."""
2321d6fea64SMauro Carvalho Chehab
2331d6fea64SMauro Carvalho Chehab    def out_function(self, fname, name, args):
234*245f1ab2SMauro Carvalho Chehab        """Outputs a function."""
2351d6fea64SMauro Carvalho Chehab
2361d6fea64SMauro Carvalho Chehab    def out_enum(self, fname, name, args):
237*245f1ab2SMauro Carvalho Chehab        """Outputs an enum."""
2381d6fea64SMauro Carvalho Chehab
2391045ec38SMauro Carvalho Chehab    def out_var(self, fname, name, args):
240*245f1ab2SMauro Carvalho Chehab        """Outputs a variable."""
2411045ec38SMauro Carvalho Chehab
2421d6fea64SMauro Carvalho Chehab    def out_typedef(self, fname, name, args):
243*245f1ab2SMauro Carvalho Chehab        """Outputs a typedef."""
2441d6fea64SMauro Carvalho Chehab
2451d6fea64SMauro Carvalho Chehab    def out_struct(self, fname, name, args):
246*245f1ab2SMauro Carvalho Chehab        """Outputs a struct."""
2471d6fea64SMauro Carvalho Chehab
2481d6fea64SMauro Carvalho Chehab
2491d6fea64SMauro Carvalho Chehabclass RestFormat(OutputFormat):
250*245f1ab2SMauro Carvalho Chehab    """Consts and functions used by ReST output."""
2511d6fea64SMauro Carvalho Chehab
252*245f1ab2SMauro Carvalho Chehab    #: Highlights to be used in ReST format
2531d6fea64SMauro Carvalho Chehab    highlights = [
2541d6fea64SMauro Carvalho Chehab        (type_constant, r"``\1``"),
2551d6fea64SMauro Carvalho Chehab        (type_constant2, r"``\1``"),
2561d6fea64SMauro Carvalho Chehab
2571d6fea64SMauro Carvalho Chehab        # Note: need to escape () to avoid func matching later
2581d6fea64SMauro Carvalho Chehab        (type_member_func, r":c:type:`\1\2\3\\(\\) <\1>`"),
2591d6fea64SMauro Carvalho Chehab        (type_member, r":c:type:`\1\2\3 <\1>`"),
2601d6fea64SMauro Carvalho Chehab        (type_fp_param, r"**\1\\(\\)**"),
2611d6fea64SMauro Carvalho Chehab        (type_fp_param2, r"**\1\\(\\)**"),
2621d6fea64SMauro Carvalho Chehab        (type_func, r"\1()"),
2631d6fea64SMauro Carvalho Chehab        (type_enum, r":c:type:`\1 <\2>`"),
2641d6fea64SMauro Carvalho Chehab        (type_struct, r":c:type:`\1 <\2>`"),
2651d6fea64SMauro Carvalho Chehab        (type_typedef, r":c:type:`\1 <\2>`"),
2661d6fea64SMauro Carvalho Chehab        (type_union, r":c:type:`\1 <\2>`"),
2671d6fea64SMauro Carvalho Chehab
2681d6fea64SMauro Carvalho Chehab        # in rst this can refer to any type
2691d6fea64SMauro Carvalho Chehab        (type_fallback, r":c:type:`\1`"),
2701d6fea64SMauro Carvalho Chehab        (type_param_ref, r"**\1\2**")
2711d6fea64SMauro Carvalho Chehab    ]
272*245f1ab2SMauro Carvalho Chehab
2731d6fea64SMauro Carvalho Chehab    blankline = "\n"
2741d6fea64SMauro Carvalho Chehab
275*245f1ab2SMauro Carvalho Chehab    #: Sphinx literal block regex.
27604a383ceSMauro Carvalho Chehab    sphinx_literal = KernRe(r'^[^.].*::$', cache=False)
277*245f1ab2SMauro Carvalho Chehab
278*245f1ab2SMauro Carvalho Chehab    #: Sphinx code block regex.
27904a383ceSMauro Carvalho Chehab    sphinx_cblock = KernRe(r'^\.\.\ +code-block::', cache=False)
2801d6fea64SMauro Carvalho Chehab
2811d6fea64SMauro Carvalho Chehab    def __init__(self):
2821d6fea64SMauro Carvalho Chehab        """
2831d6fea64SMauro Carvalho Chehab        Creates class variables.
2841d6fea64SMauro Carvalho Chehab
2851d6fea64SMauro Carvalho Chehab        Not really mandatory, but it is a good coding style and makes
2861d6fea64SMauro Carvalho Chehab        pylint happy.
2871d6fea64SMauro Carvalho Chehab        """
2881d6fea64SMauro Carvalho Chehab
2891d6fea64SMauro Carvalho Chehab        super().__init__()
2901d6fea64SMauro Carvalho Chehab        self.lineprefix = ""
2911d6fea64SMauro Carvalho Chehab
2921d6fea64SMauro Carvalho Chehab    def print_lineno(self, ln):
293*245f1ab2SMauro Carvalho Chehab        """Outputs a line number."""
2941d6fea64SMauro Carvalho Chehab
295c3597ab2SMauro Carvalho Chehab        if self.enable_lineno and ln is not None:
296c3597ab2SMauro Carvalho Chehab            ln += 1
2974fa5e411SMauro Carvalho Chehab            self.data += f".. LINENO {ln}\n"
2981d6fea64SMauro Carvalho Chehab
2991d6fea64SMauro Carvalho Chehab    def output_highlight(self, args):
300485f6f79SMauro Carvalho Chehab        """
301485f6f79SMauro Carvalho Chehab        Outputs a C symbol that may require being converted to ReST using
302*245f1ab2SMauro Carvalho Chehab        the self.highlights variable.
303485f6f79SMauro Carvalho Chehab        """
304485f6f79SMauro Carvalho Chehab
3051d6fea64SMauro Carvalho Chehab        input_text = args
3061d6fea64SMauro Carvalho Chehab        output = ""
3071d6fea64SMauro Carvalho Chehab        in_literal = False
3081d6fea64SMauro Carvalho Chehab        litprefix = ""
3091d6fea64SMauro Carvalho Chehab        block = ""
3101d6fea64SMauro Carvalho Chehab
3111d6fea64SMauro Carvalho Chehab        for line in input_text.strip("\n").split("\n"):
3121d6fea64SMauro Carvalho Chehab
3131d6fea64SMauro Carvalho Chehab            # If we're in a literal block, see if we should drop out of it.
3141d6fea64SMauro Carvalho Chehab            # Otherwise, pass the line straight through unmunged.
3151d6fea64SMauro Carvalho Chehab            if in_literal:
3161d6fea64SMauro Carvalho Chehab                if line.strip():  # If the line is not blank
3171d6fea64SMauro Carvalho Chehab                    # If this is the first non-blank line in a literal block,
3181d6fea64SMauro Carvalho Chehab                    # figure out the proper indent.
3191d6fea64SMauro Carvalho Chehab                    if not litprefix:
32004a383ceSMauro Carvalho Chehab                        r = KernRe(r'^(\s*)')
3211d6fea64SMauro Carvalho Chehab                        if r.match(line):
3221d6fea64SMauro Carvalho Chehab                            litprefix = '^' + r.group(1)
3231d6fea64SMauro Carvalho Chehab                        else:
3241d6fea64SMauro Carvalho Chehab                            litprefix = ""
3251d6fea64SMauro Carvalho Chehab
3261d6fea64SMauro Carvalho Chehab                        output += line + "\n"
32704a383ceSMauro Carvalho Chehab                    elif not KernRe(litprefix).match(line):
3281d6fea64SMauro Carvalho Chehab                        in_literal = False
3291d6fea64SMauro Carvalho Chehab                    else:
3301d6fea64SMauro Carvalho Chehab                        output += line + "\n"
3311d6fea64SMauro Carvalho Chehab                else:
3321d6fea64SMauro Carvalho Chehab                    output += line + "\n"
3331d6fea64SMauro Carvalho Chehab
3341d6fea64SMauro Carvalho Chehab            # Not in a literal block (or just dropped out)
3351d6fea64SMauro Carvalho Chehab            if not in_literal:
3361d6fea64SMauro Carvalho Chehab                block += line + "\n"
3371d6fea64SMauro Carvalho Chehab                if self.sphinx_literal.match(line) or self.sphinx_cblock.match(line):
3381d6fea64SMauro Carvalho Chehab                    in_literal = True
3391d6fea64SMauro Carvalho Chehab                    litprefix = ""
3401d6fea64SMauro Carvalho Chehab                    output += self.highlight_block(block)
3411d6fea64SMauro Carvalho Chehab                    block = ""
3421d6fea64SMauro Carvalho Chehab
3431d6fea64SMauro Carvalho Chehab        # Handle any remaining block
3441d6fea64SMauro Carvalho Chehab        if block:
3451d6fea64SMauro Carvalho Chehab            output += self.highlight_block(block)
3461d6fea64SMauro Carvalho Chehab
3471d6fea64SMauro Carvalho Chehab        # Print the output with the line prefix
3481d6fea64SMauro Carvalho Chehab        for line in output.strip("\n").split("\n"):
3494fa5e411SMauro Carvalho Chehab            self.data += self.lineprefix + line + "\n"
3501d6fea64SMauro Carvalho Chehab
351408269aeSMauro Carvalho Chehab    def out_section(self, args, out_docblock=False):
3521d6fea64SMauro Carvalho Chehab        """
3531d6fea64SMauro Carvalho Chehab        Outputs a block section.
3541d6fea64SMauro Carvalho Chehab
3551d6fea64SMauro Carvalho Chehab        This could use some work; it's used to output the DOC: sections, and
3561d6fea64SMauro Carvalho Chehab        starts by putting out the name of the doc section itself, but that
3571d6fea64SMauro Carvalho Chehab        tends to duplicate a header already in the template file.
3581d6fea64SMauro Carvalho Chehab        """
3598d733875SJonathan Corbet        for section, text in args.sections.items():
3601d6fea64SMauro Carvalho Chehab            # Skip sections that are in the nosymbol_table
3611d6fea64SMauro Carvalho Chehab            if section in self.nosymbol:
3621d6fea64SMauro Carvalho Chehab                continue
3631d6fea64SMauro Carvalho Chehab
364408269aeSMauro Carvalho Chehab            if out_docblock:
3659235ec5eSMauro Carvalho Chehab                if not self.out_mode == self.OUTPUT_INCLUDE:
3664fa5e411SMauro Carvalho Chehab                    self.data += f".. _{section}:\n\n"
3679235ec5eSMauro Carvalho Chehab                    self.data += f'{self.lineprefix}**{section}**\n\n'
3689235ec5eSMauro Carvalho Chehab            else:
3694fa5e411SMauro Carvalho Chehab                self.data += f'{self.lineprefix}**{section}**\n\n'
3701d6fea64SMauro Carvalho Chehab
3718d733875SJonathan Corbet            self.print_lineno(args.section_start_lines.get(section, 0))
3728d733875SJonathan Corbet            self.output_highlight(text)
3734fa5e411SMauro Carvalho Chehab            self.data += "\n"
3744fa5e411SMauro Carvalho Chehab        self.data += "\n"
3751d6fea64SMauro Carvalho Chehab
3761d6fea64SMauro Carvalho Chehab    def out_doc(self, fname, name, args):
3779cbc2d3bSMauro Carvalho Chehab        if not self.check_doc(name, args):
3781d6fea64SMauro Carvalho Chehab            return
379408269aeSMauro Carvalho Chehab        self.out_section(args, out_docblock=True)
3801d6fea64SMauro Carvalho Chehab
3811d6fea64SMauro Carvalho Chehab    def out_function(self, fname, name, args):
3821d6fea64SMauro Carvalho Chehab
3831d6fea64SMauro Carvalho Chehab        oldprefix = self.lineprefix
3841d6fea64SMauro Carvalho Chehab        signature = ""
3851d6fea64SMauro Carvalho Chehab
3861d6fea64SMauro Carvalho Chehab        func_macro = args.get('func_macro', False)
3871d6fea64SMauro Carvalho Chehab        if func_macro:
388a0db2051SJonathan Corbet            signature = name
3891d6fea64SMauro Carvalho Chehab        else:
3901d6fea64SMauro Carvalho Chehab            if args.get('functiontype'):
3911d6fea64SMauro Carvalho Chehab                signature = args['functiontype'] + " "
392a0db2051SJonathan Corbet            signature += name + " ("
3931d6fea64SMauro Carvalho Chehab
394bd5628bfSJonathan Corbet        ln = args.declaration_start_line
3951d6fea64SMauro Carvalho Chehab        count = 0
396de6f7ac9SJonathan Corbet        for parameter in args.parameterlist:
3971d6fea64SMauro Carvalho Chehab            if count != 0:
3981d6fea64SMauro Carvalho Chehab                signature += ", "
3991d6fea64SMauro Carvalho Chehab            count += 1
400de6f7ac9SJonathan Corbet            dtype = args.parametertypes.get(parameter, "")
4011d6fea64SMauro Carvalho Chehab
4021d6fea64SMauro Carvalho Chehab            if function_pointer.search(dtype):
4031d6fea64SMauro Carvalho Chehab                signature += function_pointer.group(1) + parameter + function_pointer.group(3)
4041d6fea64SMauro Carvalho Chehab            else:
4051d6fea64SMauro Carvalho Chehab                signature += dtype
4061d6fea64SMauro Carvalho Chehab
4071d6fea64SMauro Carvalho Chehab        if not func_macro:
4081d6fea64SMauro Carvalho Chehab            signature += ")"
4091d6fea64SMauro Carvalho Chehab
410c3597ab2SMauro Carvalho Chehab        self.print_lineno(ln)
4111d6fea64SMauro Carvalho Chehab        if args.get('typedef') or not args.get('functiontype'):
412a0db2051SJonathan Corbet            self.data += f".. c:macro:: {name}\n\n"
4131d6fea64SMauro Carvalho Chehab
4141d6fea64SMauro Carvalho Chehab            if args.get('typedef'):
4154fa5e411SMauro Carvalho Chehab                self.data += "   **Typedef**: "
4161d6fea64SMauro Carvalho Chehab                self.lineprefix = ""
4171d6fea64SMauro Carvalho Chehab                self.output_highlight(args.get('purpose', ""))
4184fa5e411SMauro Carvalho Chehab                self.data += "\n\n**Syntax**\n\n"
4194fa5e411SMauro Carvalho Chehab                self.data += f"  ``{signature}``\n\n"
4201d6fea64SMauro Carvalho Chehab            else:
4214fa5e411SMauro Carvalho Chehab                self.data += f"``{signature}``\n\n"
4221d6fea64SMauro Carvalho Chehab        else:
4234fa5e411SMauro Carvalho Chehab            self.data += f".. c:function:: {signature}\n\n"
4241d6fea64SMauro Carvalho Chehab
4251d6fea64SMauro Carvalho Chehab        if not args.get('typedef'):
4261d6fea64SMauro Carvalho Chehab            self.print_lineno(ln)
4271d6fea64SMauro Carvalho Chehab            self.lineprefix = "   "
4281d6fea64SMauro Carvalho Chehab            self.output_highlight(args.get('purpose', ""))
4294fa5e411SMauro Carvalho Chehab            self.data += "\n"
4301d6fea64SMauro Carvalho Chehab
4311d6fea64SMauro Carvalho Chehab        # Put descriptive text into a container (HTML <div>) to help set
4321d6fea64SMauro Carvalho Chehab        # function prototypes apart
4331d6fea64SMauro Carvalho Chehab        self.lineprefix = "  "
4341d6fea64SMauro Carvalho Chehab
435de6f7ac9SJonathan Corbet        if args.parameterlist:
4364fa5e411SMauro Carvalho Chehab            self.data += ".. container:: kernelindent\n\n"
4374fa5e411SMauro Carvalho Chehab            self.data += f"{self.lineprefix}**Parameters**\n\n"
4381d6fea64SMauro Carvalho Chehab
439de6f7ac9SJonathan Corbet        for parameter in args.parameterlist:
44004a383ceSMauro Carvalho Chehab            parameter_name = KernRe(r'\[.*').sub('', parameter)
441de6f7ac9SJonathan Corbet            dtype = args.parametertypes.get(parameter, "")
4421d6fea64SMauro Carvalho Chehab
4431d6fea64SMauro Carvalho Chehab            if dtype:
4444fa5e411SMauro Carvalho Chehab                self.data += f"{self.lineprefix}``{dtype}``\n"
4451d6fea64SMauro Carvalho Chehab            else:
4464fa5e411SMauro Carvalho Chehab                self.data += f"{self.lineprefix}``{parameter}``\n"
4471d6fea64SMauro Carvalho Chehab
448de6f7ac9SJonathan Corbet            self.print_lineno(args.parameterdesc_start_lines.get(parameter_name, 0))
4491d6fea64SMauro Carvalho Chehab
4501d6fea64SMauro Carvalho Chehab            self.lineprefix = "    "
451de6f7ac9SJonathan Corbet            if parameter_name in args.parameterdescs and \
452de6f7ac9SJonathan Corbet               args.parameterdescs[parameter_name] != KernelDoc.undescribed:
4531d6fea64SMauro Carvalho Chehab
454de6f7ac9SJonathan Corbet                self.output_highlight(args.parameterdescs[parameter_name])
4554fa5e411SMauro Carvalho Chehab                self.data += "\n"
4561d6fea64SMauro Carvalho Chehab            else:
4574fa5e411SMauro Carvalho Chehab                self.data += f"{self.lineprefix}*undescribed*\n\n"
4581d6fea64SMauro Carvalho Chehab            self.lineprefix = "  "
4591d6fea64SMauro Carvalho Chehab
4601d6fea64SMauro Carvalho Chehab        self.out_section(args)
4611d6fea64SMauro Carvalho Chehab        self.lineprefix = oldprefix
4621d6fea64SMauro Carvalho Chehab
4631d6fea64SMauro Carvalho Chehab    def out_enum(self, fname, name, args):
4641d6fea64SMauro Carvalho Chehab
4651d6fea64SMauro Carvalho Chehab        oldprefix = self.lineprefix
466bd5628bfSJonathan Corbet        ln = args.declaration_start_line
4671d6fea64SMauro Carvalho Chehab
4684fa5e411SMauro Carvalho Chehab        self.data += f"\n\n.. c:enum:: {name}\n\n"
4691d6fea64SMauro Carvalho Chehab
4701d6fea64SMauro Carvalho Chehab        self.print_lineno(ln)
4711d6fea64SMauro Carvalho Chehab        self.lineprefix = "  "
4721d6fea64SMauro Carvalho Chehab        self.output_highlight(args.get('purpose', ''))
4734fa5e411SMauro Carvalho Chehab        self.data += "\n"
4741d6fea64SMauro Carvalho Chehab
4754fa5e411SMauro Carvalho Chehab        self.data += ".. container:: kernelindent\n\n"
4761d6fea64SMauro Carvalho Chehab        outer = self.lineprefix + "  "
4771d6fea64SMauro Carvalho Chehab        self.lineprefix = outer + "  "
4784fa5e411SMauro Carvalho Chehab        self.data += f"{outer}**Constants**\n\n"
4791d6fea64SMauro Carvalho Chehab
480de6f7ac9SJonathan Corbet        for parameter in args.parameterlist:
4814fa5e411SMauro Carvalho Chehab            self.data += f"{outer}``{parameter}``\n"
4821d6fea64SMauro Carvalho Chehab
483de6f7ac9SJonathan Corbet            if args.parameterdescs.get(parameter, '') != KernelDoc.undescribed:
484de6f7ac9SJonathan Corbet                self.output_highlight(args.parameterdescs[parameter])
4851d6fea64SMauro Carvalho Chehab            else:
4864fa5e411SMauro Carvalho Chehab                self.data += f"{self.lineprefix}*undescribed*\n\n"
4874fa5e411SMauro Carvalho Chehab            self.data += "\n"
4881d6fea64SMauro Carvalho Chehab
4891d6fea64SMauro Carvalho Chehab        self.lineprefix = oldprefix
4901d6fea64SMauro Carvalho Chehab        self.out_section(args)
4911d6fea64SMauro Carvalho Chehab
4921045ec38SMauro Carvalho Chehab    def out_var(self, fname, name, args):
4931045ec38SMauro Carvalho Chehab        oldprefix = self.lineprefix
4941045ec38SMauro Carvalho Chehab        ln = args.declaration_start_line
4951045ec38SMauro Carvalho Chehab        full_proto = args.other_stuff["full_proto"]
4961045ec38SMauro Carvalho Chehab
4971045ec38SMauro Carvalho Chehab        self.lineprefix = "  "
4981045ec38SMauro Carvalho Chehab
499bdd1cf87SMauro Carvalho Chehab        self.data += f"\n\n.. c:macro:: {name}\n\n{self.lineprefix}``{full_proto}``\n\n"
5001045ec38SMauro Carvalho Chehab
5011045ec38SMauro Carvalho Chehab        self.print_lineno(ln)
5021045ec38SMauro Carvalho Chehab        self.output_highlight(args.get('purpose', ''))
5031045ec38SMauro Carvalho Chehab        self.data += "\n"
5041045ec38SMauro Carvalho Chehab
5051045ec38SMauro Carvalho Chehab        if args.other_stuff["default_val"]:
5061045ec38SMauro Carvalho Chehab            self.data += f'{self.lineprefix}**Initialization**\n\n'
5071045ec38SMauro Carvalho Chehab            self.output_highlight(f'default: ``{args.other_stuff["default_val"]}``')
5081045ec38SMauro Carvalho Chehab
5091045ec38SMauro Carvalho Chehab        self.out_section(args)
5101045ec38SMauro Carvalho Chehab
5111d6fea64SMauro Carvalho Chehab    def out_typedef(self, fname, name, args):
5121d6fea64SMauro Carvalho Chehab
5131d6fea64SMauro Carvalho Chehab        oldprefix = self.lineprefix
514bd5628bfSJonathan Corbet        ln = args.declaration_start_line
5151d6fea64SMauro Carvalho Chehab
5164fa5e411SMauro Carvalho Chehab        self.data += f"\n\n.. c:type:: {name}\n\n"
5171d6fea64SMauro Carvalho Chehab
5181d6fea64SMauro Carvalho Chehab        self.print_lineno(ln)
5191d6fea64SMauro Carvalho Chehab        self.lineprefix = "   "
5201d6fea64SMauro Carvalho Chehab
5211d6fea64SMauro Carvalho Chehab        self.output_highlight(args.get('purpose', ''))
5221d6fea64SMauro Carvalho Chehab
5234fa5e411SMauro Carvalho Chehab        self.data += "\n"
5241d6fea64SMauro Carvalho Chehab
5251d6fea64SMauro Carvalho Chehab        self.lineprefix = oldprefix
5261d6fea64SMauro Carvalho Chehab        self.out_section(args)
5271d6fea64SMauro Carvalho Chehab
5281d6fea64SMauro Carvalho Chehab    def out_struct(self, fname, name, args):
5291d6fea64SMauro Carvalho Chehab
5301d6fea64SMauro Carvalho Chehab        purpose = args.get('purpose', "")
5311d6fea64SMauro Carvalho Chehab        declaration = args.get('definition', "")
532bd5628bfSJonathan Corbet        dtype = args.type
533bd5628bfSJonathan Corbet        ln = args.declaration_start_line
5341d6fea64SMauro Carvalho Chehab
5354fa5e411SMauro Carvalho Chehab        self.data += f"\n\n.. c:{dtype}:: {name}\n\n"
5361d6fea64SMauro Carvalho Chehab
5371d6fea64SMauro Carvalho Chehab        self.print_lineno(ln)
5381d6fea64SMauro Carvalho Chehab
5391d6fea64SMauro Carvalho Chehab        oldprefix = self.lineprefix
5401d6fea64SMauro Carvalho Chehab        self.lineprefix += "  "
5411d6fea64SMauro Carvalho Chehab
5421d6fea64SMauro Carvalho Chehab        self.output_highlight(purpose)
5434fa5e411SMauro Carvalho Chehab        self.data += "\n"
5441d6fea64SMauro Carvalho Chehab
5454fa5e411SMauro Carvalho Chehab        self.data += ".. container:: kernelindent\n\n"
5464fa5e411SMauro Carvalho Chehab        self.data += f"{self.lineprefix}**Definition**::\n\n"
5471d6fea64SMauro Carvalho Chehab
5481d6fea64SMauro Carvalho Chehab        self.lineprefix = self.lineprefix + "  "
5491d6fea64SMauro Carvalho Chehab
5501d6fea64SMauro Carvalho Chehab        declaration = declaration.replace("\t", self.lineprefix)
5511d6fea64SMauro Carvalho Chehab
5524fa5e411SMauro Carvalho Chehab        self.data += f"{self.lineprefix}{dtype} {name}" + ' {' + "\n"
5534fa5e411SMauro Carvalho Chehab        self.data += f"{declaration}{self.lineprefix}" + "};\n\n"
5541d6fea64SMauro Carvalho Chehab
5551d6fea64SMauro Carvalho Chehab        self.lineprefix = "  "
5564fa5e411SMauro Carvalho Chehab        self.data += f"{self.lineprefix}**Members**\n\n"
557de6f7ac9SJonathan Corbet        for parameter in args.parameterlist:
5581d6fea64SMauro Carvalho Chehab            if not parameter or parameter.startswith("#"):
5591d6fea64SMauro Carvalho Chehab                continue
5601d6fea64SMauro Carvalho Chehab
5611d6fea64SMauro Carvalho Chehab            parameter_name = parameter.split("[", maxsplit=1)[0]
5621d6fea64SMauro Carvalho Chehab
563de6f7ac9SJonathan Corbet            if args.parameterdescs.get(parameter_name) == KernelDoc.undescribed:
5641d6fea64SMauro Carvalho Chehab                continue
5651d6fea64SMauro Carvalho Chehab
566de6f7ac9SJonathan Corbet            self.print_lineno(args.parameterdesc_start_lines.get(parameter_name, 0))
5671d6fea64SMauro Carvalho Chehab
5684fa5e411SMauro Carvalho Chehab            self.data += f"{self.lineprefix}``{parameter}``\n"
5691d6fea64SMauro Carvalho Chehab
5701d6fea64SMauro Carvalho Chehab            self.lineprefix = "    "
571de6f7ac9SJonathan Corbet            self.output_highlight(args.parameterdescs[parameter_name])
5721d6fea64SMauro Carvalho Chehab            self.lineprefix = "  "
5731d6fea64SMauro Carvalho Chehab
5744fa5e411SMauro Carvalho Chehab            self.data += "\n"
5751d6fea64SMauro Carvalho Chehab
5764fa5e411SMauro Carvalho Chehab        self.data += "\n"
5771d6fea64SMauro Carvalho Chehab
5781d6fea64SMauro Carvalho Chehab        self.lineprefix = oldprefix
5791d6fea64SMauro Carvalho Chehab        self.out_section(args)
5801d6fea64SMauro Carvalho Chehab
5811d6fea64SMauro Carvalho Chehab
5821d6fea64SMauro Carvalho Chehabclass ManFormat(OutputFormat):
583*245f1ab2SMauro Carvalho Chehab    """Consts and functions used by man pages output."""
5841d6fea64SMauro Carvalho Chehab
5851d6fea64SMauro Carvalho Chehab    highlights = (
5861d6fea64SMauro Carvalho Chehab        (type_constant, r"\1"),
5871d6fea64SMauro Carvalho Chehab        (type_constant2, r"\1"),
5881d6fea64SMauro Carvalho Chehab        (type_func, r"\\fB\1\\fP"),
5891d6fea64SMauro Carvalho Chehab        (type_enum, r"\\fI\1\\fP"),
5901d6fea64SMauro Carvalho Chehab        (type_struct, r"\\fI\1\\fP"),
5911d6fea64SMauro Carvalho Chehab        (type_typedef, r"\\fI\1\\fP"),
5921d6fea64SMauro Carvalho Chehab        (type_union, r"\\fI\1\\fP"),
5931d6fea64SMauro Carvalho Chehab        (type_param, r"\\fI\1\\fP"),
5941d6fea64SMauro Carvalho Chehab        (type_param_ref, r"\\fI\1\2\\fP"),
5951d6fea64SMauro Carvalho Chehab        (type_member, r"\\fI\1\2\3\\fP"),
5961d6fea64SMauro Carvalho Chehab        (type_fallback, r"\\fI\1\\fP")
5971d6fea64SMauro Carvalho Chehab    )
5981d6fea64SMauro Carvalho Chehab    blankline = ""
5991d6fea64SMauro Carvalho Chehab
600*245f1ab2SMauro Carvalho Chehab    #: Allowed timestamp formats.
60191d00bd5SMauro Carvalho Chehab    date_formats = [
60291d00bd5SMauro Carvalho Chehab        "%a %b %d %H:%M:%S %Z %Y",
60391d00bd5SMauro Carvalho Chehab        "%a %b %d %H:%M:%S %Y",
60491d00bd5SMauro Carvalho Chehab        "%Y-%m-%d",
60591d00bd5SMauro Carvalho Chehab        "%b %d %Y",
60691d00bd5SMauro Carvalho Chehab        "%B %d %Y",
60791d00bd5SMauro Carvalho Chehab        "%m %d %Y",
60891d00bd5SMauro Carvalho Chehab    ]
60991d00bd5SMauro Carvalho Chehab
6102ab867a4SMauro Carvalho Chehab    def __init__(self, modulename):
6111d6fea64SMauro Carvalho Chehab        """
6121d6fea64SMauro Carvalho Chehab        Creates class variables.
6131d6fea64SMauro Carvalho Chehab
6141d6fea64SMauro Carvalho Chehab        Not really mandatory, but it is a good coding style and makes
6151d6fea64SMauro Carvalho Chehab        pylint happy.
6161d6fea64SMauro Carvalho Chehab        """
6171d6fea64SMauro Carvalho Chehab
6181d6fea64SMauro Carvalho Chehab        super().__init__()
6192ab867a4SMauro Carvalho Chehab        self.modulename = modulename
620104e0a68SMauro Carvalho Chehab        self.symbols = []
6211d6fea64SMauro Carvalho Chehab
62291d00bd5SMauro Carvalho Chehab        dt = None
62391d00bd5SMauro Carvalho Chehab        tstamp = os.environ.get("KBUILD_BUILD_TIMESTAMP")
62491d00bd5SMauro Carvalho Chehab        if tstamp:
62591d00bd5SMauro Carvalho Chehab            for fmt in self.date_formats:
62691d00bd5SMauro Carvalho Chehab                try:
62791d00bd5SMauro Carvalho Chehab                    dt = datetime.strptime(tstamp, fmt)
62891d00bd5SMauro Carvalho Chehab                    break
62991d00bd5SMauro Carvalho Chehab                except ValueError:
63091d00bd5SMauro Carvalho Chehab                    pass
63191d00bd5SMauro Carvalho Chehab
63291d00bd5SMauro Carvalho Chehab        if not dt:
6331d6fea64SMauro Carvalho Chehab            dt = datetime.now()
6341d6fea64SMauro Carvalho Chehab
6351d6fea64SMauro Carvalho Chehab        self.man_date = dt.strftime("%B %Y")
6361d6fea64SMauro Carvalho Chehab
637104e0a68SMauro Carvalho Chehab    def arg_name(self, args, name):
638104e0a68SMauro Carvalho Chehab        """
639104e0a68SMauro Carvalho Chehab        Return the name that will be used for the man page.
640104e0a68SMauro Carvalho Chehab
641104e0a68SMauro Carvalho Chehab        As we may have the same name on different namespaces,
642104e0a68SMauro Carvalho Chehab        prepend the data type for all types except functions and typedefs.
643104e0a68SMauro Carvalho Chehab
644104e0a68SMauro Carvalho Chehab        The doc section is special: it uses the modulename.
645104e0a68SMauro Carvalho Chehab        """
646104e0a68SMauro Carvalho Chehab
647104e0a68SMauro Carvalho Chehab        dtype = args.type
648104e0a68SMauro Carvalho Chehab
649104e0a68SMauro Carvalho Chehab        if dtype == "doc":
650104e0a68SMauro Carvalho Chehab            return self.modulename
651104e0a68SMauro Carvalho Chehab
652104e0a68SMauro Carvalho Chehab        if dtype in ["function", "typedef"]:
653104e0a68SMauro Carvalho Chehab            return name
654104e0a68SMauro Carvalho Chehab
655104e0a68SMauro Carvalho Chehab        return f"{dtype} {name}"
656104e0a68SMauro Carvalho Chehab
657104e0a68SMauro Carvalho Chehab    def set_symbols(self, symbols):
658104e0a68SMauro Carvalho Chehab        """
659104e0a68SMauro Carvalho Chehab        Get a list of all symbols from kernel_doc.
660104e0a68SMauro Carvalho Chehab
661104e0a68SMauro Carvalho Chehab        Man pages will uses it to add a SEE ALSO section with other
662104e0a68SMauro Carvalho Chehab        symbols at the same file.
663104e0a68SMauro Carvalho Chehab        """
664104e0a68SMauro Carvalho Chehab        self.symbols = symbols
665104e0a68SMauro Carvalho Chehab
666104e0a68SMauro Carvalho Chehab    def out_tail(self, fname, name, args):
667*245f1ab2SMauro Carvalho Chehab        """Adds a tail for all man pages."""
668104e0a68SMauro Carvalho Chehab
669104e0a68SMauro Carvalho Chehab        # SEE ALSO section
6702bd22194SMauro Carvalho Chehab        self.data += f'.SH "SEE ALSO"' + "\n.PP\n"
6712bd22194SMauro Carvalho Chehab        self.data += (f"Kernel file \\fB{args.fname}\\fR\n")
672104e0a68SMauro Carvalho Chehab        if len(self.symbols) >= 2:
673104e0a68SMauro Carvalho Chehab            cur_name = self.arg_name(args, name)
674104e0a68SMauro Carvalho Chehab
675104e0a68SMauro Carvalho Chehab            related = []
676104e0a68SMauro Carvalho Chehab            for arg in self.symbols:
677104e0a68SMauro Carvalho Chehab                out_name = self.arg_name(arg, arg.name)
678104e0a68SMauro Carvalho Chehab
679104e0a68SMauro Carvalho Chehab                if cur_name == out_name:
680104e0a68SMauro Carvalho Chehab                    continue
681104e0a68SMauro Carvalho Chehab
682104e0a68SMauro Carvalho Chehab                related.append(f"\\fB{out_name}\\fR(9)")
683104e0a68SMauro Carvalho Chehab
684104e0a68SMauro Carvalho Chehab            self.data += ",\n".join(related) + "\n"
685104e0a68SMauro Carvalho Chehab
686104e0a68SMauro Carvalho Chehab        # TODO: does it make sense to add other sections? Maybe
687104e0a68SMauro Carvalho Chehab        # REPORTING ISSUES? LICENSE?
688104e0a68SMauro Carvalho Chehab
689104e0a68SMauro Carvalho Chehab    def msg(self, fname, name, args):
690104e0a68SMauro Carvalho Chehab        """
691104e0a68SMauro Carvalho Chehab        Handles a single entry from kernel-doc parser.
692104e0a68SMauro Carvalho Chehab
693104e0a68SMauro Carvalho Chehab        Add a tail at the end of man pages output.
694104e0a68SMauro Carvalho Chehab        """
695104e0a68SMauro Carvalho Chehab        super().msg(fname, name, args)
696104e0a68SMauro Carvalho Chehab        self.out_tail(fname, name, args)
697104e0a68SMauro Carvalho Chehab
698104e0a68SMauro Carvalho Chehab        return self.data
699104e0a68SMauro Carvalho Chehab
7001d6fea64SMauro Carvalho Chehab    def output_highlight(self, block):
701485f6f79SMauro Carvalho Chehab        """
702485f6f79SMauro Carvalho Chehab        Outputs a C symbol that may require being highlighted with
703*245f1ab2SMauro Carvalho Chehab        self.highlights variable using troff syntax.
704485f6f79SMauro Carvalho Chehab        """
7051d6fea64SMauro Carvalho Chehab
7061d6fea64SMauro Carvalho Chehab        contents = self.highlight_block(block)
7071d6fea64SMauro Carvalho Chehab
7081d6fea64SMauro Carvalho Chehab        if isinstance(contents, list):
7091d6fea64SMauro Carvalho Chehab            contents = "\n".join(contents)
7101d6fea64SMauro Carvalho Chehab
7111d6fea64SMauro Carvalho Chehab        for line in contents.strip("\n").split("\n"):
71204a383ceSMauro Carvalho Chehab            line = KernRe(r"^\s*").sub("", line)
713408269aeSMauro Carvalho Chehab            if not line:
714408269aeSMauro Carvalho Chehab                continue
7151d6fea64SMauro Carvalho Chehab
716408269aeSMauro Carvalho Chehab            if line[0] == ".":
7174fa5e411SMauro Carvalho Chehab                self.data += "\\&" + line + "\n"
7181d6fea64SMauro Carvalho Chehab            else:
7194fa5e411SMauro Carvalho Chehab                self.data += line + "\n"
7201d6fea64SMauro Carvalho Chehab
7211d6fea64SMauro Carvalho Chehab    def out_doc(self, fname, name, args):
7229cbc2d3bSMauro Carvalho Chehab        if not self.check_doc(name, args):
723408269aeSMauro Carvalho Chehab            return
724408269aeSMauro Carvalho Chehab
725104e0a68SMauro Carvalho Chehab        out_name = self.arg_name(args, name)
726104e0a68SMauro Carvalho Chehab
727104e0a68SMauro Carvalho Chehab        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
7281d6fea64SMauro Carvalho Chehab
7298d733875SJonathan Corbet        for section, text in args.sections.items():
7304fa5e411SMauro Carvalho Chehab            self.data += f'.SH "{section}"' + "\n"
7318d733875SJonathan Corbet            self.output_highlight(text)
7321d6fea64SMauro Carvalho Chehab
7331d6fea64SMauro Carvalho Chehab    def out_function(self, fname, name, args):
7341d6fea64SMauro Carvalho Chehab
735104e0a68SMauro Carvalho Chehab        out_name = self.arg_name(args, name)
736104e0a68SMauro Carvalho Chehab
737104e0a68SMauro Carvalho Chehab        self.data += f'.TH "{name}" 9 "{out_name}" "{self.man_date}" "Kernel Hacker\'s Manual" LINUX' + "\n"
7381d6fea64SMauro Carvalho Chehab
7394fa5e411SMauro Carvalho Chehab        self.data += ".SH NAME\n"
740a0db2051SJonathan Corbet        self.data += f"{name} \\- {args['purpose']}\n"
7411d6fea64SMauro Carvalho Chehab
7424fa5e411SMauro Carvalho Chehab        self.data += ".SH SYNOPSIS\n"
7431d6fea64SMauro Carvalho Chehab        if args.get('functiontype', ''):
744a0db2051SJonathan Corbet            self.data += f'.B "{args["functiontype"]}" {name}' + "\n"
7451d6fea64SMauro Carvalho Chehab        else:
746a0db2051SJonathan Corbet            self.data += f'.B "{name}' + "\n"
7471d6fea64SMauro Carvalho Chehab
7481d6fea64SMauro Carvalho Chehab        count = 0
7491d6fea64SMauro Carvalho Chehab        parenth = "("
7501d6fea64SMauro Carvalho Chehab        post = ","
7511d6fea64SMauro Carvalho Chehab
752de6f7ac9SJonathan Corbet        for parameter in args.parameterlist:
753de6f7ac9SJonathan Corbet            if count == len(args.parameterlist) - 1:
7541d6fea64SMauro Carvalho Chehab                post = ");"
7551d6fea64SMauro Carvalho Chehab
756de6f7ac9SJonathan Corbet            dtype = args.parametertypes.get(parameter, "")
7571d6fea64SMauro Carvalho Chehab            if function_pointer.match(dtype):
7581d6fea64SMauro Carvalho Chehab                # Pointer-to-function
7594fa5e411SMauro Carvalho Chehab                self.data += f'".BI "{parenth}{function_pointer.group(1)}" " ") ({function_pointer.group(2)}){post}"' + "\n"
7601d6fea64SMauro Carvalho Chehab            else:
76104a383ceSMauro Carvalho Chehab                dtype = KernRe(r'([^\*])$').sub(r'\1 ', dtype)
7621d6fea64SMauro Carvalho Chehab
7634fa5e411SMauro Carvalho Chehab                self.data += f'.BI "{parenth}{dtype}"  "{post}"' + "\n"
7641d6fea64SMauro Carvalho Chehab            count += 1
7651d6fea64SMauro Carvalho Chehab            parenth = ""
7661d6fea64SMauro Carvalho Chehab
767de6f7ac9SJonathan Corbet        if args.parameterlist:
7684fa5e411SMauro Carvalho Chehab            self.data += ".SH ARGUMENTS\n"
7691d6fea64SMauro Carvalho Chehab
770de6f7ac9SJonathan Corbet        for parameter in args.parameterlist:
7711d6fea64SMauro Carvalho Chehab            parameter_name = re.sub(r'\[.*', '', parameter)
7721d6fea64SMauro Carvalho Chehab
7734fa5e411SMauro Carvalho Chehab            self.data += f'.IP "{parameter}" 12' + "\n"
774de6f7ac9SJonathan Corbet            self.output_highlight(args.parameterdescs.get(parameter_name, ""))
7751d6fea64SMauro Carvalho Chehab
7768d733875SJonathan Corbet        for section, text in args.sections.items():
7774fa5e411SMauro Carvalho Chehab            self.data += f'.SH "{section.upper()}"' + "\n"
7788d733875SJonathan Corbet            self.output_highlight(text)
7791d6fea64SMauro Carvalho Chehab
7801d6fea64SMauro Carvalho Chehab    def out_enum(self, fname, name, args):
781104e0a68SMauro Carvalho Chehab        out_name = self.arg_name(args, name)
782104e0a68SMauro Carvalho Chehab
783104e0a68SMauro Carvalho Chehab        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
7841d6fea64SMauro Carvalho Chehab
7854fa5e411SMauro Carvalho Chehab        self.data += ".SH NAME\n"
786a0db2051SJonathan Corbet        self.data += f"enum {name} \\- {args['purpose']}\n"
7871d6fea64SMauro Carvalho Chehab
7884fa5e411SMauro Carvalho Chehab        self.data += ".SH SYNOPSIS\n"
789a0db2051SJonathan Corbet        self.data += f"enum {name}" + " {\n"
7901d6fea64SMauro Carvalho Chehab
7911d6fea64SMauro Carvalho Chehab        count = 0
792de6f7ac9SJonathan Corbet        for parameter in args.parameterlist:
7934fa5e411SMauro Carvalho Chehab            self.data += f'.br\n.BI "    {parameter}"' + "\n"
794de6f7ac9SJonathan Corbet            if count == len(args.parameterlist) - 1:
7954fa5e411SMauro Carvalho Chehab                self.data += "\n};\n"
7961d6fea64SMauro Carvalho Chehab            else:
7974fa5e411SMauro Carvalho Chehab                self.data += ", \n.br\n"
7981d6fea64SMauro Carvalho Chehab
7991d6fea64SMauro Carvalho Chehab            count += 1
8001d6fea64SMauro Carvalho Chehab
8014fa5e411SMauro Carvalho Chehab        self.data += ".SH Constants\n"
8021d6fea64SMauro Carvalho Chehab
803de6f7ac9SJonathan Corbet        for parameter in args.parameterlist:
80404a383ceSMauro Carvalho Chehab            parameter_name = KernRe(r'\[.*').sub('', parameter)
8054fa5e411SMauro Carvalho Chehab            self.data += f'.IP "{parameter}" 12' + "\n"
806de6f7ac9SJonathan Corbet            self.output_highlight(args.parameterdescs.get(parameter_name, ""))
8071d6fea64SMauro Carvalho Chehab
8088d733875SJonathan Corbet        for section, text in args.sections.items():
8094fa5e411SMauro Carvalho Chehab            self.data += f'.SH "{section}"' + "\n"
8108d733875SJonathan Corbet            self.output_highlight(text)
8111d6fea64SMauro Carvalho Chehab
8121045ec38SMauro Carvalho Chehab    def out_var(self, fname, name, args):
8131045ec38SMauro Carvalho Chehab        out_name = self.arg_name(args, name)
8141045ec38SMauro Carvalho Chehab        full_proto = args.other_stuff["full_proto"]
8151045ec38SMauro Carvalho Chehab
8161045ec38SMauro Carvalho Chehab        self.data += f'.TH "{self.modulename}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
8171045ec38SMauro Carvalho Chehab
8181045ec38SMauro Carvalho Chehab        self.data += ".SH NAME\n"
819bdd1cf87SMauro Carvalho Chehab        self.data += f"{name} \\- {args['purpose']}\n"
8201045ec38SMauro Carvalho Chehab
8211045ec38SMauro Carvalho Chehab        self.data += ".SH SYNOPSIS\n"
8221045ec38SMauro Carvalho Chehab        self.data += f"{full_proto}\n"
8231045ec38SMauro Carvalho Chehab
8241045ec38SMauro Carvalho Chehab        if args.other_stuff["default_val"]:
8251045ec38SMauro Carvalho Chehab            self.data += f'.SH "Initialization"' + "\n"
8261045ec38SMauro Carvalho Chehab            self.output_highlight(f'default: {args.other_stuff["default_val"]}')
8271045ec38SMauro Carvalho Chehab
8281045ec38SMauro Carvalho Chehab        for section, text in args.sections.items():
8291045ec38SMauro Carvalho Chehab            self.data += f'.SH "{section}"' + "\n"
8301045ec38SMauro Carvalho Chehab            self.output_highlight(text)
8311045ec38SMauro Carvalho Chehab
8321d6fea64SMauro Carvalho Chehab    def out_typedef(self, fname, name, args):
8332ab867a4SMauro Carvalho Chehab        module = self.modulename
8341d6fea64SMauro Carvalho Chehab        purpose = args.get('purpose')
835104e0a68SMauro Carvalho Chehab        out_name = self.arg_name(args, name)
8361d6fea64SMauro Carvalho Chehab
837104e0a68SMauro Carvalho Chehab        self.data += f'.TH "{module}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
8381d6fea64SMauro Carvalho Chehab
8394fa5e411SMauro Carvalho Chehab        self.data += ".SH NAME\n"
840a0db2051SJonathan Corbet        self.data += f"typedef {name} \\- {purpose}\n"
8411d6fea64SMauro Carvalho Chehab
8428d733875SJonathan Corbet        for section, text in args.sections.items():
8434fa5e411SMauro Carvalho Chehab            self.data += f'.SH "{section}"' + "\n"
8448d733875SJonathan Corbet            self.output_highlight(text)
8451d6fea64SMauro Carvalho Chehab
8461d6fea64SMauro Carvalho Chehab    def out_struct(self, fname, name, args):
8472ab867a4SMauro Carvalho Chehab        module = self.modulename
8481d6fea64SMauro Carvalho Chehab        purpose = args.get('purpose')
8491d6fea64SMauro Carvalho Chehab        definition = args.get('definition')
850104e0a68SMauro Carvalho Chehab        out_name = self.arg_name(args, name)
8511d6fea64SMauro Carvalho Chehab
852104e0a68SMauro Carvalho Chehab        self.data += f'.TH "{module}" 9 "{out_name}" "{self.man_date}" "API Manual" LINUX' + "\n"
8531d6fea64SMauro Carvalho Chehab
8544fa5e411SMauro Carvalho Chehab        self.data += ".SH NAME\n"
855a0db2051SJonathan Corbet        self.data += f"{args.type} {name} \\- {purpose}\n"
8561d6fea64SMauro Carvalho Chehab
8571d6fea64SMauro Carvalho Chehab        # Replace tabs with two spaces and handle newlines
8581d6fea64SMauro Carvalho Chehab        declaration = definition.replace("\t", "  ")
85904a383ceSMauro Carvalho Chehab        declaration = KernRe(r"\n").sub('"\n.br\n.BI "', declaration)
8601d6fea64SMauro Carvalho Chehab
8614fa5e411SMauro Carvalho Chehab        self.data += ".SH SYNOPSIS\n"
862a0db2051SJonathan Corbet        self.data += f"{args.type} {name} " + "{" + "\n.br\n"
8634fa5e411SMauro Carvalho Chehab        self.data += f'.BI "{declaration}\n' + "};\n.br\n\n"
8641d6fea64SMauro Carvalho Chehab
8654fa5e411SMauro Carvalho Chehab        self.data += ".SH Members\n"
866de6f7ac9SJonathan Corbet        for parameter in args.parameterlist:
8671d6fea64SMauro Carvalho Chehab            if parameter.startswith("#"):
8681d6fea64SMauro Carvalho Chehab                continue
8691d6fea64SMauro Carvalho Chehab
8701d6fea64SMauro Carvalho Chehab            parameter_name = re.sub(r"\[.*", "", parameter)
8711d6fea64SMauro Carvalho Chehab
872de6f7ac9SJonathan Corbet            if args.parameterdescs.get(parameter_name) == KernelDoc.undescribed:
8731d6fea64SMauro Carvalho Chehab                continue
8741d6fea64SMauro Carvalho Chehab
8754fa5e411SMauro Carvalho Chehab            self.data += f'.IP "{parameter}" 12' + "\n"
876de6f7ac9SJonathan Corbet            self.output_highlight(args.parameterdescs.get(parameter_name))
8771d6fea64SMauro Carvalho Chehab
8788d733875SJonathan Corbet        for section, text in args.sections.items():
8794fa5e411SMauro Carvalho Chehab            self.data += f'.SH "{section}"' + "\n"
8808d733875SJonathan Corbet            self.output_highlight(text)
881