0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 import codecs
0031 import os
0032 import subprocess
0033 import sys
0034 import re
0035 import glob
0036
0037 from docutils import nodes, statemachine
0038 from docutils.statemachine import ViewList
0039 from docutils.parsers.rst import directives, Directive
0040 import sphinx
0041 from sphinx.util.docutils import switch_source_input
0042 import kernellog
0043
0044 __version__ = '1.0'
0045
0046 class KernelDocDirective(Directive):
0047 """Extract kernel-doc comments from the specified file"""
0048 required_argument = 1
0049 optional_arguments = 4
0050 option_spec = {
0051 'doc': directives.unchanged_required,
0052 'export': directives.unchanged,
0053 'internal': directives.unchanged,
0054 'identifiers': directives.unchanged,
0055 'no-identifiers': directives.unchanged,
0056 'functions': directives.unchanged,
0057 }
0058 has_content = False
0059
0060 def run(self):
0061 env = self.state.document.settings.env
0062 cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
0063
0064
0065
0066
0067 cmd += ['-sphinx-version', sphinx.__version__]
0068
0069 filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
0070 export_file_patterns = []
0071
0072
0073 env.note_dependency(os.path.abspath(filename))
0074
0075 tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
0076
0077
0078 if 'functions' in self.options:
0079 self.options['identifiers'] = self.options.get('functions')
0080
0081
0082 if 'export' in self.options:
0083 cmd += ['-export']
0084 export_file_patterns = str(self.options.get('export')).split()
0085 elif 'internal' in self.options:
0086 cmd += ['-internal']
0087 export_file_patterns = str(self.options.get('internal')).split()
0088 elif 'doc' in self.options:
0089 cmd += ['-function', str(self.options.get('doc'))]
0090 elif 'identifiers' in self.options:
0091 identifiers = self.options.get('identifiers').split()
0092 if identifiers:
0093 for i in identifiers:
0094 cmd += ['-function', i]
0095 else:
0096 cmd += ['-no-doc-sections']
0097
0098 if 'no-identifiers' in self.options:
0099 no_identifiers = self.options.get('no-identifiers').split()
0100 if no_identifiers:
0101 for i in no_identifiers:
0102 cmd += ['-nosymbol', i]
0103
0104 for pattern in export_file_patterns:
0105 for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
0106 env.note_dependency(os.path.abspath(f))
0107 cmd += ['-export-file', f]
0108
0109 cmd += [filename]
0110
0111 try:
0112 kernellog.verbose(env.app,
0113 'calling kernel-doc \'%s\'' % (" ".join(cmd)))
0114
0115 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
0116 out, err = p.communicate()
0117
0118 out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
0119
0120 if p.returncode != 0:
0121 sys.stderr.write(err)
0122
0123 kernellog.warn(env.app,
0124 'kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode))
0125 return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
0126 elif env.config.kerneldoc_verbosity > 0:
0127 sys.stderr.write(err)
0128
0129 lines = statemachine.string2lines(out, tab_width, convert_whitespace=True)
0130 result = ViewList()
0131
0132 lineoffset = 0;
0133 line_regex = re.compile("^\.\. LINENO ([0-9]+)$")
0134 for line in lines:
0135 match = line_regex.search(line)
0136 if match:
0137
0138 lineoffset = int(match.group(1)) - 1
0139
0140 else:
0141 doc = env.srcdir + "/" + env.docname + ":" + str(self.lineno)
0142 result.append(line, doc + ": " + filename, lineoffset)
0143 lineoffset += 1
0144
0145 node = nodes.section()
0146 self.do_parse(result, node)
0147
0148 return node.children
0149
0150 except Exception as e:
0151 kernellog.warn(env.app, 'kernel-doc \'%s\' processing failed with: %s' %
0152 (" ".join(cmd), str(e)))
0153 return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
0154
0155 def do_parse(self, result, node):
0156 with switch_source_input(self.state, result):
0157 self.state.nested_parse(result, 0, node, match_titles=1)
0158
0159 def setup(app):
0160 app.add_config_value('kerneldoc_bin', None, 'env')
0161 app.add_config_value('kerneldoc_srctree', None, 'env')
0162 app.add_config_value('kerneldoc_verbosity', 1, 'env')
0163
0164 app.add_directive('kernel-doc', KernelDocDirective)
0165
0166 return dict(
0167 version = __version__,
0168 parallel_read_safe = True,
0169 parallel_write_safe = True
0170 )