1b9721225SMauro Carvalho Chehab# coding=utf-8 2b9721225SMauro Carvalho Chehab# SPDX-License-Identifier: GPL-2.0 3b9721225SMauro Carvalho Chehab# 4b9721225SMauro Carvalho Chehabu""" 5b9721225SMauro Carvalho Chehab kernel-feat 6b9721225SMauro Carvalho Chehab ~~~~~~~~~~~ 7b9721225SMauro Carvalho Chehab 8b9721225SMauro Carvalho Chehab Implementation of the ``kernel-feat`` reST-directive. 9b9721225SMauro Carvalho Chehab 10b9721225SMauro Carvalho Chehab :copyright: Copyright (C) 2016 Markus Heiser 11b9721225SMauro Carvalho Chehab :copyright: Copyright (C) 2016-2019 Mauro Carvalho Chehab 12b9721225SMauro Carvalho Chehab :maintained-by: Mauro Carvalho Chehab <[email protected]> 13b9721225SMauro Carvalho Chehab :license: GPL Version 2, June 1991 see Linux/COPYING for details. 14b9721225SMauro Carvalho Chehab 15b9721225SMauro Carvalho Chehab The ``kernel-feat`` (:py:class:`KernelFeat`) directive calls the 16b9721225SMauro Carvalho Chehab scripts/get_feat.pl script to parse the Kernel ABI files. 17b9721225SMauro Carvalho Chehab 18b9721225SMauro Carvalho Chehab Overview of directive's argument and options. 19b9721225SMauro Carvalho Chehab 20b9721225SMauro Carvalho Chehab .. code-block:: rst 21b9721225SMauro Carvalho Chehab 22b9721225SMauro Carvalho Chehab .. kernel-feat:: <ABI directory location> 23b9721225SMauro Carvalho Chehab :debug: 24b9721225SMauro Carvalho Chehab 25b9721225SMauro Carvalho Chehab The argument ``<ABI directory location>`` is required. It contains the 26b9721225SMauro Carvalho Chehab location of the ABI files to be parsed. 27b9721225SMauro Carvalho Chehab 28b9721225SMauro Carvalho Chehab ``debug`` 29b9721225SMauro Carvalho Chehab Inserts a code-block with the *raw* reST. Sometimes it is helpful to see 30b9721225SMauro Carvalho Chehab what reST is generated. 31b9721225SMauro Carvalho Chehab 32b9721225SMauro Carvalho Chehab""" 33b9721225SMauro Carvalho Chehab 34b9721225SMauro Carvalho Chehabimport codecs 35b9721225SMauro Carvalho Chehabimport os 3685999f03SMauro Carvalho Chehabimport re 37b9721225SMauro Carvalho Chehabimport subprocess 38b9721225SMauro Carvalho Chehabimport sys 39b9721225SMauro Carvalho Chehab 40b9721225SMauro Carvalho Chehabfrom os import path 41b9721225SMauro Carvalho Chehab 42b9721225SMauro Carvalho Chehabfrom docutils import nodes, statemachine 43b9721225SMauro Carvalho Chehabfrom docutils.statemachine import ViewList 44b9721225SMauro Carvalho Chehabfrom docutils.parsers.rst import directives, Directive 45b9721225SMauro Carvalho Chehabfrom docutils.utils.error_reporting import ErrorString 46b9721225SMauro Carvalho Chehabfrom sphinx.util.docutils import switch_source_input 47b9721225SMauro Carvalho Chehab 48b9721225SMauro Carvalho Chehab__version__ = '1.0' 49b9721225SMauro Carvalho Chehab 50b9721225SMauro Carvalho Chehabdef setup(app): 51b9721225SMauro Carvalho Chehab 52b9721225SMauro Carvalho Chehab app.add_directive("kernel-feat", KernelFeat) 53b9721225SMauro Carvalho Chehab return dict( 54b9721225SMauro Carvalho Chehab version = __version__ 55b9721225SMauro Carvalho Chehab , parallel_read_safe = True 56b9721225SMauro Carvalho Chehab , parallel_write_safe = True 57b9721225SMauro Carvalho Chehab ) 58b9721225SMauro Carvalho Chehab 59b9721225SMauro Carvalho Chehabclass KernelFeat(Directive): 60b9721225SMauro Carvalho Chehab 61b9721225SMauro Carvalho Chehab u"""KernelFeat (``kernel-feat``) directive""" 62b9721225SMauro Carvalho Chehab 63b9721225SMauro Carvalho Chehab required_arguments = 1 64b9721225SMauro Carvalho Chehab optional_arguments = 2 65b9721225SMauro Carvalho Chehab has_content = False 66b9721225SMauro Carvalho Chehab final_argument_whitespace = True 67b9721225SMauro Carvalho Chehab 68b9721225SMauro Carvalho Chehab option_spec = { 69b9721225SMauro Carvalho Chehab "debug" : directives.flag 70b9721225SMauro Carvalho Chehab } 71b9721225SMauro Carvalho Chehab 72b9721225SMauro Carvalho Chehab def warn(self, message, **replace): 73b9721225SMauro Carvalho Chehab replace["fname"] = self.state.document.current_source 74b9721225SMauro Carvalho Chehab replace["line_no"] = replace.get("line_no", self.lineno) 75b9721225SMauro Carvalho Chehab message = ("%(fname)s:%(line_no)s: [kernel-feat WARN] : " + message) % replace 76b9721225SMauro Carvalho Chehab self.state.document.settings.env.app.warn(message, prefix="") 77b9721225SMauro Carvalho Chehab 78b9721225SMauro Carvalho Chehab def run(self): 79b9721225SMauro Carvalho Chehab 80b9721225SMauro Carvalho Chehab doc = self.state.document 81b9721225SMauro Carvalho Chehab if not doc.settings.file_insertion_enabled: 82b9721225SMauro Carvalho Chehab raise self.warning("docutils: file insertion disabled") 83b9721225SMauro Carvalho Chehab 84b9721225SMauro Carvalho Chehab env = doc.settings.env 85b9721225SMauro Carvalho Chehab cwd = path.dirname(doc.current_source) 8685999f03SMauro Carvalho Chehab cmd = "get_feat.pl rest --enable-fname --dir " 87b9721225SMauro Carvalho Chehab cmd += self.arguments[0] 88b9721225SMauro Carvalho Chehab 89b9721225SMauro Carvalho Chehab if len(self.arguments) > 1: 90b9721225SMauro Carvalho Chehab cmd += " --arch " + self.arguments[1] 91b9721225SMauro Carvalho Chehab 92b9721225SMauro Carvalho Chehab srctree = path.abspath(os.environ["srctree"]) 93b9721225SMauro Carvalho Chehab 94b9721225SMauro Carvalho Chehab fname = cmd 95b9721225SMauro Carvalho Chehab 96b9721225SMauro Carvalho Chehab # extend PATH with $(srctree)/scripts 97b9721225SMauro Carvalho Chehab path_env = os.pathsep.join([ 98b9721225SMauro Carvalho Chehab srctree + os.sep + "scripts", 99b9721225SMauro Carvalho Chehab os.environ["PATH"] 100b9721225SMauro Carvalho Chehab ]) 101b9721225SMauro Carvalho Chehab shell_env = os.environ.copy() 102b9721225SMauro Carvalho Chehab shell_env["PATH"] = path_env 103b9721225SMauro Carvalho Chehab shell_env["srctree"] = srctree 104b9721225SMauro Carvalho Chehab 105b9721225SMauro Carvalho Chehab lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env) 10685999f03SMauro Carvalho Chehab 107*86a0adc0SBenjamin Gray line_regex = re.compile(r"^\.\. FILE (\S+)$") 10885999f03SMauro Carvalho Chehab 10985999f03SMauro Carvalho Chehab out_lines = "" 11085999f03SMauro Carvalho Chehab 11185999f03SMauro Carvalho Chehab for line in lines.split("\n"): 11285999f03SMauro Carvalho Chehab match = line_regex.search(line) 11385999f03SMauro Carvalho Chehab if match: 11485999f03SMauro Carvalho Chehab fname = match.group(1) 11585999f03SMauro Carvalho Chehab 11685999f03SMauro Carvalho Chehab # Add the file to Sphinx build dependencies 11785999f03SMauro Carvalho Chehab env.note_dependency(os.path.abspath(fname)) 11885999f03SMauro Carvalho Chehab else: 11985999f03SMauro Carvalho Chehab out_lines += line + "\n" 12085999f03SMauro Carvalho Chehab 12185999f03SMauro Carvalho Chehab nodeList = self.nestedParse(out_lines, fname) 122b9721225SMauro Carvalho Chehab return nodeList 123b9721225SMauro Carvalho Chehab 124b9721225SMauro Carvalho Chehab def runCmd(self, cmd, **kwargs): 12532211146SRandy Dunlap u"""Run command ``cmd`` and return its stdout as unicode.""" 126b9721225SMauro Carvalho Chehab 127b9721225SMauro Carvalho Chehab try: 128b9721225SMauro Carvalho Chehab proc = subprocess.Popen( 129b9721225SMauro Carvalho Chehab cmd 130b9721225SMauro Carvalho Chehab , stdout = subprocess.PIPE 131b9721225SMauro Carvalho Chehab , stderr = subprocess.PIPE 132b9721225SMauro Carvalho Chehab , **kwargs 133b9721225SMauro Carvalho Chehab ) 134b9721225SMauro Carvalho Chehab out, err = proc.communicate() 135b9721225SMauro Carvalho Chehab 136b9721225SMauro Carvalho Chehab out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8') 137b9721225SMauro Carvalho Chehab 138b9721225SMauro Carvalho Chehab if proc.returncode != 0: 139b9721225SMauro Carvalho Chehab raise self.severe( 140b9721225SMauro Carvalho Chehab u"command '%s' failed with return code %d" 141b9721225SMauro Carvalho Chehab % (cmd, proc.returncode) 142b9721225SMauro Carvalho Chehab ) 143b9721225SMauro Carvalho Chehab except OSError as exc: 144b9721225SMauro Carvalho Chehab raise self.severe(u"problems with '%s' directive: %s." 145b9721225SMauro Carvalho Chehab % (self.name, ErrorString(exc))) 146b9721225SMauro Carvalho Chehab return out 147b9721225SMauro Carvalho Chehab 148b9721225SMauro Carvalho Chehab def nestedParse(self, lines, fname): 149b9721225SMauro Carvalho Chehab content = ViewList() 150b9721225SMauro Carvalho Chehab node = nodes.section() 151b9721225SMauro Carvalho Chehab 152b9721225SMauro Carvalho Chehab if "debug" in self.options: 153b9721225SMauro Carvalho Chehab code_block = "\n\n.. code-block:: rst\n :linenos:\n" 154b9721225SMauro Carvalho Chehab for l in lines.split("\n"): 155b9721225SMauro Carvalho Chehab code_block += "\n " + l 156b9721225SMauro Carvalho Chehab lines = code_block + "\n\n" 157b9721225SMauro Carvalho Chehab 158b9721225SMauro Carvalho Chehab for c, l in enumerate(lines.split("\n")): 159b9721225SMauro Carvalho Chehab content.append(l, fname, c) 160b9721225SMauro Carvalho Chehab 161b9721225SMauro Carvalho Chehab buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter 162b9721225SMauro Carvalho Chehab 163b9721225SMauro Carvalho Chehab with switch_source_input(self.state, content): 164b9721225SMauro Carvalho Chehab self.state.nested_parse(content, 0, node, match_titles=1) 165b9721225SMauro Carvalho Chehab 166b9721225SMauro Carvalho Chehab return node.children 167