2 # SPDX-License-Identifier: GPL-2.0
8 Implementation of the ``kernel-feat`` reST-directive.
10 :copyright: Copyright (C) 2016 Markus Heiser
11 :copyright: Copyright (C) 2016-2019 Mauro Carvalho Chehab
12 :maintained-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
13 :license: GPL Version 2, June 1991 see Linux/COPYING for details.
15 The ``kernel-feat`` (:py:class:`KernelFeat`) directive calls the
16 scripts/get_feat.pl script to parse the Kernel ABI files.
18 Overview of directive's argument and options.
22 .. kernel-feat:: <ABI directory location>
25 The argument ``<ABI directory location>`` is required. It contains the
26 location of the ABI files to be parsed.
29 Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
30 what reST is generated.
41 from docutils import nodes, statemachine
42 from docutils.statemachine import ViewList
43 from docutils.parsers.rst import directives, Directive
44 from docutils.utils.error_reporting import ErrorString
47 # AutodocReporter is only good up to Sphinx 1.7
51 Use_SSI = sphinx.__version__[:3] >= '1.7'
53 from sphinx.util.docutils import switch_source_input
55 from sphinx.ext.autodoc import AutodocReporter
61 app.add_directive("kernel-feat", KernelFeat)
64 , parallel_read_safe = True
65 , parallel_write_safe = True
68 class KernelFeat(Directive):
70 u"""KernelFeat (``kernel-feat``) directive"""
72 required_arguments = 1
73 optional_arguments = 2
75 final_argument_whitespace = True
78 "debug" : directives.flag
81 def warn(self, message, **replace):
82 replace["fname"] = self.state.document.current_source
83 replace["line_no"] = replace.get("line_no", self.lineno)
84 message = ("%(fname)s:%(line_no)s: [kernel-feat WARN] : " + message) % replace
85 self.state.document.settings.env.app.warn(message, prefix="")
89 doc = self.state.document
90 if not doc.settings.file_insertion_enabled:
91 raise self.warning("docutils: file insertion disabled")
93 env = doc.settings.env
94 cwd = path.dirname(doc.current_source)
95 cmd = "get_feat.pl rest --dir "
96 cmd += self.arguments[0]
98 if len(self.arguments) > 1:
99 cmd += " --arch " + self.arguments[1]
101 srctree = path.abspath(os.environ["srctree"])
105 # extend PATH with $(srctree)/scripts
106 path_env = os.pathsep.join([
107 srctree + os.sep + "scripts",
110 shell_env = os.environ.copy()
111 shell_env["PATH"] = path_env
112 shell_env["srctree"] = srctree
114 lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
115 nodeList = self.nestedParse(lines, fname)
118 def runCmd(self, cmd, **kwargs):
119 u"""Run command ``cmd`` and return it's stdout as unicode."""
122 proc = subprocess.Popen(
124 , stdout = subprocess.PIPE
125 , stderr = subprocess.PIPE
128 out, err = proc.communicate()
130 out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
132 if proc.returncode != 0:
134 u"command '%s' failed with return code %d"
135 % (cmd, proc.returncode)
137 except OSError as exc:
138 raise self.severe(u"problems with '%s' directive: %s."
139 % (self.name, ErrorString(exc)))
142 def nestedParse(self, lines, fname):
144 node = nodes.section()
146 if "debug" in self.options:
147 code_block = "\n\n.. code-block:: rst\n :linenos:\n"
148 for l in lines.split("\n"):
149 code_block += "\n " + l
150 lines = code_block + "\n\n"
152 for c, l in enumerate(lines.split("\n")):
153 content.append(l, fname, c)
155 buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
158 with switch_source_input(self.state, content):
159 self.state.nested_parse(content, 0, node, match_titles=1)
161 self.state.memo.title_styles = []
162 self.state.memo.section_level = 0
163 self.state.memo.reporter = AutodocReporter(content, self.state.memo.reporter)
165 self.state.nested_parse(content, 0, node, match_titles=1)
167 self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf