162306a36Sopenharmony_ci# coding=utf-8 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci# 462306a36Sopenharmony_ciu""" 562306a36Sopenharmony_ci kernel-feat 662306a36Sopenharmony_ci ~~~~~~~~~~~ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci Implementation of the ``kernel-feat`` reST-directive. 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci :copyright: Copyright (C) 2016 Markus Heiser 1162306a36Sopenharmony_ci :copyright: Copyright (C) 2016-2019 Mauro Carvalho Chehab 1262306a36Sopenharmony_ci :maintained-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> 1362306a36Sopenharmony_ci :license: GPL Version 2, June 1991 see Linux/COPYING for details. 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci The ``kernel-feat`` (:py:class:`KernelFeat`) directive calls the 1662306a36Sopenharmony_ci scripts/get_feat.pl script to parse the Kernel ABI files. 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci Overview of directive's argument and options. 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci .. code-block:: rst 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci .. kernel-feat:: <ABI directory location> 2362306a36Sopenharmony_ci :debug: 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci The argument ``<ABI directory location>`` is required. It contains the 2662306a36Sopenharmony_ci location of the ABI files to be parsed. 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci ``debug`` 2962306a36Sopenharmony_ci Inserts a code-block with the *raw* reST. Sometimes it is helpful to see 3062306a36Sopenharmony_ci what reST is generated. 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci""" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciimport codecs 3562306a36Sopenharmony_ciimport os 3662306a36Sopenharmony_ciimport re 3762306a36Sopenharmony_ciimport subprocess 3862306a36Sopenharmony_ciimport sys 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cifrom docutils import nodes, statemachine 4162306a36Sopenharmony_cifrom docutils.statemachine import ViewList 4262306a36Sopenharmony_cifrom docutils.parsers.rst import directives, Directive 4362306a36Sopenharmony_cifrom docutils.utils.error_reporting import ErrorString 4462306a36Sopenharmony_cifrom sphinx.util.docutils import switch_source_input 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci__version__ = '1.0' 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cidef setup(app): 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci app.add_directive("kernel-feat", KernelFeat) 5162306a36Sopenharmony_ci return dict( 5262306a36Sopenharmony_ci version = __version__ 5362306a36Sopenharmony_ci , parallel_read_safe = True 5462306a36Sopenharmony_ci , parallel_write_safe = True 5562306a36Sopenharmony_ci ) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciclass KernelFeat(Directive): 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci u"""KernelFeat (``kernel-feat``) directive""" 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci required_arguments = 1 6262306a36Sopenharmony_ci optional_arguments = 2 6362306a36Sopenharmony_ci has_content = False 6462306a36Sopenharmony_ci final_argument_whitespace = True 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci option_spec = { 6762306a36Sopenharmony_ci "debug" : directives.flag 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci def warn(self, message, **replace): 7162306a36Sopenharmony_ci replace["fname"] = self.state.document.current_source 7262306a36Sopenharmony_ci replace["line_no"] = replace.get("line_no", self.lineno) 7362306a36Sopenharmony_ci message = ("%(fname)s:%(line_no)s: [kernel-feat WARN] : " + message) % replace 7462306a36Sopenharmony_ci self.state.document.settings.env.app.warn(message, prefix="") 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci def run(self): 7762306a36Sopenharmony_ci doc = self.state.document 7862306a36Sopenharmony_ci if not doc.settings.file_insertion_enabled: 7962306a36Sopenharmony_ci raise self.warning("docutils: file insertion disabled") 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci env = doc.settings.env 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci srctree = os.path.abspath(os.environ["srctree"]) 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci args = [ 8662306a36Sopenharmony_ci os.path.join(srctree, 'scripts/get_feat.pl'), 8762306a36Sopenharmony_ci 'rest', 8862306a36Sopenharmony_ci '--enable-fname', 8962306a36Sopenharmony_ci '--dir', 9062306a36Sopenharmony_ci os.path.join(srctree, 'Documentation', self.arguments[0]), 9162306a36Sopenharmony_ci ] 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if len(self.arguments) > 1: 9462306a36Sopenharmony_ci args.extend(['--arch', self.arguments[1]]) 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci lines = subprocess.check_output(args, cwd=os.path.dirname(doc.current_source)).decode('utf-8') 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci line_regex = re.compile(r"^\.\. FILE (\S+)$") 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci out_lines = "" 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci for line in lines.split("\n"): 10362306a36Sopenharmony_ci match = line_regex.search(line) 10462306a36Sopenharmony_ci if match: 10562306a36Sopenharmony_ci fname = match.group(1) 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci # Add the file to Sphinx build dependencies 10862306a36Sopenharmony_ci env.note_dependency(os.path.abspath(fname)) 10962306a36Sopenharmony_ci else: 11062306a36Sopenharmony_ci out_lines += line + "\n" 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci nodeList = self.nestedParse(out_lines, self.arguments[0]) 11362306a36Sopenharmony_ci return nodeList 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci def nestedParse(self, lines, fname): 11662306a36Sopenharmony_ci content = ViewList() 11762306a36Sopenharmony_ci node = nodes.section() 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if "debug" in self.options: 12062306a36Sopenharmony_ci code_block = "\n\n.. code-block:: rst\n :linenos:\n" 12162306a36Sopenharmony_ci for l in lines.split("\n"): 12262306a36Sopenharmony_ci code_block += "\n " + l 12362306a36Sopenharmony_ci lines = code_block + "\n\n" 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci for c, l in enumerate(lines.split("\n")): 12662306a36Sopenharmony_ci content.append(l, fname, c) 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci with switch_source_input(self.state, content): 13162306a36Sopenharmony_ci self.state.nested_parse(content, 0, node, match_titles=1) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci return node.children 134