Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1# -*- coding: utf-8; mode: python -*-
  2# coding=utf-8
  3# SPDX-License-Identifier: GPL-2.0
  4#
  5u"""
  6    kernel-abi
  7    ~~~~~~~~~~
  8
  9    Implementation of the ``kernel-abi`` reST-directive.
 10
 11    :copyright:  Copyright (C) 2016  Markus Heiser
 12    :copyright:  Copyright (C) 2016-2020  Mauro Carvalho Chehab
 13    :maintained-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
 14    :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
 15
 16    The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the
 17    scripts/get_abi.pl script to parse the Kernel ABI files.
 18
 19    Overview of directive's argument and options.
 20
 21    .. code-block:: rst
 22
 23        .. kernel-abi:: <ABI directory location>
 24            :debug:
 25
 26    The argument ``<ABI directory location>`` is required. It contains the
 27    location of the ABI files to be parsed.
 28
 29    ``debug``
 30      Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
 31      what reST is generated.
 32
 33"""
 34
 35import codecs
 36import os
 37import subprocess
 38import sys
 39import re
 40import kernellog
 41
 42from docutils import nodes, statemachine
 43from docutils.statemachine import ViewList
 44from docutils.parsers.rst import directives, Directive
 45from docutils.utils.error_reporting import ErrorString
 46from sphinx.util.docutils import switch_source_input
 47
 48__version__  = '1.0'
 49
 50def setup(app):
 51
 52    app.add_directive("kernel-abi", KernelCmd)
 53    return dict(
 54        version = __version__
 55        , parallel_read_safe = True
 56        , parallel_write_safe = True
 57    )
 58
 59class KernelCmd(Directive):
 60
 61    u"""KernelABI (``kernel-abi``) directive"""
 62
 63    required_arguments = 1
 64    optional_arguments = 2
 65    has_content = False
 66    final_argument_whitespace = True
 67
 68    option_spec = {
 69        "debug"     : directives.flag,
 70        "rst"       : directives.unchanged
 71    }
 72
 73    def run(self):
 74        doc = self.state.document
 75        if not doc.settings.file_insertion_enabled:
 76            raise self.warning("docutils: file insertion disabled")
 77
 78        srctree = os.path.abspath(os.environ["srctree"])
 79
 80        args = [
 81            os.path.join(srctree, 'scripts/get_abi.pl'),
 82            'rest',
 83            '--enable-lineno',
 84            '--dir', os.path.join(srctree, 'Documentation', self.arguments[0]),
 85        ]
 86
 87        if 'rst' in self.options:
 88            args.append('--rst-source')
 89
 90        lines = subprocess.check_output(args, cwd=os.path.dirname(doc.current_source)).decode('utf-8')
 91        nodeList = self.nestedParse(lines, self.arguments[0])
 92        return nodeList
 93
 94    def nestedParse(self, lines, fname):
 95        env = self.state.document.settings.env
 96        content = ViewList()
 97        node = nodes.section()
 98
 99        if "debug" in self.options:
100            code_block = "\n\n.. code-block:: rst\n    :linenos:\n"
101            for l in lines.split("\n"):
102                code_block += "\n    " + l
103            lines = code_block + "\n\n"
104
105        line_regex = re.compile(r"^\.\. LINENO (\S+)\#([0-9]+)$")
106        ln = 0
107        n = 0
108        f = fname
109
110        for line in lines.split("\n"):
111            n = n + 1
112            match = line_regex.search(line)
113            if match:
114                new_f = match.group(1)
115
116                # Sphinx parser is lazy: it stops parsing contents in the
117                # middle, if it is too big. So, handle it per input file
118                if new_f != f and content:
119                    self.do_parse(content, node)
120                    content = ViewList()
121
122                    # Add the file to Sphinx build dependencies
123                    env.note_dependency(os.path.abspath(f))
124
125                f = new_f
126
127                # sphinx counts lines from 0
128                ln = int(match.group(2)) - 1
129            else:
130                content.append(line, f, ln)
131
132        kernellog.info(self.state.document.settings.env.app, "%s: parsed %i lines" % (fname, n))
133
134        if content:
135            self.do_parse(content, node)
136
137        return node.children
138
139    def do_parse(self, content, node):
140        with switch_source_input(self.state, content):
141            self.state.nested_parse(content, 0, node, match_titles=1)