blob: 03ace5f01b5c021e12adba23b83b8cb074c949ba [file] [log] [blame]
Mauro Carvalho Chehabb9721222020-11-30 16:36:33 +01001# coding=utf-8
2# SPDX-License-Identifier: GPL-2.0
3#
4u"""
5 kernel-feat
6 ~~~~~~~~~~~
7
8 Implementation of the ``kernel-feat`` reST-directive.
9
10 :copyright: Copyright (C) 2016 Markus Heiser
11 :copyright: Copyright (C) 2016-2019 Mauro Carvalho Chehab
12 :maintained-by: Mauro Carvalho Chehab <[email protected]>
13 :license: GPL Version 2, June 1991 see Linux/COPYING for details.
14
15 The ``kernel-feat`` (:py:class:`KernelFeat`) directive calls the
16 scripts/get_feat.pl script to parse the Kernel ABI files.
17
18 Overview of directive's argument and options.
19
20 .. code-block:: rst
21
22 .. kernel-feat:: <ABI directory location>
23 :debug:
24
25 The argument ``<ABI directory location>`` is required. It contains the
26 location of the ABI files to be parsed.
27
28 ``debug``
29 Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
30 what reST is generated.
31
32"""
33
34import codecs
35import os
Mauro Carvalho Chehab85999f02022-03-26 11:27:20 +010036import re
Mauro Carvalho Chehabb9721222020-11-30 16:36:33 +010037import subprocess
38import sys
39
Mauro Carvalho Chehabb9721222020-11-30 16:36:33 +010040from docutils import nodes, statemachine
41from docutils.statemachine import ViewList
42from docutils.parsers.rst import directives, Directive
43from docutils.utils.error_reporting import ErrorString
Jonathan Corbetf546ff02021-02-01 16:26:25 -070044from sphinx.util.docutils import switch_source_input
Mauro Carvalho Chehabb9721222020-11-30 16:36:33 +010045
46__version__ = '1.0'
47
48def setup(app):
49
50 app.add_directive("kernel-feat", KernelFeat)
51 return dict(
52 version = __version__
53 , parallel_read_safe = True
54 , parallel_write_safe = True
55 )
56
57class KernelFeat(Directive):
58
59 u"""KernelFeat (``kernel-feat``) directive"""
60
61 required_arguments = 1
62 optional_arguments = 2
63 has_content = False
64 final_argument_whitespace = True
65
66 option_spec = {
67 "debug" : directives.flag
68 }
69
70 def warn(self, message, **replace):
71 replace["fname"] = self.state.document.current_source
72 replace["line_no"] = replace.get("line_no", self.lineno)
73 message = ("%(fname)s:%(line_no)s: [kernel-feat WARN] : " + message) % replace
74 self.state.document.settings.env.app.warn(message, prefix="")
75
76 def run(self):
Mauro Carvalho Chehabb9721222020-11-30 16:36:33 +010077 doc = self.state.document
78 if not doc.settings.file_insertion_enabled:
79 raise self.warning("docutils: file insertion disabled")
80
81 env = doc.settings.env
Vegard Nossume961f8c62024-01-10 18:47:58 +010082
83 srctree = os.path.abspath(os.environ["srctree"])
84
85 args = [
86 os.path.join(srctree, 'scripts/get_feat.pl'),
87 'rest',
88 '--enable-fname',
89 '--dir',
90 os.path.join(srctree, 'Documentation', self.arguments[0]),
91 ]
Mauro Carvalho Chehabb9721222020-11-30 16:36:33 +010092
93 if len(self.arguments) > 1:
Vegard Nossume961f8c62024-01-10 18:47:58 +010094 args.extend(['--arch', self.arguments[1]])
Mauro Carvalho Chehabb9721222020-11-30 16:36:33 +010095
Vegard Nossume961f8c62024-01-10 18:47:58 +010096 lines = subprocess.check_output(args, cwd=os.path.dirname(doc.current_source)).decode('utf-8')
Mauro Carvalho Chehab85999f02022-03-26 11:27:20 +010097
Benjamin Gray55ae38f2023-09-12 16:07:56 +100098 line_regex = re.compile(r"^\.\. FILE (\S+)$")
Mauro Carvalho Chehab85999f02022-03-26 11:27:20 +010099
100 out_lines = ""
101
102 for line in lines.split("\n"):
103 match = line_regex.search(line)
104 if match:
105 fname = match.group(1)
106
107 # Add the file to Sphinx build dependencies
108 env.note_dependency(os.path.abspath(fname))
109 else:
110 out_lines += line + "\n"
111
Vegard Nossum7366ff72024-02-05 18:51:26 +0100112 nodeList = self.nestedParse(out_lines, self.arguments[0])
Mauro Carvalho Chehabb9721222020-11-30 16:36:33 +0100113 return nodeList
114
Mauro Carvalho Chehabb9721222020-11-30 16:36:33 +0100115 def nestedParse(self, lines, fname):
116 content = ViewList()
117 node = nodes.section()
118
119 if "debug" in self.options:
120 code_block = "\n\n.. code-block:: rst\n :linenos:\n"
121 for l in lines.split("\n"):
122 code_block += "\n " + l
123 lines = code_block + "\n\n"
124
125 for c, l in enumerate(lines.split("\n")):
126 content.append(l, fname, c)
127
128 buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
129
Jonathan Corbetf546ff02021-02-01 16:26:25 -0700130 with switch_source_input(self.state, content):
131 self.state.nested_parse(content, 0, node, match_titles=1)
Mauro Carvalho Chehabb9721222020-11-30 16:36:33 +0100132
133 return node.children