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