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