blob: 8601a3b75a28ea8f1c8bca532ca9bc2f3598aa7e [file] [log] [blame]
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +01001# -*- coding: utf-8; mode: python -*-
Mauro Carvalho Chehab823830d2020-10-30 08:40:32 +01002# coding=utf-8
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +01003# SPDX-License-Identifier: GPL-2.0
Mauro Carvalho Chehab823830d2020-10-30 08:40:32 +01004#
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +01005u"""
6 kernel-abi
7 ~~~~~~~~~~
8
9 Implementation of the ``kernel-abi`` reST-directive.
10
11 :copyright: Copyright (C) 2016 Markus Heiser
12 :copyright: Copyright (C) 2016-2020 Mauro Carvalho Chehab
13 :maintained-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
14 :license: GPL Version 2, June 1991 see Linux/COPYING for details.
15
16 The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the
17 scripts/get_abi.pl script to parse the Kernel ABI files.
18
19 Overview of directive's argument and options.
20
21 .. code-block:: rst
22
23 .. kernel-abi:: <ABI directory location>
24 :debug:
25
26 The argument ``<ABI directory location>`` is required. It contains the
27 location of the ABI files to be parsed.
28
29 ``debug``
30 Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
31 what reST is generated.
32
33"""
34
Mauro Carvalho Chehab823830d2020-10-30 08:40:32 +010035import codecs
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +010036import os
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +010037import subprocess
Mauro Carvalho Chehabc830fa92020-10-30 08:40:33 +010038import sys
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +010039
Mauro Carvalho Chehabc830fa92020-10-30 08:40:33 +010040from os import path
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +010041
Mauro Carvalho Chehabc830fa92020-10-30 08:40:33 +010042from docutils import nodes, statemachine
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +010043from docutils.statemachine import ViewList
Mauro Carvalho Chehabc830fa92020-10-30 08:40:33 +010044from docutils.parsers.rst import directives, Directive
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +010045from docutils.utils.error_reporting import ErrorString
46
Mauro Carvalho Chehabc830fa92020-10-30 08:40:33 +010047#
48# AutodocReporter is only good up to Sphinx 1.7
49#
50import sphinx
51
52Use_SSI = sphinx.__version__[:3] >= '1.7'
53if Use_SSI:
54 from sphinx.util.docutils import switch_source_input
55else:
56 from sphinx.ext.autodoc import AutodocReporter
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +010057
58__version__ = '1.0'
59
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +010060def setup(app):
61
62 app.add_directive("kernel-abi", KernelCmd)
63 return dict(
64 version = __version__
65 , parallel_read_safe = True
66 , parallel_write_safe = True
67 )
68
69class KernelCmd(Directive):
70
71 u"""KernelABI (``kernel-abi``) directive"""
72
73 required_arguments = 1
74 optional_arguments = 0
75 has_content = False
76 final_argument_whitespace = True
77
78 option_spec = {
79 "debug" : directives.flag
80 }
81
82 def warn(self, message, **replace):
83 replace["fname"] = self.state.document.current_source
84 replace["line_no"] = replace.get("line_no", self.lineno)
85 message = ("%(fname)s:%(line_no)s: [kernel-abi WARN] : " + message) % replace
86 self.state.document.settings.env.app.warn(message, prefix="")
87
88 def run(self):
89
90 doc = self.state.document
91 if not doc.settings.file_insertion_enabled:
92 raise self.warning("docutils: file insertion disabled")
93
94 env = doc.settings.env
95 cwd = path.dirname(doc.current_source)
96 cmd = "get_abi.pl rest --dir "
97 cmd += self.arguments[0]
98
99 srctree = path.abspath(os.environ["srctree"])
100
101 fname = cmd
102
103 # extend PATH with $(srctree)/scripts
104 path_env = os.pathsep.join([
105 srctree + os.sep + "scripts",
106 os.environ["PATH"]
107 ])
108 shell_env = os.environ.copy()
109 shell_env["PATH"] = path_env
110 shell_env["srctree"] = srctree
111
112 lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
113 nodeList = self.nestedParse(lines, fname)
114 return nodeList
115
116 def runCmd(self, cmd, **kwargs):
117 u"""Run command ``cmd`` and return it's stdout as unicode."""
118
119 try:
120 proc = subprocess.Popen(
121 cmd
122 , stdout = subprocess.PIPE
123 , stderr = subprocess.PIPE
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +0100124 , **kwargs
125 )
126 out, err = proc.communicate()
Mauro Carvalho Chehab823830d2020-10-30 08:40:32 +0100127
128 out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
129
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +0100130 if proc.returncode != 0:
131 raise self.severe(
132 u"command '%s' failed with return code %d"
133 % (cmd, proc.returncode)
134 )
135 except OSError as exc:
136 raise self.severe(u"problems with '%s' directive: %s."
137 % (self.name, ErrorString(exc)))
Mauro Carvalho Chehab823830d2020-10-30 08:40:32 +0100138 return out
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +0100139
140 def nestedParse(self, lines, fname):
141 content = ViewList()
142 node = nodes.section()
143
144 if "debug" in self.options:
145 code_block = "\n\n.. code-block:: rst\n :linenos:\n"
146 for l in lines.split("\n"):
147 code_block += "\n " + l
148 lines = code_block + "\n\n"
149
150 for c, l in enumerate(lines.split("\n")):
151 content.append(l, fname, c)
152
153 buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
Mauro Carvalho Chehabc830fa92020-10-30 08:40:33 +0100154
155 if Use_SSI:
156 with switch_source_input(self.state, content):
157 self.state.nested_parse(content, 0, node, match_titles=1)
158 else:
159 self.state.memo.title_styles = []
160 self.state.memo.section_level = 0
161 self.state.memo.reporter = AutodocReporter(content, self.state.memo.reporter)
162 try:
163 self.state.nested_parse(content, 0, node, match_titles=1)
164 finally:
165 self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
166
Mauro Carvalho Chehab9ca876f2020-10-30 08:40:31 +0100167 return node.children