1160 lines · 33.8 KB · Python
RawDownload
        for parameter in args.parameterlist:            self.data += f"{outer}``{parameter}``\n"             if args.parameterdescs.get(parameter, '') != KernelDoc.undescribed:                self.output_highlight(args.parameterdescs[parameter])            else:                self.data += f"{self.lineprefix}*undescribed*\n\n"            self.data += "\n"         self.lineprefix = oldprefix        self.out_section(args)     def out_var(self, fname, name, args):        oldprefix = self.lineprefix        ln = args.declaration_start_line        full_proto = args.other_stuff.get("full_proto")        if not full_proto:            raise KeyError(f"Can't find full proto for {name} variable")         self.lineprefix = "  "         self.data += f"\n\n.. c:macro:: {name}\n\n{self.lineprefix}``{full_proto}``\n\n"         self.print_lineno(ln)        self.output_highlight(args.get('purpose', ''))        self.data += "\n"         if args.other_stuff["default_val"]:            self.data += f'{self.lineprefix}**Initialization**\n\n'            self.output_highlight(f'default: ``{args.other_stuff["default_val"]}``')         self.out_section(args)     def out_typedef(self, fname, name, args):         oldprefix = self.lineprefix        ln = args.declaration_start_line         self.data += f"\n\n.. c:type:: {name}\n\n"         self.print_lineno(ln)        self.lineprefix = "   "         self.output_highlight(args.get('purpose', ''))         self.data += "\n"         self.lineprefix = oldprefix        self.out_section(args)     def out_struct(self, fname, name, args):         purpose = args.get('purpose', "")        declaration = args.get('definition', "")        dtype = args.type        ln = args.declaration_start_line         self.data += f"\n\n.. c:{dtype}:: {name}\n\n"         self.print_lineno(ln)         oldprefix = self.lineprefix        self.lineprefix += "  "         self.output_highlight(purpose)        self.data += "\n"         self.data += ".. container:: kernelindent\n\n"        self.data += f"{self.lineprefix}**Definition**::\n\n"         self.lineprefix = self.lineprefix + "  "         declaration = declaration.replace("\t", self.lineprefix)         self.data += f"{self.lineprefix}{dtype} {name}" + ' {' + "\n"        self.data += f"{declaration}{self.lineprefix}" + "};\n\n"         self.lineprefix = "  "        self.data += f"{self.lineprefix}**Members**\n\n"        for parameter in args.parameterlist:            if not parameter or parameter.startswith("#"):                continue             parameter_name = parameter.split("[", maxsplit=1)[0]             if args.parameterdescs.get(parameter_name) == KernelDoc.undescribed:                continue             self.print_lineno(args.parameterdesc_start_lines.get(parameter_name, 0))             self.data += f"{self.lineprefix}``{parameter}``\n"             self.lineprefix = "    "            self.output_highlight(args.parameterdescs[parameter_name])            self.lineprefix = "  "             self.data += "\n"         self.data += "\n"         self.lineprefix = oldprefix        self.out_section(args)  class ManFormat(OutputFormat):    """    Consts and functions used by man pages output.     This class has one mandatory parameter and some optional ones, which    are needed to define the title header contents:     ``modulename``        Defines the module name to be used at the troff ``.TH`` output.         This argument is optional. If not specified, it will be filled        with the directory which contains the documented file.     ``section``        Usually a numeric value from 0 to 9, but man pages also accept        some strings like "p".         Defauls to ``9``     ``manual``        Defaults to ``Kernel API Manual``.     The above controls the output of teh corresponding fields on troff    title headers, which will be filled like this::         .TH "{name}" {section} "{date}" "{modulename}" "{manual}"     where ``name``` will match the API symbol name, and ``date`` will be    either the date where the Kernel was compiled or the current date    """     highlights = (        (type_constant, r"\1"),        (type_constant2, r"\1"),        (type_func, r"\\fB\1\\fP"),        (type_enum, r"\\fI\1\\fP"),        (type_struct, r"\\fI\1\\fP"),        (type_typedef, r"\\fI\1\\fP"),        (type_union, r"\\fI\1\\fP"),        (type_param, r"\\fI\1\\fP"),        (type_param_ref, r"\\fI\1\2\\fP"),        (type_member, r"\\fI\1\2\3\\fP"),        (type_fallback, r"\\fI\1\\fP")    )    blankline = ""     #: Allowed timestamp formats.    date_formats = [        "%a %b %d %H:%M:%S %Z %Y",        "%a %b %d %H:%M:%S %Y",        "%Y-%m-%d",        "%b %d %Y",        "%B %d %Y",        "%m %d %Y",    ]     def modulename(self, args):        if self._modulename:            return self._modulename         return os.path.dirname(args.fname)     def emit_th(self, name, args):        """Emit a title header line."""        title = name.strip()        module = self.modulename(args)         self.data += f'.TH "{title}" {self.section} "{self.date}" '        self.data += f'"{module}" "{self.manual}"\n'     def __init__(self, modulename=None, section="9", manual="Kernel API Manual"):        """        Creates class variables.         Not really mandatory, but it is a good coding style and makes        pylint happy.        """         super().__init__()         self._modulename = modulename        self.section = section        self.manual = manual         self.symbols = []         dt = None        tstamp = os.environ.get("KBUILD_BUILD_TIMESTAMP")        if tstamp:            for fmt in self.date_formats:                try:                    dt = datetime.strptime(tstamp, fmt)                    break                except ValueError:                    pass         if not dt:            dt = datetime.now()         self.date = dt.strftime("%B %Y")     def arg_name(self, args, name):        """        Return the name that will be used for the man page.         As we may have the same name on different namespaces,        prepend the data type for all types except functions and typedefs.         The doc section is special: it uses the modulename.        """         dtype = args.type         if dtype == "doc":            return name#            return os.path.basename(self.modulename(args))         if dtype in ["function", "typedef"]:            return name         return f"{dtype} {name}"     def set_symbols(self, symbols):        """        Get a list of all symbols from kernel_doc.         Man pages will uses it to add a SEE ALSO section with other        symbols at the same file.        """        self.symbols = symbols     def out_tail(self, fname, name, args):        """Adds a tail for all man pages."""         # SEE ALSO section        self.data += f'.SH "SEE ALSO"' + "\n.PP\n"        self.data += (f"Kernel file \\fB{args.fname}\\fR\n")        if len(self.symbols) >= 2:            cur_name = self.arg_name(args, name)             related = []            for arg in self.symbols:                out_name = self.arg_name(arg, arg.name)                 if cur_name == out_name:                    continue                 related.append(f"\\fB{out_name}\\fR(9)")             self.data += ",\n".join(related) + "\n"         # TODO: does it make sense to add other sections? Maybe        # REPORTING ISSUES? LICENSE?     def msg(self, fname, name, args):        """        Handles a single entry from kernel-doc parser.         Add a tail at the end of man pages output.        """        super().msg(fname, name, args)        self.out_tail(fname, name, args)         return self.data     def emit_table(self, colspec_row, rows):         if not rows:            return ""         out = ""        colspec = "\t".join(["l"] * len(rows[0]))         out += "\n.TS\n"        out += "box;\n"        out += f"{colspec}.\n"         if colspec_row:            out_row = []             for text in colspec_row:                out_row.append(f"\\fB{text}\\fP")             out += "\t".join(out_row) + "\n_\n"         for r in rows:            out += "\t".join(r) + "\n"         out += ".TE\n"         return out     def grid_table(self, lines, start):        """        Ancillary function to help handling a grid table inside the text.        """         i = start + 1        rows = []        colspec_row = None         while i < len(lines):            line = lines[i]             if KernRe(r"^\s*\|.*\|\s*$").match(line):                parts = []                 for p in line.strip('|').split('|'):                    parts.append(p.strip())                 rows.append(parts)             elif KernRe(r'^\+\=[\+\=]+\+\s*$').match(line):                if rows and rows[0]:                    if not colspec_row:                        colspec_row = [""] * len(rows[0])                     for j in range(0, len(rows[0])):                        content = []                        for row in rows:                            content.append(row[j])                         colspec_row[j] = " ".join(content)                     rows = []             elif KernRe(r"^\s*\+[-+]+\+.*$").match(line):                pass             else:                break             i += 1         return i, self.emit_table(colspec_row, rows)     def simple_table(self, lines, start):        """        Ancillary function to help handling a simple table inside the text.        """         i = start        rows = []        colspec_row = None         pos = []        for m in KernRe(r'\=+').finditer(lines[i]):            pos.append((m.start(), m.end() - 1))         i += 1        while i < len(lines):            line = lines[i]             if KernRe(r"^\s*[\=]+[ \t\=]+$").match(line):                i += 1                break             elif KernRe(r'^[\s=]+$').match(line):                if rows and rows[0]:                    if not colspec_row:                        colspec_row = [""] * len(rows[0])                     for j in range(0, len(rows[0])):                        content = []                        for row in rows:                            content.append(row[j])                         colspec_row[j] = " ".join(content)                     rows = []             else:                row = [""] * len(pos)                 for j in range(0, len(pos)):                    start, end = pos[j]                     row[j] = line[start:end].strip()                 rows.append(row)             i += 1         return i, self.emit_table(colspec_row, rows)     def code_block(self, lines, start):        """        Ensure that code blocks won't be messed up at the output.         By default, troff join lines at the same paragraph. Disable it,        on code blocks.        """         line = lines[start]         if "code-block" in line:            out = "\n.nf\n"        elif line.startswith("..") and line.endswith("::"):            #            # Handle note, warning, error, ... markups            #            line = line[2:-1].strip().upper()            out = f"\n.nf\n\\fB{line}\\fP\n"        elif line.endswith("::"):            out = line[:-1]            out += "\n.nf\n"        else:            # Just in case. Should never happen in practice            out = "\n.nf\n"         i = start + 1        ident = None         while i < len(lines):            line = lines[i]             m = KernRe(r"\S").match(line)            if not m:                out += line + "\n"                i += 1                continue             pos = m.start()            if not ident:                if pos > 0:                    ident = pos                else:                    out += "\n.fi\n"                    if i > start + 1:                        return i - 1, out                    else:                        # Just in case. Should never happen in practice                        return i, out             if pos >= ident:                out += line + "\n"                i += 1                continue             break         out += "\n.fi\n"        return i, out     def output_highlight(self, block):        """        Outputs a C symbol that may require being highlighted with        self.highlights variable using troff syntax.        """         contents = self.highlight_block(block)         if isinstance(contents, list):            contents = "\n".join(contents)         lines = contents.strip("\n").split("\n")        i = 0         while i < len(lines):            org_line = lines[i]             line = KernRe(r"^\s*").sub("", org_line)             if line:                if KernRe(r"^\+\-[-+]+\+.*$").match(line):                    i, text = self.grid_table(lines, i)                    self.data += text                    continue                 if KernRe(r"^\=+[ \t]\=[ \t\=]+$").match(line):                    i, text = self.simple_table(lines, i)                    self.data += text                    continue                 if line.endswith("::") or KernRe(r"\.\.\s+code-block.*::").match(line):                    i, text = self.code_block(lines, i)                    self.data += text                    continue                 if line[0] == ".":                    self.data += "\\&" + line + "\n"                    i += 1                    continue                 #                # Handle lists                #                line = KernRe(r'^[-*]\s+').sub(r'.IP \[bu]\n', line)                line = KernRe(r'^(\d+|a-z)[\.\)]\s+').sub(r'.IP \1\n', line)            else:                line = ".PP\n"             i += 1             self.data += line + "\n" 

Lines 501–1000 of 1160. Previous lines