Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1# coding=utf-8
2# SPDX-License-Identifier: GPL-2.0
3#
4"""
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 <mchehab+samsung@kernel.org>
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
36import re
37import subprocess
38import sys
39
40from docutils import nodes, statemachine
41from docutils.statemachine import ViewList
42from docutils.parsers.rst import directives, Directive
43from sphinx.util.docutils import switch_source_input
44
45def ErrorString(exc): # Shamelessly stolen from docutils
46 return f'{exc.__class__.__name}: {exc}'
47
48__version__ = '1.0'
49
50def setup(app):
51
52 app.add_directive("kernel-feat", KernelFeat)
53 return dict(
54 version = __version__
55 , parallel_read_safe = True
56 , parallel_write_safe = True
57 )
58
59class KernelFeat(Directive):
60
61 """KernelFeat (``kernel-feat``) directive"""
62
63 required_arguments = 1
64 optional_arguments = 2
65 has_content = False
66 final_argument_whitespace = True
67
68 option_spec = {
69 "debug" : directives.flag
70 }
71
72 def warn(self, message, **replace):
73 replace["fname"] = self.state.document.current_source
74 replace["line_no"] = replace.get("line_no", self.lineno)
75 message = ("%(fname)s:%(line_no)s: [kernel-feat WARN] : " + message) % replace
76 self.state.document.settings.env.app.warn(message, prefix="")
77
78 def run(self):
79 doc = self.state.document
80 if not doc.settings.file_insertion_enabled:
81 raise self.warning("docutils: file insertion disabled")
82
83 env = doc.settings.env
84
85 srctree = os.path.abspath(os.environ["srctree"])
86
87 args = [
88 os.path.join(srctree, 'scripts/get_feat.pl'),
89 'rest',
90 '--enable-fname',
91 '--dir',
92 os.path.join(srctree, 'Documentation', self.arguments[0]),
93 ]
94
95 if len(self.arguments) > 1:
96 args.extend(['--arch', self.arguments[1]])
97
98 lines = subprocess.check_output(args, cwd=os.path.dirname(doc.current_source)).decode('utf-8')
99
100 line_regex = re.compile(r"^\.\. FILE (\S+)$")
101
102 out_lines = ""
103
104 for line in lines.split("\n"):
105 match = line_regex.search(line)
106 if match:
107 fname = match.group(1)
108
109 # Add the file to Sphinx build dependencies
110 env.note_dependency(os.path.abspath(fname))
111 else:
112 out_lines += line + "\n"
113
114 nodeList = self.nestedParse(out_lines, self.arguments[0])
115 return nodeList
116
117 def nestedParse(self, lines, fname):
118 content = ViewList()
119 node = nodes.section()
120
121 if "debug" in self.options:
122 code_block = "\n\n.. code-block:: rst\n :linenos:\n"
123 for l in lines.split("\n"):
124 code_block += "\n " + l
125 lines = code_block + "\n\n"
126
127 for c, l in enumerate(lines.split("\n")):
128 content.append(l, fname, c)
129
130 buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
131
132 with switch_source_input(self.state, content):
133 self.state.nested_parse(content, 0, node, match_titles=1)
134
135 return node.children