kernel_feat.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. # coding=utf-8
  2. # SPDX-License-Identifier: GPL-2.0
  3. #
  4. u"""
  5. kernel-feat
  6. ~~~~~~~~~~~
  7. Implementation of the ``kernel-feat`` reST-directive.
  8. :copyright: Copyright (C) 2016 Markus Heiser
  9. :copyright: Copyright (C) 2016-2019 Mauro Carvalho Chehab
  10. :maintained-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
  11. :license: GPL Version 2, June 1991 see Linux/COPYING for details.
  12. The ``kernel-feat`` (:py:class:`KernelFeat`) directive calls the
  13. scripts/get_feat.pl script to parse the Kernel ABI files.
  14. Overview of directive's argument and options.
  15. .. code-block:: rst
  16. .. kernel-feat:: <ABI directory location>
  17. :debug:
  18. The argument ``<ABI directory location>`` is required. It contains the
  19. location of the ABI files to be parsed.
  20. ``debug``
  21. Inserts a code-block with the *raw* reST. Sometimes it is helpful to see
  22. what reST is generated.
  23. """
  24. import codecs
  25. import os
  26. import re
  27. import subprocess
  28. import sys
  29. from docutils import nodes, statemachine
  30. from docutils.statemachine import ViewList
  31. from docutils.parsers.rst import directives, Directive
  32. from docutils.utils.error_reporting import ErrorString
  33. from sphinx.util.docutils import switch_source_input
  34. __version__ = '1.0'
  35. def setup(app):
  36. app.add_directive("kernel-feat", KernelFeat)
  37. return dict(
  38. version = __version__
  39. , parallel_read_safe = True
  40. , parallel_write_safe = True
  41. )
  42. class KernelFeat(Directive):
  43. u"""KernelFeat (``kernel-feat``) directive"""
  44. required_arguments = 1
  45. optional_arguments = 2
  46. has_content = False
  47. final_argument_whitespace = True
  48. option_spec = {
  49. "debug" : directives.flag
  50. }
  51. def warn(self, message, **replace):
  52. replace["fname"] = self.state.document.current_source
  53. replace["line_no"] = replace.get("line_no", self.lineno)
  54. message = ("%(fname)s:%(line_no)s: [kernel-feat WARN] : " + message) % replace
  55. self.state.document.settings.env.app.warn(message, prefix="")
  56. def run(self):
  57. doc = self.state.document
  58. if not doc.settings.file_insertion_enabled:
  59. raise self.warning("docutils: file insertion disabled")
  60. env = doc.settings.env
  61. srctree = os.path.abspath(os.environ["srctree"])
  62. args = [
  63. os.path.join(srctree, 'scripts/get_feat.pl'),
  64. 'rest',
  65. '--enable-fname',
  66. '--dir',
  67. os.path.join(srctree, 'Documentation', self.arguments[0]),
  68. ]
  69. if len(self.arguments) > 1:
  70. args.extend(['--arch', self.arguments[1]])
  71. lines = subprocess.check_output(args, cwd=os.path.dirname(doc.current_source)).decode('utf-8')
  72. line_regex = re.compile(r"^\.\. FILE (\S+)$")
  73. out_lines = ""
  74. for line in lines.split("\n"):
  75. match = line_regex.search(line)
  76. if match:
  77. fname = match.group(1)
  78. # Add the file to Sphinx build dependencies
  79. env.note_dependency(os.path.abspath(fname))
  80. else:
  81. out_lines += line + "\n"
  82. nodeList = self.nestedParse(out_lines, self.arguments[0])
  83. return nodeList
  84. def nestedParse(self, lines, fname):
  85. content = ViewList()
  86. node = nodes.section()
  87. if "debug" in self.options:
  88. code_block = "\n\n.. code-block:: rst\n :linenos:\n"
  89. for l in lines.split("\n"):
  90. code_block += "\n " + l
  91. lines = code_block + "\n\n"
  92. for c, l in enumerate(lines.split("\n")):
  93. content.append(l, fname, c)
  94. buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
  95. with switch_source_input(self.state, content):
  96. self.state.nested_parse(content, 0, node, match_titles=1)
  97. return node.children