mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
tools: docs: parse-headers.py: move it from sphinx dir
As suggested by Jon, we should start having a tools/docs directory, instead of placing everything under scripts. In the specific case of parse-headers.py, the previous location is where we're placing Sphinx extensions, which is not the right place for execs. Move it to tools/docs/parse-headers.py. Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Signed-off-by: Jonathan Corbet <corbet@lwn.net> Link: https://lore.kernel.org/r/0f5ac2d704cffe9834e589b39549d2393e1237ef.1755872208.git.mchehab+huawei@kernel.org
This commit is contained in:
committed by
Jonathan Corbet
parent
37497a4dc5
commit
cde494660f
@@ -1,2 +1,2 @@
|
|||||||
[MASTER]
|
[MASTER]
|
||||||
init-hook='import sys; sys.path += ["scripts/lib/kdoc", "scripts/lib/abi"]'
|
init-hook='import sys; sys.path += ["scripts/lib/kdoc", "scripts/lib/abi", "tools/docs/lib"]'
|
||||||
|
|||||||
0
tools/docs/lib/__init__.py
Normal file
0
tools/docs/lib/__init__.py
Normal file
70
tools/docs/lib/enrich_formatter.py
Normal file
70
tools/docs/lib/enrich_formatter.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
# Copyright (c) 2025 by Mauro Carvalho Chehab <mchehab@kernel.org>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Ancillary argparse HelpFormatter class that works on a similar way as
|
||||||
|
argparse.RawDescriptionHelpFormatter, e.g. description maintains line
|
||||||
|
breaks, but it also implement transformations to the help text. The
|
||||||
|
actual transformations ar given by enrich_text(), if the output is tty.
|
||||||
|
|
||||||
|
Currently, the follow transformations are done:
|
||||||
|
|
||||||
|
- Positional arguments are shown in upper cases;
|
||||||
|
- if output is TTY, ``var`` and positional arguments are shown prepended
|
||||||
|
by an ANSI SGR code. This is usually translated to bold. On some
|
||||||
|
terminals, like, konsole, this is translated into a colored bold text.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
class EnrichFormatter(argparse.HelpFormatter):
|
||||||
|
"""
|
||||||
|
Better format the output, making easier to identify the positional args
|
||||||
|
and how they're used at the __doc__ description.
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""Initialize class and check if is TTY"""
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self._tty = sys.stdout.isatty()
|
||||||
|
|
||||||
|
def enrich_text(self, text):
|
||||||
|
"""Handle ReST markups (currently, only ``foo``)"""
|
||||||
|
if self._tty and text:
|
||||||
|
# Replace ``text`` with ANSI SGR (bold)
|
||||||
|
return re.sub(r'\`\`(.+?)\`\`',
|
||||||
|
lambda m: f'\033[1m{m.group(1)}\033[0m', text)
|
||||||
|
return text
|
||||||
|
|
||||||
|
def _fill_text(self, text, width, indent):
|
||||||
|
"""Enrich descriptions with markups on it"""
|
||||||
|
enriched = self.enrich_text(text)
|
||||||
|
return "\n".join(indent + line for line in enriched.splitlines())
|
||||||
|
|
||||||
|
def _format_usage(self, usage, actions, groups, prefix):
|
||||||
|
"""Enrich positional arguments at usage: line"""
|
||||||
|
|
||||||
|
prog = self._prog
|
||||||
|
parts = []
|
||||||
|
|
||||||
|
for action in actions:
|
||||||
|
if action.option_strings:
|
||||||
|
opt = action.option_strings[0]
|
||||||
|
if action.nargs != 0:
|
||||||
|
opt += f" {action.dest.upper()}"
|
||||||
|
parts.append(f"[{opt}]")
|
||||||
|
else:
|
||||||
|
# Positional argument
|
||||||
|
parts.append(self.enrich_text(f"``{action.dest.upper()}``"))
|
||||||
|
|
||||||
|
usage_text = f"{prefix or 'usage: '} {prog} {' '.join(parts)}\n"
|
||||||
|
return usage_text
|
||||||
|
|
||||||
|
def _format_action_invocation(self, action):
|
||||||
|
"""Enrich argument names"""
|
||||||
|
if not action.option_strings:
|
||||||
|
return self.enrich_text(f"``{action.dest.upper()}``")
|
||||||
|
|
||||||
|
return ", ".join(action.option_strings)
|
||||||
@@ -1,36 +1,32 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
# Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@kernel.org>.
|
# Copyright (c) 2016-2025 by Mauro Carvalho Chehab <mchehab@kernel.org>.
|
||||||
# pylint: disable=C0103,R0902,R0912,R0914,R0915
|
# pylint: disable=R0912,R0915
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Convert a C header or source file ``FILE_IN``, into a ReStructured Text
|
Parse a source file or header, creating ReStructured Text cross references.
|
||||||
included via ..parsed-literal block with cross-references for the
|
|
||||||
documentation files that describe the API. It accepts an optional
|
|
||||||
``FILE_RULES`` file to describes what elements will be either ignored or
|
|
||||||
be pointed to a non-default reference type/name.
|
|
||||||
|
|
||||||
The output is written at ``FILE_OUT``.
|
It accepts an optional file to change the default symbol reference or to
|
||||||
|
suppress symbols from the output.
|
||||||
|
|
||||||
It is capable of identifying defines, functions, structs, typedefs,
|
It is capable of identifying defines, functions, structs, typedefs,
|
||||||
enums and enum symbols and create cross-references for all of them.
|
enums and enum symbols and create cross-references for all of them.
|
||||||
It is also capable of distinguish #define used for specifying a Linux
|
It is also capable of distinguish #define used for specifying a Linux
|
||||||
ioctl.
|
ioctl.
|
||||||
|
|
||||||
The optional ``FILE_RULES`` contains a set of rules like:
|
The optional rules file contains a set of rules like:
|
||||||
|
|
||||||
ignore ioctl VIDIOC_ENUM_FMT
|
ignore ioctl VIDIOC_ENUM_FMT
|
||||||
replace ioctl VIDIOC_DQBUF vidioc_qbuf
|
replace ioctl VIDIOC_DQBUF vidioc_qbuf
|
||||||
replace define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ :c:type:`v4l2_event_motion_det`
|
replace define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ :c:type:`v4l2_event_motion_det`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
class ParseHeader:
|
class ParseDataStructs:
|
||||||
"""
|
"""
|
||||||
Creates an enriched version of a Kernel header file with cross-links
|
Creates an enriched version of a Kernel header file with cross-links
|
||||||
to each C data structure type.
|
to each C data structure type.
|
||||||
@@ -400,80 +396,3 @@ class ParseHeader:
|
|||||||
f.write("=" * len(title))
|
f.write("=" * len(title))
|
||||||
f.write("\n\n.. parsed-literal::\n\n")
|
f.write("\n\n.. parsed-literal::\n\n")
|
||||||
f.write(text)
|
f.write(text)
|
||||||
|
|
||||||
class EnrichFormatter(argparse.HelpFormatter):
|
|
||||||
"""
|
|
||||||
Better format the output, making easier to identify the positional args
|
|
||||||
and how they're used at the __doc__ description.
|
|
||||||
"""
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
"""Initialize class and check if is TTY"""
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self._tty = sys.stdout.isatty()
|
|
||||||
|
|
||||||
def enrich_text(self, text):
|
|
||||||
"""Handle ReST markups (currently, only ``foo``)"""
|
|
||||||
if self._tty and text:
|
|
||||||
# Replace ``text`` with ANSI bold
|
|
||||||
return re.sub(r'\`\`(.+?)\`\`',
|
|
||||||
lambda m: f'\033[1m{m.group(1)}\033[0m', text)
|
|
||||||
return text
|
|
||||||
|
|
||||||
def _fill_text(self, text, width, indent):
|
|
||||||
"""Enrich descriptions with markups on it"""
|
|
||||||
enriched = self.enrich_text(text)
|
|
||||||
return "\n".join(indent + line for line in enriched.splitlines())
|
|
||||||
|
|
||||||
def _format_usage(self, usage, actions, groups, prefix):
|
|
||||||
"""Enrich positional arguments at usage: line"""
|
|
||||||
|
|
||||||
prog = self._prog
|
|
||||||
parts = []
|
|
||||||
|
|
||||||
for action in actions:
|
|
||||||
if action.option_strings:
|
|
||||||
opt = action.option_strings[0]
|
|
||||||
if action.nargs != 0:
|
|
||||||
opt += f" {action.dest.upper()}"
|
|
||||||
parts.append(f"[{opt}]")
|
|
||||||
else:
|
|
||||||
# Positional argument
|
|
||||||
parts.append(self.enrich_text(f"``{action.dest.upper()}``"))
|
|
||||||
|
|
||||||
usage_text = f"{prefix or 'usage: '} {prog} {' '.join(parts)}\n"
|
|
||||||
return usage_text
|
|
||||||
|
|
||||||
def _format_action_invocation(self, action):
|
|
||||||
"""Enrich argument names"""
|
|
||||||
if not action.option_strings:
|
|
||||||
return self.enrich_text(f"``{action.dest.upper()}``")
|
|
||||||
else:
|
|
||||||
return ", ".join(action.option_strings)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main function"""
|
|
||||||
parser = argparse.ArgumentParser(description=__doc__,
|
|
||||||
formatter_class=EnrichFormatter)
|
|
||||||
|
|
||||||
parser.add_argument("-d", "--debug", action="count", default=0,
|
|
||||||
help="Increase debug level. Can be used multiple times")
|
|
||||||
parser.add_argument("file_in", help="Input C file")
|
|
||||||
parser.add_argument("file_out", help="Output RST file")
|
|
||||||
parser.add_argument("file_rules", nargs="?",
|
|
||||||
help="Exceptions file (optional)")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
parser = ParseHeader(debug=args.debug)
|
|
||||||
parser.parse_file(args.file_in)
|
|
||||||
|
|
||||||
if args.file_rules:
|
|
||||||
parser.process_exceptions(args.file_rules)
|
|
||||||
|
|
||||||
parser.debug_print()
|
|
||||||
parser.write_output(args.file_in, args.file_out)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
57
tools/docs/parse-headers.py
Executable file
57
tools/docs/parse-headers.py
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
# Copyright (c) 2016, 2025 by Mauro Carvalho Chehab <mchehab@kernel.org>.
|
||||||
|
# pylint: disable=C0103
|
||||||
|
|
||||||
|
"""
|
||||||
|
Convert a C header or source file ``FILE_IN``, into a ReStructured Text
|
||||||
|
included via ..parsed-literal block with cross-references for the
|
||||||
|
documentation files that describe the API. It accepts an optional
|
||||||
|
``FILE_RULES`` file to describes what elements will be either ignored or
|
||||||
|
be pointed to a non-default reference type/name.
|
||||||
|
|
||||||
|
The output is written at ``FILE_OUT``.
|
||||||
|
|
||||||
|
It is capable of identifying defines, functions, structs, typedefs,
|
||||||
|
enums and enum symbols and create cross-references for all of them.
|
||||||
|
It is also capable of distinguish #define used for specifying a Linux
|
||||||
|
ioctl.
|
||||||
|
|
||||||
|
The optional ``FILE_RULES`` contains a set of rules like:
|
||||||
|
|
||||||
|
ignore ioctl VIDIOC_ENUM_FMT
|
||||||
|
replace ioctl VIDIOC_DQBUF vidioc_qbuf
|
||||||
|
replace define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ :c:type:`v4l2_event_motion_det`
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from lib.parse_data_structs import ParseDataStructs
|
||||||
|
from lib.enrich_formatter import EnrichFormatter
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function"""
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__,
|
||||||
|
formatter_class=EnrichFormatter)
|
||||||
|
|
||||||
|
parser.add_argument("-d", "--debug", action="count", default=0,
|
||||||
|
help="Increase debug level. Can be used multiple times")
|
||||||
|
parser.add_argument("file_in", help="Input C file")
|
||||||
|
parser.add_argument("file_out", help="Output RST file")
|
||||||
|
parser.add_argument("file_rules", nargs="?",
|
||||||
|
help="Exceptions file (optional)")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
parser = ParseDataStructs(debug=args.debug)
|
||||||
|
parser.parse_file(args.file_in)
|
||||||
|
|
||||||
|
if args.file_rules:
|
||||||
|
parser.process_exceptions(args.file_rules)
|
||||||
|
|
||||||
|
parser.debug_print()
|
||||||
|
parser.write_output(args.file_in, args.file_out)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user