scripts/kernel-doc.py: add a Python parser
Maintaining kernel-doc has been a challenge, as there aren't many
perl developers among maintainers. Also, the logic there is too
complex. Having lots of global variables and using pure functions
doesn't help.
Rewrite the script in Python, placing most global variables
inside classes. This should help maintaining the script in long
term.
It also allows a better integration with kernel-doc Sphinx
extension in the future.
I opted to keep this version as close as possible to what we
have already in Perl. There are some differences though:
1. There is one regular expression that required a rewrite:
/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/
As this one uses two features that aren't available by the native
Python regular expression module (re):
- recursive patterns: ?1
- atomic grouping (?>...)
Rewrite it to use a much simpler regular expression:
/\bSTRUCT_GROUP\(([^\)]+)\)[^;]*;/
Extra care should be taken when validating this script, as such
replacement might cause some regressions.
2. The filters are now applied only during output generation.
In particular, "nosymbol" argument is only handled there.
It means that, if the same file is processed twice for
different symbols, the warnings will be duplicated.
I opted to use this behavior as it allows the Sphinx extension
to read the file(s) only once, and apply the filtering only
when producing the ReST output. This hopefully will help
to speed up doc generation
3. This version can handle multiple files and multiple directories.
So, if one just wants to produce a big output with everything
inside a file, this could be done with
$ time ./scripts/kernel-doc.py -man . 2>/dev/null >new
real 0m54.592s
user 0m53.345s
sys 0m0.997s
4. I tried to replicate as much as possible the same arguments
from kernel-doc, with about the same behavior, for the
command line parameters starting with a single dash (-parameter).
I also added one letter aliases for each parameter, and a
--parameter (sometimes with a better name).
5. There are some sutile nuances between how Perl handles
certain regular expressions. In special, the qr operatior,
which compiles a regular expression also works as a
non-capturing group. It means that some regexes like
this one:
my $type1 = qr{[\w\s]+};
needs to be mapped as:
type1 = r'(?:[\w\s]+)?'
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/2fa671a9fb08d03a376a42d46cc0b1d3aab4ae3f.1744106241.git.mchehab+huawei@kernel.org
2025-04-08 18:09:06 +08:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
# Copyright(c) 2025: Mauro Carvalho Chehab <mchehab@kernel.org>.
|
|
|
|
|
#
|
|
|
|
|
# pylint: disable=R0902,R0903,R0904,R0911,R0912,R0913,R0914,R0915,R0917,R1702
|
|
|
|
|
# pylint: disable=C0302,C0103,C0301
|
|
|
|
|
# pylint: disable=C0116,C0115,W0511,W0613
|
|
|
|
|
#
|
|
|
|
|
# Converted from the kernel-doc script originally written in Perl
|
|
|
|
|
# under GPLv2, copyrighted since 1998 by the following authors:
|
|
|
|
|
#
|
|
|
|
|
# Aditya Srivastava <yashsri421@gmail.com>
|
|
|
|
|
# Akira Yokosawa <akiyks@gmail.com>
|
|
|
|
|
# Alexander A. Klimov <grandmaster@al2klimov.de>
|
|
|
|
|
# Alexander Lobakin <aleksander.lobakin@intel.com>
|
|
|
|
|
# André Almeida <andrealmeid@igalia.com>
|
|
|
|
|
# Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
|
|
|
|
# Anna-Maria Behnsen <anna-maria@linutronix.de>
|
|
|
|
|
# Armin Kuster <akuster@mvista.com>
|
|
|
|
|
# Bart Van Assche <bart.vanassche@sandisk.com>
|
|
|
|
|
# Ben Hutchings <ben@decadent.org.uk>
|
|
|
|
|
# Borislav Petkov <bbpetkov@yahoo.de>
|
|
|
|
|
# Chen-Yu Tsai <wenst@chromium.org>
|
|
|
|
|
# Coco Li <lixiaoyan@google.com>
|
|
|
|
|
# Conchúr Navid <conchur@web.de>
|
|
|
|
|
# Daniel Santos <daniel.santos@pobox.com>
|
|
|
|
|
# Danilo Cesar Lemes de Paula <danilo.cesar@collabora.co.uk>
|
|
|
|
|
# Dan Luedtke <mail@danrl.de>
|
|
|
|
|
# Donald Hunter <donald.hunter@gmail.com>
|
|
|
|
|
# Gabriel Krisman Bertazi <krisman@collabora.co.uk>
|
|
|
|
|
# Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
|
|
|
# Harvey Harrison <harvey.harrison@gmail.com>
|
|
|
|
|
# Horia Geanta <horia.geanta@freescale.com>
|
|
|
|
|
# Ilya Dryomov <idryomov@gmail.com>
|
|
|
|
|
# Jakub Kicinski <kuba@kernel.org>
|
|
|
|
|
# Jani Nikula <jani.nikula@intel.com>
|
|
|
|
|
# Jason Baron <jbaron@redhat.com>
|
|
|
|
|
# Jason Gunthorpe <jgg@nvidia.com>
|
|
|
|
|
# Jérémy Bobbio <lunar@debian.org>
|
|
|
|
|
# Johannes Berg <johannes.berg@intel.com>
|
|
|
|
|
# Johannes Weiner <hannes@cmpxchg.org>
|
|
|
|
|
# Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
|
|
|
|
# Jonathan Corbet <corbet@lwn.net>
|
|
|
|
|
# Jonathan Neuschäfer <j.neuschaefer@gmx.net>
|
|
|
|
|
# Kamil Rytarowski <n54@gmx.com>
|
|
|
|
|
# Kees Cook <kees@kernel.org>
|
|
|
|
|
# Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
|
|
|
|
# Levin, Alexander (Sasha Levin) <alexander.levin@verizon.com>
|
|
|
|
|
# Linus Torvalds <torvalds@linux-foundation.org>
|
|
|
|
|
# Lucas De Marchi <lucas.demarchi@profusion.mobi>
|
|
|
|
|
# Mark Rutland <mark.rutland@arm.com>
|
|
|
|
|
# Markus Heiser <markus.heiser@darmarit.de>
|
|
|
|
|
# Martin Waitz <tali@admingilde.org>
|
|
|
|
|
# Masahiro Yamada <masahiroy@kernel.org>
|
|
|
|
|
# Matthew Wilcox <willy@infradead.org>
|
|
|
|
|
# Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
|
|
|
|
# Michal Wajdeczko <michal.wajdeczko@intel.com>
|
|
|
|
|
# Michael Zucchi
|
|
|
|
|
# Mike Rapoport <rppt@linux.ibm.com>
|
|
|
|
|
# Niklas Söderlund <niklas.soderlund@corigine.com>
|
|
|
|
|
# Nishanth Menon <nm@ti.com>
|
|
|
|
|
# Paolo Bonzini <pbonzini@redhat.com>
|
|
|
|
|
# Pavan Kumar Linga <pavan.kumar.linga@intel.com>
|
|
|
|
|
# Pavel Pisa <pisa@cmp.felk.cvut.cz>
|
|
|
|
|
# Peter Maydell <peter.maydell@linaro.org>
|
|
|
|
|
# Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
|
|
|
|
# Randy Dunlap <rdunlap@infradead.org>
|
|
|
|
|
# Richard Kennedy <richard@rsk.demon.co.uk>
|
|
|
|
|
# Rich Walker <rw@shadow.org.uk>
|
|
|
|
|
# Rolf Eike Beer <eike-kernel@sf-tec.de>
|
|
|
|
|
# Sakari Ailus <sakari.ailus@linux.intel.com>
|
|
|
|
|
# Silvio Fricke <silvio.fricke@gmail.com>
|
|
|
|
|
# Simon Huggins
|
|
|
|
|
# Tim Waugh <twaugh@redhat.com>
|
|
|
|
|
# Tomasz Warniełło <tomasz.warniello@gmail.com>
|
|
|
|
|
# Utkarsh Tripathi <utripathi2002@gmail.com>
|
|
|
|
|
# valdis.kletnieks@vt.edu <valdis.kletnieks@vt.edu>
|
|
|
|
|
# Vegard Nossum <vegard.nossum@oracle.com>
|
|
|
|
|
# Will Deacon <will.deacon@arm.com>
|
|
|
|
|
# Yacine Belkadi <yacine.belkadi.1@gmail.com>
|
|
|
|
|
# Yujie Liu <yujie.liu@intel.com>
|
|
|
|
|
|
|
|
|
|
# TODO: implement warning filtering
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
kernel_doc
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
Print formatted kernel documentation to stdout
|
|
|
|
|
|
|
|
|
|
Read C language source or header FILEs, extract embedded
|
|
|
|
|
documentation comments, and print formatted documentation
|
|
|
|
|
to standard output.
|
|
|
|
|
|
|
|
|
|
The documentation comments are identified by the "/**"
|
|
|
|
|
opening comment mark.
|
|
|
|
|
|
|
|
|
|
See Documentation/doc-guide/kernel-doc.rst for the
|
|
|
|
|
documentation comment syntax.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
import logging
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
from pprint import pformat
|
|
|
|
|
|
|
|
|
|
from dateutil import tz
|
|
|
|
|
|
2025-04-08 18:09:10 +08:00
|
|
|
# Import Python modules
|
scripts/kernel-doc.py: add a Python parser
Maintaining kernel-doc has been a challenge, as there aren't many
perl developers among maintainers. Also, the logic there is too
complex. Having lots of global variables and using pure functions
doesn't help.
Rewrite the script in Python, placing most global variables
inside classes. This should help maintaining the script in long
term.
It also allows a better integration with kernel-doc Sphinx
extension in the future.
I opted to keep this version as close as possible to what we
have already in Perl. There are some differences though:
1. There is one regular expression that required a rewrite:
/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/
As this one uses two features that aren't available by the native
Python regular expression module (re):
- recursive patterns: ?1
- atomic grouping (?>...)
Rewrite it to use a much simpler regular expression:
/\bSTRUCT_GROUP\(([^\)]+)\)[^;]*;/
Extra care should be taken when validating this script, as such
replacement might cause some regressions.
2. The filters are now applied only during output generation.
In particular, "nosymbol" argument is only handled there.
It means that, if the same file is processed twice for
different symbols, the warnings will be duplicated.
I opted to use this behavior as it allows the Sphinx extension
to read the file(s) only once, and apply the filtering only
when producing the ReST output. This hopefully will help
to speed up doc generation
3. This version can handle multiple files and multiple directories.
So, if one just wants to produce a big output with everything
inside a file, this could be done with
$ time ./scripts/kernel-doc.py -man . 2>/dev/null >new
real 0m54.592s
user 0m53.345s
sys 0m0.997s
4. I tried to replicate as much as possible the same arguments
from kernel-doc, with about the same behavior, for the
command line parameters starting with a single dash (-parameter).
I also added one letter aliases for each parameter, and a
--parameter (sometimes with a better name).
5. There are some sutile nuances between how Perl handles
certain regular expressions. In special, the qr operatior,
which compiles a regular expression also works as a
non-capturing group. It means that some regexes like
this one:
my $type1 = qr{[\w\s]+};
needs to be mapped as:
type1 = r'(?:[\w\s]+)?'
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/2fa671a9fb08d03a376a42d46cc0b1d3aab4ae3f.1744106241.git.mchehab+huawei@kernel.org
2025-04-08 18:09:06 +08:00
|
|
|
|
2025-04-08 18:09:10 +08:00
|
|
|
LIB_DIR = "lib/kdoc"
|
|
|
|
|
SRC_DIR = os.path.dirname(os.path.realpath(__file__))
|
scripts/kernel-doc.py: add a Python parser
Maintaining kernel-doc has been a challenge, as there aren't many
perl developers among maintainers. Also, the logic there is too
complex. Having lots of global variables and using pure functions
doesn't help.
Rewrite the script in Python, placing most global variables
inside classes. This should help maintaining the script in long
term.
It also allows a better integration with kernel-doc Sphinx
extension in the future.
I opted to keep this version as close as possible to what we
have already in Perl. There are some differences though:
1. There is one regular expression that required a rewrite:
/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/
As this one uses two features that aren't available by the native
Python regular expression module (re):
- recursive patterns: ?1
- atomic grouping (?>...)
Rewrite it to use a much simpler regular expression:
/\bSTRUCT_GROUP\(([^\)]+)\)[^;]*;/
Extra care should be taken when validating this script, as such
replacement might cause some regressions.
2. The filters are now applied only during output generation.
In particular, "nosymbol" argument is only handled there.
It means that, if the same file is processed twice for
different symbols, the warnings will be duplicated.
I opted to use this behavior as it allows the Sphinx extension
to read the file(s) only once, and apply the filtering only
when producing the ReST output. This hopefully will help
to speed up doc generation
3. This version can handle multiple files and multiple directories.
So, if one just wants to produce a big output with everything
inside a file, this could be done with
$ time ./scripts/kernel-doc.py -man . 2>/dev/null >new
real 0m54.592s
user 0m53.345s
sys 0m0.997s
4. I tried to replicate as much as possible the same arguments
from kernel-doc, with about the same behavior, for the
command line parameters starting with a single dash (-parameter).
I also added one letter aliases for each parameter, and a
--parameter (sometimes with a better name).
5. There are some sutile nuances between how Perl handles
certain regular expressions. In special, the qr operatior,
which compiles a regular expression also works as a
non-capturing group. It means that some regexes like
this one:
my $type1 = qr{[\w\s]+};
needs to be mapped as:
type1 = r'(?:[\w\s]+)?'
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/2fa671a9fb08d03a376a42d46cc0b1d3aab4ae3f.1744106241.git.mchehab+huawei@kernel.org
2025-04-08 18:09:06 +08:00
|
|
|
|
2025-04-08 18:09:10 +08:00
|
|
|
sys.path.insert(0, os.path.join(SRC_DIR, LIB_DIR))
|
scripts/kernel-doc.py: add a Python parser
Maintaining kernel-doc has been a challenge, as there aren't many
perl developers among maintainers. Also, the logic there is too
complex. Having lots of global variables and using pure functions
doesn't help.
Rewrite the script in Python, placing most global variables
inside classes. This should help maintaining the script in long
term.
It also allows a better integration with kernel-doc Sphinx
extension in the future.
I opted to keep this version as close as possible to what we
have already in Perl. There are some differences though:
1. There is one regular expression that required a rewrite:
/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/
As this one uses two features that aren't available by the native
Python regular expression module (re):
- recursive patterns: ?1
- atomic grouping (?>...)
Rewrite it to use a much simpler regular expression:
/\bSTRUCT_GROUP\(([^\)]+)\)[^;]*;/
Extra care should be taken when validating this script, as such
replacement might cause some regressions.
2. The filters are now applied only during output generation.
In particular, "nosymbol" argument is only handled there.
It means that, if the same file is processed twice for
different symbols, the warnings will be duplicated.
I opted to use this behavior as it allows the Sphinx extension
to read the file(s) only once, and apply the filtering only
when producing the ReST output. This hopefully will help
to speed up doc generation
3. This version can handle multiple files and multiple directories.
So, if one just wants to produce a big output with everything
inside a file, this could be done with
$ time ./scripts/kernel-doc.py -man . 2>/dev/null >new
real 0m54.592s
user 0m53.345s
sys 0m0.997s
4. I tried to replicate as much as possible the same arguments
from kernel-doc, with about the same behavior, for the
command line parameters starting with a single dash (-parameter).
I also added one letter aliases for each parameter, and a
--parameter (sometimes with a better name).
5. There are some sutile nuances between how Perl handles
certain regular expressions. In special, the qr operatior,
which compiles a regular expression also works as a
non-capturing group. It means that some regexes like
this one:
my $type1 = qr{[\w\s]+};
needs to be mapped as:
type1 = r'(?:[\w\s]+)?'
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/2fa671a9fb08d03a376a42d46cc0b1d3aab4ae3f.1744106241.git.mchehab+huawei@kernel.org
2025-04-08 18:09:06 +08:00
|
|
|
|
2025-04-08 18:09:11 +08:00
|
|
|
from kdoc_parser import KernelDoc, type_param
|
|
|
|
|
from kdoc_re import Re
|
2025-04-08 18:09:12 +08:00
|
|
|
from kdoc_files import KernelFiles
|
scripts/kernel-doc.py: add a Python parser
Maintaining kernel-doc has been a challenge, as there aren't many
perl developers among maintainers. Also, the logic there is too
complex. Having lots of global variables and using pure functions
doesn't help.
Rewrite the script in Python, placing most global variables
inside classes. This should help maintaining the script in long
term.
It also allows a better integration with kernel-doc Sphinx
extension in the future.
I opted to keep this version as close as possible to what we
have already in Perl. There are some differences though:
1. There is one regular expression that required a rewrite:
/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/
As this one uses two features that aren't available by the native
Python regular expression module (re):
- recursive patterns: ?1
- atomic grouping (?>...)
Rewrite it to use a much simpler regular expression:
/\bSTRUCT_GROUP\(([^\)]+)\)[^;]*;/
Extra care should be taken when validating this script, as such
replacement might cause some regressions.
2. The filters are now applied only during output generation.
In particular, "nosymbol" argument is only handled there.
It means that, if the same file is processed twice for
different symbols, the warnings will be duplicated.
I opted to use this behavior as it allows the Sphinx extension
to read the file(s) only once, and apply the filtering only
when producing the ReST output. This hopefully will help
to speed up doc generation
3. This version can handle multiple files and multiple directories.
So, if one just wants to produce a big output with everything
inside a file, this could be done with
$ time ./scripts/kernel-doc.py -man . 2>/dev/null >new
real 0m54.592s
user 0m53.345s
sys 0m0.997s
4. I tried to replicate as much as possible the same arguments
from kernel-doc, with about the same behavior, for the
command line parameters starting with a single dash (-parameter).
I also added one letter aliases for each parameter, and a
--parameter (sometimes with a better name).
5. There are some sutile nuances between how Perl handles
certain regular expressions. In special, the qr operatior,
which compiles a regular expression also works as a
non-capturing group. It means that some regexes like
this one:
my $type1 = qr{[\w\s]+};
needs to be mapped as:
type1 = r'(?:[\w\s]+)?'
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/2fa671a9fb08d03a376a42d46cc0b1d3aab4ae3f.1744106241.git.mchehab+huawei@kernel.org
2025-04-08 18:09:06 +08:00
|
|
|
|
|
|
|
|
function_pointer = Re(r"([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)", cache=False)
|
|
|
|
|
|
|
|
|
|
# match expressions used to find embedded type information
|
|
|
|
|
type_constant = Re(r"\b``([^\`]+)``\b", cache=False)
|
|
|
|
|
type_constant2 = Re(r"\%([-_*\w]+)", cache=False)
|
|
|
|
|
type_func = Re(r"(\w+)\(\)", cache=False)
|
|
|
|
|
type_param_ref = Re(r"([\!~\*]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)", cache=False)
|
|
|
|
|
|
|
|
|
|
# Special RST handling for func ptr params
|
|
|
|
|
type_fp_param = Re(r"\@(\w+)\(\)", cache=False)
|
|
|
|
|
|
|
|
|
|
# Special RST handling for structs with func ptr params
|
|
|
|
|
type_fp_param2 = Re(r"\@(\w+->\S+)\(\)", cache=False)
|
|
|
|
|
|
|
|
|
|
type_env = Re(r"(\$\w+)", cache=False)
|
|
|
|
|
type_enum = Re(r"\&(enum\s*([_\w]+))", cache=False)
|
|
|
|
|
type_struct = Re(r"\&(struct\s*([_\w]+))", cache=False)
|
|
|
|
|
type_typedef = Re(r"\&(typedef\s*([_\w]+))", cache=False)
|
|
|
|
|
type_union = Re(r"\&(union\s*([_\w]+))", cache=False)
|
|
|
|
|
type_member = Re(r"\&([_\w]+)(\.|->)([_\w]+)", cache=False)
|
|
|
|
|
type_fallback = Re(r"\&([_\w]+)", cache=False)
|
|
|
|
|
type_member_func = type_member + Re(r"\(\)", cache=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OutputFormat:
|
|
|
|
|
# output mode.
|
|
|
|
|
OUTPUT_ALL = 0 # output all symbols and doc sections
|
|
|
|
|
OUTPUT_INCLUDE = 1 # output only specified symbols
|
|
|
|
|
OUTPUT_EXPORTED = 2 # output exported symbols
|
|
|
|
|
OUTPUT_INTERNAL = 3 # output non-exported symbols
|
|
|
|
|
|
|
|
|
|
# Virtual member to be overriden at the inherited classes
|
|
|
|
|
highlights = []
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
"""Declare internal vars and set mode to OUTPUT_ALL"""
|
|
|
|
|
|
|
|
|
|
self.out_mode = self.OUTPUT_ALL
|
|
|
|
|
self.enable_lineno = None
|
|
|
|
|
self.nosymbol = {}
|
|
|
|
|
self.symbol = None
|
|
|
|
|
self.function_table = set()
|
|
|
|
|
self.config = None
|
|
|
|
|
|
|
|
|
|
def set_config(self, config):
|
|
|
|
|
self.config = config
|
|
|
|
|
|
|
|
|
|
def set_filter(self, export, internal, symbol, nosymbol, function_table,
|
|
|
|
|
enable_lineno):
|
|
|
|
|
"""
|
|
|
|
|
Initialize filter variables according with the requested mode.
|
|
|
|
|
|
|
|
|
|
Only one choice is valid between export, internal and symbol.
|
|
|
|
|
|
|
|
|
|
The nosymbol filter can be used on all modes.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
self.enable_lineno = enable_lineno
|
|
|
|
|
|
|
|
|
|
if symbol:
|
|
|
|
|
self.out_mode = self.OUTPUT_INCLUDE
|
|
|
|
|
function_table = symbol
|
|
|
|
|
elif export:
|
|
|
|
|
self.out_mode = self.OUTPUT_EXPORTED
|
|
|
|
|
elif internal:
|
|
|
|
|
self.out_mode = self.OUTPUT_INTERNAL
|
|
|
|
|
else:
|
|
|
|
|
self.out_mode = self.OUTPUT_ALL
|
|
|
|
|
|
|
|
|
|
if nosymbol:
|
|
|
|
|
self.nosymbol = set(nosymbol)
|
|
|
|
|
|
|
|
|
|
if function_table:
|
|
|
|
|
self.function_table = function_table
|
|
|
|
|
|
|
|
|
|
def highlight_block(self, block):
|
|
|
|
|
"""
|
|
|
|
|
Apply the RST highlights to a sub-block of text.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
for r, sub in self.highlights:
|
|
|
|
|
block = r.sub(sub, block)
|
|
|
|
|
|
|
|
|
|
return block
|
|
|
|
|
|
|
|
|
|
def check_doc(self, name):
|
|
|
|
|
"""Check if DOC should be output"""
|
|
|
|
|
|
|
|
|
|
if self.out_mode == self.OUTPUT_ALL:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
if self.out_mode == self.OUTPUT_INCLUDE:
|
|
|
|
|
if name in self.nosymbol:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if name in self.function_table:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def check_declaration(self, dtype, name):
|
|
|
|
|
if name in self.nosymbol:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if self.out_mode == self.OUTPUT_ALL:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
if self.out_mode in [ self.OUTPUT_INCLUDE, self.OUTPUT_EXPORTED ]:
|
|
|
|
|
if name in self.function_table:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
if self.out_mode == self.OUTPUT_INTERNAL:
|
|
|
|
|
if dtype != "function":
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
if name not in self.function_table:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def check_function(self, fname, name, args):
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def check_enum(self, fname, name, args):
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def check_typedef(self, fname, name, args):
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def msg(self, fname, name, args):
|
|
|
|
|
|
|
|
|
|
dtype = args.get('type', "")
|
|
|
|
|
|
|
|
|
|
if dtype == "doc":
|
|
|
|
|
self.out_doc(fname, name, args)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if not self.check_declaration(dtype, name):
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if dtype == "function":
|
|
|
|
|
self.out_function(fname, name, args)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if dtype == "enum":
|
|
|
|
|
self.out_enum(fname, name, args)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if dtype == "typedef":
|
|
|
|
|
self.out_typedef(fname, name, args)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if dtype in ["struct", "union"]:
|
|
|
|
|
self.out_struct(fname, name, args)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# Warn if some type requires an output logic
|
|
|
|
|
self.config.log.warning("doesn't now how to output '%s' block",
|
|
|
|
|
dtype)
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
# Virtual methods to be overridden by inherited classes
|
|
|
|
|
def out_doc(self, fname, name, args):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def out_function(self, fname, name, args):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def out_enum(self, fname, name, args):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def out_typedef(self, fname, name, args):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def out_struct(self, fname, name, args):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RestFormat(OutputFormat):
|
|
|
|
|
# """Consts and functions used by ReST output"""
|
|
|
|
|
|
|
|
|
|
highlights = [
|
|
|
|
|
(type_constant, r"``\1``"),
|
|
|
|
|
(type_constant2, r"``\1``"),
|
|
|
|
|
|
|
|
|
|
# Note: need to escape () to avoid func matching later
|
|
|
|
|
(type_member_func, r":c:type:`\1\2\3\\(\\) <\1>`"),
|
|
|
|
|
(type_member, r":c:type:`\1\2\3 <\1>`"),
|
|
|
|
|
(type_fp_param, r"**\1\\(\\)**"),
|
|
|
|
|
(type_fp_param2, r"**\1\\(\\)**"),
|
|
|
|
|
(type_func, r"\1()"),
|
|
|
|
|
(type_enum, r":c:type:`\1 <\2>`"),
|
|
|
|
|
(type_struct, r":c:type:`\1 <\2>`"),
|
|
|
|
|
(type_typedef, r":c:type:`\1 <\2>`"),
|
|
|
|
|
(type_union, r":c:type:`\1 <\2>`"),
|
|
|
|
|
|
|
|
|
|
# in rst this can refer to any type
|
|
|
|
|
(type_fallback, r":c:type:`\1`"),
|
|
|
|
|
(type_param_ref, r"**\1\2**")
|
|
|
|
|
]
|
|
|
|
|
blankline = "\n"
|
|
|
|
|
|
|
|
|
|
sphinx_literal = Re(r'^[^.].*::$', cache=False)
|
|
|
|
|
sphinx_cblock = Re(r'^\.\.\ +code-block::', cache=False)
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
"""
|
|
|
|
|
Creates class variables.
|
|
|
|
|
|
|
|
|
|
Not really mandatory, but it is a good coding style and makes
|
|
|
|
|
pylint happy.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.lineprefix = ""
|
|
|
|
|
|
|
|
|
|
def print_lineno (self, ln):
|
|
|
|
|
"""Outputs a line number"""
|
|
|
|
|
|
|
|
|
|
if self.enable_lineno and ln:
|
|
|
|
|
print(f".. LINENO {ln}")
|
|
|
|
|
|
|
|
|
|
def output_highlight(self, args):
|
|
|
|
|
input_text = args
|
|
|
|
|
output = ""
|
|
|
|
|
in_literal = False
|
|
|
|
|
litprefix = ""
|
|
|
|
|
block = ""
|
|
|
|
|
|
|
|
|
|
for line in input_text.strip("\n").split("\n"):
|
|
|
|
|
|
|
|
|
|
# If we're in a literal block, see if we should drop out of it.
|
|
|
|
|
# Otherwise, pass the line straight through unmunged.
|
|
|
|
|
if in_literal:
|
|
|
|
|
if line.strip(): # If the line is not blank
|
|
|
|
|
# If this is the first non-blank line in a literal block,
|
|
|
|
|
# figure out the proper indent.
|
|
|
|
|
if not litprefix:
|
|
|
|
|
r = Re(r'^(\s*)')
|
|
|
|
|
if r.match(line):
|
|
|
|
|
litprefix = '^' + r.group(1)
|
|
|
|
|
else:
|
|
|
|
|
litprefix = ""
|
|
|
|
|
|
|
|
|
|
output += line + "\n"
|
|
|
|
|
elif not Re(litprefix).match(line):
|
|
|
|
|
in_literal = False
|
|
|
|
|
else:
|
|
|
|
|
output += line + "\n"
|
|
|
|
|
else:
|
|
|
|
|
output += line + "\n"
|
|
|
|
|
|
|
|
|
|
# Not in a literal block (or just dropped out)
|
|
|
|
|
if not in_literal:
|
|
|
|
|
block += line + "\n"
|
|
|
|
|
if self.sphinx_literal.match(line) or self.sphinx_cblock.match(line):
|
|
|
|
|
in_literal = True
|
|
|
|
|
litprefix = ""
|
|
|
|
|
output += self.highlight_block(block)
|
|
|
|
|
block = ""
|
|
|
|
|
|
|
|
|
|
# Handle any remaining block
|
|
|
|
|
if block:
|
|
|
|
|
output += self.highlight_block(block)
|
|
|
|
|
|
|
|
|
|
# Print the output with the line prefix
|
|
|
|
|
for line in output.strip("\n").split("\n"):
|
|
|
|
|
print(self.lineprefix + line)
|
|
|
|
|
|
|
|
|
|
def out_section(self, args, out_reference=False):
|
|
|
|
|
"""
|
|
|
|
|
Outputs a block section.
|
|
|
|
|
|
|
|
|
|
This could use some work; it's used to output the DOC: sections, and
|
|
|
|
|
starts by putting out the name of the doc section itself, but that
|
|
|
|
|
tends to duplicate a header already in the template file.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
sectionlist = args.get('sectionlist', [])
|
|
|
|
|
sections = args.get('sections', {})
|
|
|
|
|
section_start_lines = args.get('section_start_lines', {})
|
|
|
|
|
|
|
|
|
|
for section in sectionlist:
|
|
|
|
|
# Skip sections that are in the nosymbol_table
|
|
|
|
|
if section in self.nosymbol:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if not self.out_mode == self.OUTPUT_INCLUDE:
|
|
|
|
|
if out_reference:
|
|
|
|
|
print(f".. _{section}:\n")
|
|
|
|
|
|
|
|
|
|
if not self.symbol:
|
|
|
|
|
print(f'{self.lineprefix}**{section}**\n')
|
|
|
|
|
|
|
|
|
|
self.print_lineno(section_start_lines.get(section, 0))
|
|
|
|
|
self.output_highlight(sections[section])
|
|
|
|
|
print()
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
def out_doc(self, fname, name, args):
|
|
|
|
|
if not self.check_doc(name):
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.out_section(args, out_reference=True)
|
|
|
|
|
|
|
|
|
|
def out_function(self, fname, name, args):
|
|
|
|
|
|
|
|
|
|
oldprefix = self.lineprefix
|
|
|
|
|
signature = ""
|
|
|
|
|
|
|
|
|
|
func_macro = args.get('func_macro', False)
|
|
|
|
|
if func_macro:
|
|
|
|
|
signature = args['function']
|
|
|
|
|
else:
|
|
|
|
|
if args.get('functiontype'):
|
|
|
|
|
signature = args['functiontype'] + " "
|
|
|
|
|
signature += args['function'] + " ("
|
|
|
|
|
|
|
|
|
|
parameterlist = args.get('parameterlist', [])
|
|
|
|
|
parameterdescs = args.get('parameterdescs', {})
|
|
|
|
|
parameterdesc_start_lines = args.get('parameterdesc_start_lines', {})
|
|
|
|
|
|
|
|
|
|
ln = args.get('ln', 0)
|
|
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
|
for parameter in parameterlist:
|
|
|
|
|
if count != 0:
|
|
|
|
|
signature += ", "
|
|
|
|
|
count += 1
|
|
|
|
|
dtype = args['parametertypes'].get(parameter, "")
|
|
|
|
|
|
|
|
|
|
if function_pointer.search(dtype):
|
|
|
|
|
signature += function_pointer.group(1) + parameter + function_pointer.group(3)
|
|
|
|
|
else:
|
|
|
|
|
signature += dtype
|
|
|
|
|
|
|
|
|
|
if not func_macro:
|
|
|
|
|
signature += ")"
|
|
|
|
|
|
|
|
|
|
if args.get('typedef') or not args.get('functiontype'):
|
|
|
|
|
print(f".. c:macro:: {args['function']}\n")
|
|
|
|
|
|
|
|
|
|
if args.get('typedef'):
|
|
|
|
|
self.print_lineno(ln)
|
|
|
|
|
print(" **Typedef**: ", end="")
|
|
|
|
|
self.lineprefix = ""
|
|
|
|
|
self.output_highlight(args.get('purpose', ""))
|
|
|
|
|
print("\n\n**Syntax**\n")
|
|
|
|
|
print(f" ``{signature}``\n")
|
|
|
|
|
else:
|
|
|
|
|
print(f"``{signature}``\n")
|
|
|
|
|
else:
|
|
|
|
|
print(f".. c:function:: {signature}\n")
|
|
|
|
|
|
|
|
|
|
if not args.get('typedef'):
|
|
|
|
|
self.print_lineno(ln)
|
|
|
|
|
self.lineprefix = " "
|
|
|
|
|
self.output_highlight(args.get('purpose', ""))
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
# Put descriptive text into a container (HTML <div>) to help set
|
|
|
|
|
# function prototypes apart
|
|
|
|
|
self.lineprefix = " "
|
|
|
|
|
|
|
|
|
|
if parameterlist:
|
|
|
|
|
print(".. container:: kernelindent\n")
|
|
|
|
|
print(f"{self.lineprefix}**Parameters**\n")
|
|
|
|
|
|
|
|
|
|
for parameter in parameterlist:
|
|
|
|
|
parameter_name = Re(r'\[.*').sub('', parameter)
|
|
|
|
|
dtype = args['parametertypes'].get(parameter, "")
|
|
|
|
|
|
|
|
|
|
if dtype:
|
|
|
|
|
print(f"{self.lineprefix}``{dtype}``")
|
|
|
|
|
else:
|
|
|
|
|
print(f"{self.lineprefix}``{parameter}``")
|
|
|
|
|
|
|
|
|
|
self.print_lineno(parameterdesc_start_lines.get(parameter_name, 0))
|
|
|
|
|
|
|
|
|
|
self.lineprefix = " "
|
|
|
|
|
if parameter_name in parameterdescs and \
|
|
|
|
|
parameterdescs[parameter_name] != KernelDoc.undescribed:
|
|
|
|
|
|
|
|
|
|
self.output_highlight(parameterdescs[parameter_name])
|
|
|
|
|
print()
|
|
|
|
|
else:
|
|
|
|
|
print(f"{self.lineprefix}*undescribed*\n")
|
|
|
|
|
self.lineprefix = " "
|
|
|
|
|
|
|
|
|
|
self.out_section(args)
|
|
|
|
|
self.lineprefix = oldprefix
|
|
|
|
|
|
|
|
|
|
def out_enum(self, fname, name, args):
|
|
|
|
|
|
|
|
|
|
oldprefix = self.lineprefix
|
|
|
|
|
name = args.get('enum', '')
|
|
|
|
|
parameterlist = args.get('parameterlist', [])
|
|
|
|
|
parameterdescs = args.get('parameterdescs', {})
|
|
|
|
|
ln = args.get('ln', 0)
|
|
|
|
|
|
|
|
|
|
print(f"\n\n.. c:enum:: {name}\n")
|
|
|
|
|
|
|
|
|
|
self.print_lineno(ln)
|
|
|
|
|
self.lineprefix = " "
|
|
|
|
|
self.output_highlight(args.get('purpose', ''))
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
print(".. container:: kernelindent\n")
|
|
|
|
|
outer = self.lineprefix + " "
|
|
|
|
|
self.lineprefix = outer + " "
|
|
|
|
|
print(f"{outer}**Constants**\n")
|
|
|
|
|
|
|
|
|
|
for parameter in parameterlist:
|
|
|
|
|
print(f"{outer}``{parameter}``")
|
|
|
|
|
|
|
|
|
|
if parameterdescs.get(parameter, '') != KernelDoc.undescribed:
|
|
|
|
|
self.output_highlight(parameterdescs[parameter])
|
|
|
|
|
else:
|
|
|
|
|
print(f"{self.lineprefix}*undescribed*\n")
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
self.lineprefix = oldprefix
|
|
|
|
|
self.out_section(args)
|
|
|
|
|
|
|
|
|
|
def out_typedef(self, fname, name, args):
|
|
|
|
|
|
|
|
|
|
oldprefix = self.lineprefix
|
|
|
|
|
name = args.get('typedef', '')
|
|
|
|
|
ln = args.get('ln', 0)
|
|
|
|
|
|
|
|
|
|
print(f"\n\n.. c:type:: {name}\n")
|
|
|
|
|
|
|
|
|
|
self.print_lineno(ln)
|
|
|
|
|
self.lineprefix = " "
|
|
|
|
|
|
|
|
|
|
self.output_highlight(args.get('purpose', ''))
|
|
|
|
|
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
self.lineprefix = oldprefix
|
|
|
|
|
self.out_section(args)
|
|
|
|
|
|
|
|
|
|
def out_struct(self, fname, name, args):
|
|
|
|
|
|
|
|
|
|
name = args.get('struct', "")
|
|
|
|
|
purpose = args.get('purpose', "")
|
|
|
|
|
declaration = args.get('definition', "")
|
|
|
|
|
dtype = args.get('type', "struct")
|
|
|
|
|
ln = args.get('ln', 0)
|
|
|
|
|
|
|
|
|
|
parameterlist = args.get('parameterlist', [])
|
|
|
|
|
parameterdescs = args.get('parameterdescs', {})
|
|
|
|
|
parameterdesc_start_lines = args.get('parameterdesc_start_lines', {})
|
|
|
|
|
|
|
|
|
|
print(f"\n\n.. c:{dtype}:: {name}\n")
|
|
|
|
|
|
|
|
|
|
self.print_lineno(ln)
|
|
|
|
|
|
|
|
|
|
oldprefix = self.lineprefix
|
|
|
|
|
self.lineprefix += " "
|
|
|
|
|
|
|
|
|
|
self.output_highlight(purpose)
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
print(".. container:: kernelindent\n")
|
|
|
|
|
print(f"{self.lineprefix}**Definition**::\n")
|
|
|
|
|
|
|
|
|
|
self.lineprefix = self.lineprefix + " "
|
|
|
|
|
|
|
|
|
|
declaration = declaration.replace("\t", self.lineprefix)
|
|
|
|
|
|
|
|
|
|
print(f"{self.lineprefix}{dtype} {name}" + ' {')
|
|
|
|
|
print(f"{declaration}{self.lineprefix}" + "};\n")
|
|
|
|
|
|
|
|
|
|
self.lineprefix = " "
|
|
|
|
|
print(f"{self.lineprefix}**Members**\n")
|
|
|
|
|
for parameter in parameterlist:
|
|
|
|
|
if not parameter or parameter.startswith("#"):
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
parameter_name = parameter.split("[", maxsplit=1)[0]
|
|
|
|
|
|
|
|
|
|
if parameterdescs.get(parameter_name) == KernelDoc.undescribed:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
self.print_lineno(parameterdesc_start_lines.get(parameter_name, 0))
|
|
|
|
|
|
|
|
|
|
print(f"{self.lineprefix}``{parameter}``")
|
|
|
|
|
|
|
|
|
|
self.lineprefix = " "
|
|
|
|
|
self.output_highlight(parameterdescs[parameter_name])
|
|
|
|
|
self.lineprefix = " "
|
|
|
|
|
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
self.lineprefix = oldprefix
|
|
|
|
|
self.out_section(args)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ManFormat(OutputFormat):
|
|
|
|
|
"""Consts and functions used by man pages output"""
|
|
|
|
|
|
|
|
|
|
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 = ""
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
"""
|
|
|
|
|
Creates class variables.
|
|
|
|
|
|
|
|
|
|
Not really mandatory, but it is a good coding style and makes
|
|
|
|
|
pylint happy.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
super().__init__()
|
|
|
|
|
|
|
|
|
|
dt = datetime.now()
|
|
|
|
|
if os.environ.get("KBUILD_BUILD_TIMESTAMP", None):
|
|
|
|
|
# use UTC TZ
|
|
|
|
|
to_zone = tz.gettz('UTC')
|
|
|
|
|
dt = dt.astimezone(to_zone)
|
|
|
|
|
|
|
|
|
|
self.man_date = dt.strftime("%B %Y")
|
|
|
|
|
|
|
|
|
|
def output_highlight(self, block):
|
|
|
|
|
|
|
|
|
|
contents = self.highlight_block(block)
|
|
|
|
|
|
|
|
|
|
if isinstance(contents, list):
|
|
|
|
|
contents = "\n".join(contents)
|
|
|
|
|
|
|
|
|
|
for line in contents.strip("\n").split("\n"):
|
|
|
|
|
line = Re(r"^\s*").sub("", line)
|
|
|
|
|
|
|
|
|
|
if line and line[0] == ".":
|
|
|
|
|
print("\\&" + line)
|
|
|
|
|
else:
|
|
|
|
|
print(line)
|
|
|
|
|
|
|
|
|
|
def out_doc(self, fname, name, args):
|
|
|
|
|
module = args.get('module')
|
|
|
|
|
sectionlist = args.get('sectionlist', [])
|
|
|
|
|
sections = args.get('sections', {})
|
|
|
|
|
|
|
|
|
|
print(f'.TH "{module}" 9 "{module}" "{self.man_date}" "API Manual" LINUX')
|
|
|
|
|
|
|
|
|
|
for section in sectionlist:
|
|
|
|
|
print(f'.SH "{section}"')
|
|
|
|
|
self.output_highlight(sections.get(section))
|
|
|
|
|
|
|
|
|
|
def out_function(self, fname, name, args):
|
|
|
|
|
"""output function in man"""
|
|
|
|
|
|
|
|
|
|
parameterlist = args.get('parameterlist', [])
|
|
|
|
|
parameterdescs = args.get('parameterdescs', {})
|
|
|
|
|
sectionlist = args.get('sectionlist', [])
|
|
|
|
|
sections = args.get('sections', {})
|
|
|
|
|
|
|
|
|
|
print(f'.TH "{args['function']}" 9 "{args['function']}" "{self.man_date}" "Kernel Hacker\'s Manual" LINUX')
|
|
|
|
|
|
|
|
|
|
print(".SH NAME")
|
|
|
|
|
print(f"{args['function']} \\- {args['purpose']}")
|
|
|
|
|
|
|
|
|
|
print(".SH SYNOPSIS")
|
|
|
|
|
if args.get('functiontype', ''):
|
|
|
|
|
print(f'.B "{args['functiontype']}" {args['function']}')
|
|
|
|
|
else:
|
|
|
|
|
print(f'.B "{args['function']}')
|
|
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
|
parenth = "("
|
|
|
|
|
post = ","
|
|
|
|
|
|
|
|
|
|
for parameter in parameterlist:
|
|
|
|
|
if count == len(parameterlist) - 1:
|
|
|
|
|
post = ");"
|
|
|
|
|
|
|
|
|
|
dtype = args['parametertypes'].get(parameter, "")
|
|
|
|
|
if function_pointer.match(dtype):
|
|
|
|
|
# Pointer-to-function
|
|
|
|
|
print(f'".BI "{parenth}{function_pointer.group(1)}" " ") ({function_pointer.group(2)}){post}"')
|
|
|
|
|
else:
|
|
|
|
|
dtype = Re(r'([^\*])$').sub(r'\1 ', dtype)
|
|
|
|
|
|
|
|
|
|
print(f'.BI "{parenth}{dtype}" "{post}"')
|
|
|
|
|
count += 1
|
|
|
|
|
parenth = ""
|
|
|
|
|
|
|
|
|
|
if parameterlist:
|
|
|
|
|
print(".SH ARGUMENTS")
|
|
|
|
|
|
|
|
|
|
for parameter in parameterlist:
|
|
|
|
|
parameter_name = re.sub(r'\[.*', '', parameter)
|
|
|
|
|
|
|
|
|
|
print(f'.IP "{parameter}" 12')
|
|
|
|
|
self.output_highlight(parameterdescs.get(parameter_name, ""))
|
|
|
|
|
|
|
|
|
|
for section in sectionlist:
|
|
|
|
|
print(f'.SH "{section.upper()}"')
|
|
|
|
|
self.output_highlight(sections[section])
|
|
|
|
|
|
|
|
|
|
def out_enum(self, fname, name, args):
|
|
|
|
|
|
|
|
|
|
name = args.get('enum', '')
|
|
|
|
|
parameterlist = args.get('parameterlist', [])
|
|
|
|
|
sectionlist = args.get('sectionlist', [])
|
|
|
|
|
sections = args.get('sections', {})
|
|
|
|
|
|
|
|
|
|
print(f'.TH "{args['module']}" 9 "enum {args['enum']}" "{self.man_date}" "API Manual" LINUX')
|
|
|
|
|
|
|
|
|
|
print(".SH NAME")
|
|
|
|
|
print(f"enum {args['enum']} \\- {args['purpose']}")
|
|
|
|
|
|
|
|
|
|
print(".SH SYNOPSIS")
|
|
|
|
|
print(f"enum {args['enum']}" + " {")
|
|
|
|
|
|
|
|
|
|
count = 0
|
|
|
|
|
for parameter in parameterlist:
|
|
|
|
|
print(f'.br\n.BI " {parameter}"')
|
|
|
|
|
if count == len(parameterlist) - 1:
|
|
|
|
|
print("\n};")
|
|
|
|
|
else:
|
|
|
|
|
print(", \n.br")
|
|
|
|
|
|
|
|
|
|
count += 1
|
|
|
|
|
|
|
|
|
|
print(".SH Constants")
|
|
|
|
|
|
|
|
|
|
for parameter in parameterlist:
|
|
|
|
|
parameter_name = Re(r'\[.*').sub('', parameter)
|
|
|
|
|
print(f'.IP "{parameter}" 12')
|
|
|
|
|
self.output_highlight(args['parameterdescs'].get(parameter_name, ""))
|
|
|
|
|
|
|
|
|
|
for section in sectionlist:
|
|
|
|
|
print(f'.SH "{section}"')
|
|
|
|
|
self.output_highlight(sections[section])
|
|
|
|
|
|
|
|
|
|
def out_typedef(self, fname, name, args):
|
|
|
|
|
module = args.get('module')
|
|
|
|
|
typedef = args.get('typedef')
|
|
|
|
|
purpose = args.get('purpose')
|
|
|
|
|
sectionlist = args.get('sectionlist', [])
|
|
|
|
|
sections = args.get('sections', {})
|
|
|
|
|
|
|
|
|
|
print(f'.TH "{module}" 9 "{typedef}" "{self.man_date}" "API Manual" LINUX')
|
|
|
|
|
|
|
|
|
|
print(".SH NAME")
|
|
|
|
|
print(f"typedef {typedef} \\- {purpose}")
|
|
|
|
|
|
|
|
|
|
for section in sectionlist:
|
|
|
|
|
print(f'.SH "{section}"')
|
|
|
|
|
self.output_highlight(sections.get(section))
|
|
|
|
|
|
|
|
|
|
def out_struct(self, fname, name, args):
|
|
|
|
|
module = args.get('module')
|
|
|
|
|
struct_type = args.get('type')
|
|
|
|
|
struct_name = args.get('struct')
|
|
|
|
|
purpose = args.get('purpose')
|
|
|
|
|
definition = args.get('definition')
|
|
|
|
|
sectionlist = args.get('sectionlist', [])
|
|
|
|
|
parameterlist = args.get('parameterlist', [])
|
|
|
|
|
sections = args.get('sections', {})
|
|
|
|
|
parameterdescs = args.get('parameterdescs', {})
|
|
|
|
|
|
|
|
|
|
print(f'.TH "{module}" 9 "{struct_type} {struct_name}" "{self.man_date}" "API Manual" LINUX')
|
|
|
|
|
|
|
|
|
|
print(".SH NAME")
|
|
|
|
|
print(f"{struct_type} {struct_name} \\- {purpose}")
|
|
|
|
|
|
|
|
|
|
# Replace tabs with two spaces and handle newlines
|
|
|
|
|
declaration = definition.replace("\t", " ")
|
|
|
|
|
declaration = Re(r"\n").sub('"\n.br\n.BI "', declaration)
|
|
|
|
|
|
|
|
|
|
print(".SH SYNOPSIS")
|
|
|
|
|
print(f"{struct_type} {struct_name} " + "{" +"\n.br")
|
|
|
|
|
print(f'.BI "{declaration}\n' + "};\n.br\n")
|
|
|
|
|
|
|
|
|
|
print(".SH Members")
|
|
|
|
|
for parameter in parameterlist:
|
|
|
|
|
if parameter.startswith("#"):
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
parameter_name = re.sub(r"\[.*", "", parameter)
|
|
|
|
|
|
|
|
|
|
if parameterdescs.get(parameter_name) == KernelDoc.undescribed:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
print(f'.IP "{parameter}" 12')
|
|
|
|
|
self.output_highlight(parameterdescs.get(parameter_name))
|
|
|
|
|
|
|
|
|
|
for section in sectionlist:
|
|
|
|
|
print(f'.SH "{section}"')
|
|
|
|
|
self.output_highlight(sections.get(section))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Command line interface
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DESC = """
|
|
|
|
|
Read C language source or header FILEs, extract embedded documentation comments,
|
|
|
|
|
and print formatted documentation to standard output.
|
|
|
|
|
|
|
|
|
|
The documentation comments are identified by the "/**" opening comment mark.
|
|
|
|
|
|
|
|
|
|
See Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
EXPORT_FILE_DESC = """
|
|
|
|
|
Specify an additional FILE in which to look for EXPORT_SYMBOL information.
|
|
|
|
|
|
|
|
|
|
May be used multiple times.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
EXPORT_DESC = """
|
|
|
|
|
Only output documentation for the symbols that have been
|
|
|
|
|
exported using EXPORT_SYMBOL() and related macros in any input
|
|
|
|
|
FILE or -export-file FILE.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
INTERNAL_DESC = """
|
|
|
|
|
Only output documentation for the symbols that have NOT been
|
|
|
|
|
exported using EXPORT_SYMBOL() and related macros in any input
|
|
|
|
|
FILE or -export-file FILE.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
FUNCTION_DESC = """
|
|
|
|
|
Only output documentation for the given function or DOC: section
|
|
|
|
|
title. All other functions and DOC: sections are ignored.
|
|
|
|
|
|
|
|
|
|
May be used multiple times.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
NOSYMBOL_DESC = """
|
|
|
|
|
Exclude the specified symbol from the output documentation.
|
|
|
|
|
|
|
|
|
|
May be used multiple times.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
FILES_DESC = """
|
|
|
|
|
Header and C source files to be parsed.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
WARN_CONTENTS_BEFORE_SECTIONS_DESC = """
|
|
|
|
|
Warns if there are contents before sections (deprecated).
|
|
|
|
|
|
|
|
|
|
This option is kept just for backward-compatibility, but it does nothing,
|
|
|
|
|
neither here nor at the original Perl script.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
2025-04-08 18:09:07 +08:00
|
|
|
class MsgFormatter(logging.Formatter):
|
|
|
|
|
def format(self, record):
|
|
|
|
|
record.levelname = record.levelname.capitalize()
|
|
|
|
|
return logging.Formatter.format(self, record)
|
|
|
|
|
|
scripts/kernel-doc.py: add a Python parser
Maintaining kernel-doc has been a challenge, as there aren't many
perl developers among maintainers. Also, the logic there is too
complex. Having lots of global variables and using pure functions
doesn't help.
Rewrite the script in Python, placing most global variables
inside classes. This should help maintaining the script in long
term.
It also allows a better integration with kernel-doc Sphinx
extension in the future.
I opted to keep this version as close as possible to what we
have already in Perl. There are some differences though:
1. There is one regular expression that required a rewrite:
/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/
As this one uses two features that aren't available by the native
Python regular expression module (re):
- recursive patterns: ?1
- atomic grouping (?>...)
Rewrite it to use a much simpler regular expression:
/\bSTRUCT_GROUP\(([^\)]+)\)[^;]*;/
Extra care should be taken when validating this script, as such
replacement might cause some regressions.
2. The filters are now applied only during output generation.
In particular, "nosymbol" argument is only handled there.
It means that, if the same file is processed twice for
different symbols, the warnings will be duplicated.
I opted to use this behavior as it allows the Sphinx extension
to read the file(s) only once, and apply the filtering only
when producing the ReST output. This hopefully will help
to speed up doc generation
3. This version can handle multiple files and multiple directories.
So, if one just wants to produce a big output with everything
inside a file, this could be done with
$ time ./scripts/kernel-doc.py -man . 2>/dev/null >new
real 0m54.592s
user 0m53.345s
sys 0m0.997s
4. I tried to replicate as much as possible the same arguments
from kernel-doc, with about the same behavior, for the
command line parameters starting with a single dash (-parameter).
I also added one letter aliases for each parameter, and a
--parameter (sometimes with a better name).
5. There are some sutile nuances between how Perl handles
certain regular expressions. In special, the qr operatior,
which compiles a regular expression also works as a
non-capturing group. It means that some regexes like
this one:
my $type1 = qr{[\w\s]+};
needs to be mapped as:
type1 = r'(?:[\w\s]+)?'
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/2fa671a9fb08d03a376a42d46cc0b1d3aab4ae3f.1744106241.git.mchehab+huawei@kernel.org
2025-04-08 18:09:06 +08:00
|
|
|
def main():
|
|
|
|
|
"""Main program"""
|
|
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter,
|
|
|
|
|
description=DESC)
|
|
|
|
|
|
|
|
|
|
# Normal arguments
|
|
|
|
|
|
|
|
|
|
parser.add_argument("-v", "-verbose", "--verbose", action="store_true",
|
|
|
|
|
help="Verbose output, more warnings and other information.")
|
|
|
|
|
|
|
|
|
|
parser.add_argument("-d", "-debug", "--debug", action="store_true",
|
|
|
|
|
help="Enable debug messages")
|
|
|
|
|
|
|
|
|
|
parser.add_argument("-M", "-modulename", "--modulename",
|
|
|
|
|
help="Allow setting a module name at the output.")
|
|
|
|
|
|
|
|
|
|
parser.add_argument("-l", "-enable-lineno", "--enable_lineno",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Enable line number output (only in ReST mode)")
|
|
|
|
|
|
|
|
|
|
# Arguments to control the warning behavior
|
|
|
|
|
|
|
|
|
|
parser.add_argument("-Wreturn", "--wreturn", action="store_true",
|
|
|
|
|
help="Warns about the lack of a return markup on functions.")
|
|
|
|
|
|
|
|
|
|
parser.add_argument("-Wshort-desc", "-Wshort-description", "--wshort-desc",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Warns if initial short description is missing")
|
|
|
|
|
|
|
|
|
|
parser.add_argument("-Wcontents-before-sections",
|
|
|
|
|
"--wcontents-before-sections", action="store_true",
|
|
|
|
|
help=WARN_CONTENTS_BEFORE_SECTIONS_DESC)
|
|
|
|
|
|
|
|
|
|
parser.add_argument("-Wall", "--wall", action="store_true",
|
|
|
|
|
help="Enable all types of warnings")
|
|
|
|
|
|
|
|
|
|
parser.add_argument("-Werror", "--werror", action="store_true",
|
|
|
|
|
help="Treat warnings as errors.")
|
|
|
|
|
|
|
|
|
|
parser.add_argument("-export-file", "--export-file", action='append',
|
|
|
|
|
help=EXPORT_FILE_DESC)
|
|
|
|
|
|
|
|
|
|
# Output format mutually-exclusive group
|
|
|
|
|
|
|
|
|
|
out_group = parser.add_argument_group("Output format selection (mutually exclusive)")
|
|
|
|
|
|
|
|
|
|
out_fmt = out_group.add_mutually_exclusive_group()
|
|
|
|
|
|
|
|
|
|
out_fmt.add_argument("-m", "-man", "--man", action="store_true",
|
|
|
|
|
help="Output troff manual page format.")
|
|
|
|
|
out_fmt.add_argument("-r", "-rst", "--rst", action="store_true",
|
|
|
|
|
help="Output reStructuredText format (default).")
|
|
|
|
|
out_fmt.add_argument("-N", "-none", "--none", action="store_true",
|
|
|
|
|
help="Do not output documentation, only warnings.")
|
|
|
|
|
|
|
|
|
|
# Output selection mutually-exclusive group
|
|
|
|
|
|
|
|
|
|
sel_group = parser.add_argument_group("Output selection (mutually exclusive)")
|
|
|
|
|
sel_mut = sel_group.add_mutually_exclusive_group()
|
|
|
|
|
|
|
|
|
|
sel_mut.add_argument("-e", "-export", "--export", action='store_true',
|
|
|
|
|
help=EXPORT_DESC)
|
|
|
|
|
|
|
|
|
|
sel_mut.add_argument("-i", "-internal", "--internal", action='store_true',
|
|
|
|
|
help=INTERNAL_DESC)
|
|
|
|
|
|
|
|
|
|
sel_mut.add_argument("-s", "-function", "--symbol", action='append',
|
|
|
|
|
help=FUNCTION_DESC)
|
|
|
|
|
|
|
|
|
|
# This one is valid for all 3 types of filter
|
|
|
|
|
parser.add_argument("-n", "-nosymbol", "--nosymbol", action='append',
|
|
|
|
|
help=NOSYMBOL_DESC)
|
|
|
|
|
|
|
|
|
|
parser.add_argument("files", metavar="FILE",
|
|
|
|
|
nargs="+", help=FILES_DESC)
|
|
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
if args.wall:
|
|
|
|
|
args.wreturn = True
|
|
|
|
|
args.wshort_desc = True
|
|
|
|
|
args.wcontents_before_sections = True
|
|
|
|
|
|
2025-04-08 18:09:07 +08:00
|
|
|
logger = logging.getLogger()
|
|
|
|
|
|
scripts/kernel-doc.py: add a Python parser
Maintaining kernel-doc has been a challenge, as there aren't many
perl developers among maintainers. Also, the logic there is too
complex. Having lots of global variables and using pure functions
doesn't help.
Rewrite the script in Python, placing most global variables
inside classes. This should help maintaining the script in long
term.
It also allows a better integration with kernel-doc Sphinx
extension in the future.
I opted to keep this version as close as possible to what we
have already in Perl. There are some differences though:
1. There is one regular expression that required a rewrite:
/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/
As this one uses two features that aren't available by the native
Python regular expression module (re):
- recursive patterns: ?1
- atomic grouping (?>...)
Rewrite it to use a much simpler regular expression:
/\bSTRUCT_GROUP\(([^\)]+)\)[^;]*;/
Extra care should be taken when validating this script, as such
replacement might cause some regressions.
2. The filters are now applied only during output generation.
In particular, "nosymbol" argument is only handled there.
It means that, if the same file is processed twice for
different symbols, the warnings will be duplicated.
I opted to use this behavior as it allows the Sphinx extension
to read the file(s) only once, and apply the filtering only
when producing the ReST output. This hopefully will help
to speed up doc generation
3. This version can handle multiple files and multiple directories.
So, if one just wants to produce a big output with everything
inside a file, this could be done with
$ time ./scripts/kernel-doc.py -man . 2>/dev/null >new
real 0m54.592s
user 0m53.345s
sys 0m0.997s
4. I tried to replicate as much as possible the same arguments
from kernel-doc, with about the same behavior, for the
command line parameters starting with a single dash (-parameter).
I also added one letter aliases for each parameter, and a
--parameter (sometimes with a better name).
5. There are some sutile nuances between how Perl handles
certain regular expressions. In special, the qr operatior,
which compiles a regular expression also works as a
non-capturing group. It means that some regexes like
this one:
my $type1 = qr{[\w\s]+};
needs to be mapped as:
type1 = r'(?:[\w\s]+)?'
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/2fa671a9fb08d03a376a42d46cc0b1d3aab4ae3f.1744106241.git.mchehab+huawei@kernel.org
2025-04-08 18:09:06 +08:00
|
|
|
if not args.debug:
|
2025-04-08 18:09:07 +08:00
|
|
|
logger.setLevel(logging.INFO)
|
scripts/kernel-doc.py: add a Python parser
Maintaining kernel-doc has been a challenge, as there aren't many
perl developers among maintainers. Also, the logic there is too
complex. Having lots of global variables and using pure functions
doesn't help.
Rewrite the script in Python, placing most global variables
inside classes. This should help maintaining the script in long
term.
It also allows a better integration with kernel-doc Sphinx
extension in the future.
I opted to keep this version as close as possible to what we
have already in Perl. There are some differences though:
1. There is one regular expression that required a rewrite:
/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/
As this one uses two features that aren't available by the native
Python regular expression module (re):
- recursive patterns: ?1
- atomic grouping (?>...)
Rewrite it to use a much simpler regular expression:
/\bSTRUCT_GROUP\(([^\)]+)\)[^;]*;/
Extra care should be taken when validating this script, as such
replacement might cause some regressions.
2. The filters are now applied only during output generation.
In particular, "nosymbol" argument is only handled there.
It means that, if the same file is processed twice for
different symbols, the warnings will be duplicated.
I opted to use this behavior as it allows the Sphinx extension
to read the file(s) only once, and apply the filtering only
when producing the ReST output. This hopefully will help
to speed up doc generation
3. This version can handle multiple files and multiple directories.
So, if one just wants to produce a big output with everything
inside a file, this could be done with
$ time ./scripts/kernel-doc.py -man . 2>/dev/null >new
real 0m54.592s
user 0m53.345s
sys 0m0.997s
4. I tried to replicate as much as possible the same arguments
from kernel-doc, with about the same behavior, for the
command line parameters starting with a single dash (-parameter).
I also added one letter aliases for each parameter, and a
--parameter (sometimes with a better name).
5. There are some sutile nuances between how Perl handles
certain regular expressions. In special, the qr operatior,
which compiles a regular expression also works as a
non-capturing group. It means that some regexes like
this one:
my $type1 = qr{[\w\s]+};
needs to be mapped as:
type1 = r'(?:[\w\s]+)?'
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/2fa671a9fb08d03a376a42d46cc0b1d3aab4ae3f.1744106241.git.mchehab+huawei@kernel.org
2025-04-08 18:09:06 +08:00
|
|
|
else:
|
2025-04-08 18:09:07 +08:00
|
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
|
|
|
|
|
|
formatter = MsgFormatter('%(levelname)s: %(message)s')
|
|
|
|
|
|
|
|
|
|
handler = logging.StreamHandler()
|
|
|
|
|
handler.setFormatter(formatter)
|
|
|
|
|
|
|
|
|
|
logger.addHandler(handler)
|
scripts/kernel-doc.py: add a Python parser
Maintaining kernel-doc has been a challenge, as there aren't many
perl developers among maintainers. Also, the logic there is too
complex. Having lots of global variables and using pure functions
doesn't help.
Rewrite the script in Python, placing most global variables
inside classes. This should help maintaining the script in long
term.
It also allows a better integration with kernel-doc Sphinx
extension in the future.
I opted to keep this version as close as possible to what we
have already in Perl. There are some differences though:
1. There is one regular expression that required a rewrite:
/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/
As this one uses two features that aren't available by the native
Python regular expression module (re):
- recursive patterns: ?1
- atomic grouping (?>...)
Rewrite it to use a much simpler regular expression:
/\bSTRUCT_GROUP\(([^\)]+)\)[^;]*;/
Extra care should be taken when validating this script, as such
replacement might cause some regressions.
2. The filters are now applied only during output generation.
In particular, "nosymbol" argument is only handled there.
It means that, if the same file is processed twice for
different symbols, the warnings will be duplicated.
I opted to use this behavior as it allows the Sphinx extension
to read the file(s) only once, and apply the filtering only
when producing the ReST output. This hopefully will help
to speed up doc generation
3. This version can handle multiple files and multiple directories.
So, if one just wants to produce a big output with everything
inside a file, this could be done with
$ time ./scripts/kernel-doc.py -man . 2>/dev/null >new
real 0m54.592s
user 0m53.345s
sys 0m0.997s
4. I tried to replicate as much as possible the same arguments
from kernel-doc, with about the same behavior, for the
command line parameters starting with a single dash (-parameter).
I also added one letter aliases for each parameter, and a
--parameter (sometimes with a better name).
5. There are some sutile nuances between how Perl handles
certain regular expressions. In special, the qr operatior,
which compiles a regular expression also works as a
non-capturing group. It means that some regexes like
this one:
my $type1 = qr{[\w\s]+};
needs to be mapped as:
type1 = r'(?:[\w\s]+)?'
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Link: https://lore.kernel.org/r/2fa671a9fb08d03a376a42d46cc0b1d3aab4ae3f.1744106241.git.mchehab+huawei@kernel.org
2025-04-08 18:09:06 +08:00
|
|
|
|
|
|
|
|
if args.man:
|
|
|
|
|
out_style = ManFormat()
|
|
|
|
|
elif args.none:
|
|
|
|
|
out_style = None
|
|
|
|
|
else:
|
|
|
|
|
out_style = RestFormat()
|
|
|
|
|
|
|
|
|
|
kfiles = KernelFiles(files=args.files, verbose=args.verbose,
|
|
|
|
|
out_style=out_style, werror=args.werror,
|
|
|
|
|
wreturn=args.wreturn, wshort_desc=args.wshort_desc,
|
|
|
|
|
wcontents_before_sections=args.wcontents_before_sections,
|
|
|
|
|
modulename=args.modulename,
|
|
|
|
|
export_file=args.export_file)
|
|
|
|
|
|
|
|
|
|
kfiles.parse()
|
|
|
|
|
|
|
|
|
|
kfiles.msg(enable_lineno=args.enable_lineno, export=args.export,
|
|
|
|
|
internal=args.internal, symbol=args.symbol,
|
|
|
|
|
nosymbol=args.nosymbol)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Call main method
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|