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