Blame view

Documentation/sphinx/kernel_abi.py 5.6 KB
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
1
  # -*- coding: utf-8; mode: python -*-
823830d40   Mauro Carvalho Chehab   docs: kernel_abi....
2
  # coding=utf-8
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
3
  # SPDX-License-Identifier: GPL-2.0
823830d40   Mauro Carvalho Chehab   docs: kernel_abi....
4
  #
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  u"""
      kernel-abi
      ~~~~~~~~~~
  
      Implementation of the ``kernel-abi`` reST-directive.
  
      :copyright:  Copyright (C) 2016  Markus Heiser
      :copyright:  Copyright (C) 2016-2020  Mauro Carvalho Chehab
      :maintained-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
      :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
  
      The ``kernel-abi`` (:py:class:`KernelCmd`) directive calls the
      scripts/get_abi.pl script to parse the Kernel ABI files.
  
      Overview of directive's argument and options.
  
      .. code-block:: rst
  
          .. kernel-abi:: <ABI directory location>
              :debug:
  
      The argument ``<ABI directory location>`` is required. It contains the
      location of the ABI files to be parsed.
  
      ``debug``
        Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
        what reST is generated.
  
  """
823830d40   Mauro Carvalho Chehab   docs: kernel_abi....
34
  import codecs
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
35
  import os
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
36
  import subprocess
c830fa9a4   Mauro Carvalho Chehab   docs: kernel_abi....
37
  import sys
997b7c8b4   Mauro Carvalho Chehab   docs: kernel_abi....
38
  import re
3c543d298   Mauro Carvalho Chehab   docs: kernel_abi....
39
  import kernellog
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
40

c830fa9a4   Mauro Carvalho Chehab   docs: kernel_abi....
41
  from os import path
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
42

c830fa9a4   Mauro Carvalho Chehab   docs: kernel_abi....
43
  from docutils import nodes, statemachine
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
44
  from docutils.statemachine import ViewList
c830fa9a4   Mauro Carvalho Chehab   docs: kernel_abi....
45
  from docutils.parsers.rst import directives, Directive
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
46
  from docutils.utils.error_reporting import ErrorString
c830fa9a4   Mauro Carvalho Chehab   docs: kernel_abi....
47
48
49
50
51
52
53
54
55
56
  #
  # AutodocReporter is only good up to Sphinx 1.7
  #
  import sphinx
  
  Use_SSI = sphinx.__version__[:3] >= '1.7'
  if Use_SSI:
      from sphinx.util.docutils import switch_source_input
  else:
      from sphinx.ext.autodoc import AutodocReporter
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
57
58
  
  __version__  = '1.0'
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  def setup(app):
  
      app.add_directive("kernel-abi", KernelCmd)
      return dict(
          version = __version__
          , parallel_read_safe = True
          , parallel_write_safe = True
      )
  
  class KernelCmd(Directive):
  
      u"""KernelABI (``kernel-abi``) directive"""
  
      required_arguments = 1
642514df1   Mauro Carvalho Chehab   docs: ABI: make i...
73
      optional_arguments = 2
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
74
75
76
77
      has_content = False
      final_argument_whitespace = True
  
      option_spec = {
642514df1   Mauro Carvalho Chehab   docs: ABI: make i...
78
79
          "debug"     : directives.flag,
          "rst"       : directives.unchanged
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
80
      }
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
81
82
83
84
85
86
87
88
      def run(self):
  
          doc = self.state.document
          if not doc.settings.file_insertion_enabled:
              raise self.warning("docutils: file insertion disabled")
  
          env = doc.settings.env
          cwd = path.dirname(doc.current_source)
997b7c8b4   Mauro Carvalho Chehab   docs: kernel_abi....
89
          cmd = "get_abi.pl rest --enable-lineno --dir "
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
90
          cmd += self.arguments[0]
642514df1   Mauro Carvalho Chehab   docs: ABI: make i...
91
92
          if 'rst' in self.options:
              cmd += " --rst-source"
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
93
94
95
96
97
98
99
100
101
102
103
104
105
106
          srctree = path.abspath(os.environ["srctree"])
  
          fname = cmd
  
          # extend PATH with $(srctree)/scripts
          path_env = os.pathsep.join([
              srctree + os.sep + "scripts",
              os.environ["PATH"]
          ])
          shell_env = os.environ.copy()
          shell_env["PATH"]    = path_env
          shell_env["srctree"] = srctree
  
          lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
