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