3c543d298   Mauro Carvalho Chehab   docs: kernel_abi....
107
          nodeList = self.nestedParse(lines, self.arguments[0])
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
108
109
110
111
112
113
114
115
116
117
          return nodeList
  
      def runCmd(self, cmd, **kwargs):
          u"""Run command ``cmd`` and return it's stdout as unicode."""
  
          try:
              proc = subprocess.Popen(
                  cmd
                  , stdout = subprocess.PIPE
                  , stderr = subprocess.PIPE
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
118
119
120
                  , **kwargs
              )
              out, err = proc.communicate()
823830d40   Mauro Carvalho Chehab   docs: kernel_abi....
121
122
  
              out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
123
124
125
126
127
128
129
130
              if proc.returncode != 0:
                  raise self.severe(
                      u"command '%s' failed with return code %d"
                      % (cmd, proc.returncode)
                  )
          except OSError as exc:
              raise self.severe(u"problems with '%s' directive: %s."
                                % (self.name, ErrorString(exc)))
823830d40   Mauro Carvalho Chehab   docs: kernel_abi....
131
          return out
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
132

3c543d298   Mauro Carvalho Chehab   docs: kernel_abi....
133
      def nestedParse(self, lines, fname):
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
134
          content = ViewList()
3c543d298   Mauro Carvalho Chehab   docs: kernel_abi....
135
          node = nodes.section()
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  
          if "debug" in self.options:
              code_block = "
  
  .. code-block:: rst
      :linenos:
  "
              for l in lines.split("
  "):
                  code_block += "
      " + l
              lines = code_block + "
  
  "
997b7c8b4   Mauro Carvalho Chehab   docs: kernel_abi....
150
151
          line_regex = re.compile("^#define LINENO (\S+)\#([0-9]+)$")
          ln = 0
3c543d298   Mauro Carvalho Chehab   docs: kernel_abi....
152
153
          n = 0
          f = fname
997b7c8b4   Mauro Carvalho Chehab   docs: kernel_abi....
154
155
156
  
          for line in lines.split("
  "):
3c543d298   Mauro Carvalho Chehab   docs: kernel_abi....
157
              n = n + 1
997b7c8b4   Mauro Carvalho Chehab   docs: kernel_abi....
158
159
              match = line_regex.search(line)
              if match:
3c543d298   Mauro Carvalho Chehab   docs: kernel_abi....
160
161
162
163
164
165
166
167
168
                  new_f = match.group(1)
  
                  # Sphinx parser is lazy: it stops parsing contents in the
                  # middle, if it is too big. So, handle it per input file
                  if new_f != f and content:
                      self.do_parse(content, node)
                      content = ViewList()
  
                  f = new_f
997b7c8b4   Mauro Carvalho Chehab   docs: kernel_abi....
169
170
171
172
                  # sphinx counts lines from 0
                  ln = int(match.group(2)) - 1
              else:
                  content.append(line, f, ln)
9ca876f96   Mauro Carvalho Chehab   docs: kernel_abi....
173

3c543d298   Mauro Carvalho Chehab   docs: kernel_abi....
174
175
176
177
          kernellog.info(self.state.document.settings.env.app, "%s: parsed %i lines" % (fname, n))
  
          if content:
              self.do_parse(content, node)
c830fa9a4   Mauro Carvalho Chehab   docs: kernel_abi....
178

3c543d298   Mauro Carvalho Chehab   docs: kernel_abi....
179
180
181
          return node.children
  
      def do_parse(self, content, node):
c830fa9a4   Mauro Carvalho Chehab   docs: kernel_abi....
182
183
184
185
          if Use_SSI:
              with switch_source_input(self.state, content):
                  self.state.nested_parse(content, 0, node, match_titles=1)
          else:
3c543d298   Mauro Carvalho Chehab   docs: kernel_abi....
186
              buf  = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
c830fa9a4   Mauro Carvalho Chehab   docs: kernel_abi....
187
188
189
190
191
192
193
              self.state.memo.title_styles  = []
              self.state.memo.section_level = 0
              self.state.memo.reporter      = AutodocReporter(content, self.state.memo.reporter)
              try:
                  self.state.nested_parse(content, 0, node, match_titles=1)
              finally:
                  self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf