Add a tool which parse comment from source files and extract kerneldoc-like documentation from them. Note: this is rather quite crude, support only generic 'blocs' and doc for functions; it has no support for anything else. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- Documentation/sphinx/cdoc.py | 180 +++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100755 Documentation/sphinx/cdoc.py diff --git a/Documentation/sphinx/cdoc.py b/Documentation/sphinx/cdoc.py new file mode 100755 index 000000000..ba875242a --- /dev/null +++ b/Documentation/sphinx/cdoc.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python +# SPDX_License-Identifier: MIT +# +# Copyright (C) 2018 Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> +# + +"""Extract doc-comments from C files""" + +import re + +__version__ = '0.0' + + +class Lines: + def __init__(self, lines): + self.index = 0 + self.lines = lines + self.last = None + self.back = False + + def __iter__(self): + return self + + def memo(self): + return (self.index, self.last) + + def __next__(self): + if not self.back: + self.last = next(self.lines).rstrip() + self.index += 1 + else: + self.back = False + return self.memo() + def next(self): + return self.__next__() + + def undo(self): + self.back = True + +def readline_cont(lines): + (lineno, line) = next(lines) + while line[-1] == '\\': + del line[-1] + line = line.rstrip() + (n, l) = next(lines) + line += ' ' + l.lstrip() + return (lineno, line) + +def readline_until(lines, delim): + try: + (lineno, line) = next(lines) + if line == '': + raise StopIteration + while line[-1] not in delim: + (n, l) = next(lines) + line += ' ' + l.lstrip() + except: + line = '' + return (lineno, line) + + +def process_block(lines): + info = { } + args = [] + tags = [] + desc = [] + state = 0 + + (n, l) = lines.memo() + #print('processing line ' + str(n) + ': ' + l) + + ## is it a single line comment ? + m = re.match(r"^/\*\*\s+(.+[^\s])\s*\*/$", l) # /** (.*) */ + if not m: + m = re.match(r"^///\s+(.+[^\s])\s*$", l) # /// (.*) + if m: + info['type'] = 'single' + info['desc'] = (n, m.group(1)) + return info + + ## read the multi line comment + for (n, l) in lines: + #print('state %d: %4d: %s' % (state, n, l)) + m = re.match(r"^( \*|///?) ?(.*)", l) + if not m: + lines.undo() + break + if l == ' */': + break + l = m.group(2) + + if state == 0: + info['short'] = (n ,l) + state = 1 + elif state == 1: + if l != '': + lines.undo() + state = 2 + elif state == 2 or state == 5: + m = re.match(r"^@([\w-]*)(:?\s*)(.*)", l) + if m: + tag = m.group(1) + sep = m.group(2) + ## FIXME/ warn if sep != ': ' + l = m.group(3) + ## FIXME: try multi-line ??? + if state == 2: + args.append((n, tag, l)) + if state == 5: + tags.append((n, tag, l)) + else: + lines.undo() + if state == 2: + state = 3 + elif state == 3: + if l != '': + desc = [n, l] + state = 4 + elif state == 4: + if len(l) and l[0] == '@': + lines.undo() + state = 5 + else: + desc.append(l) + else: + print('??? %4d: %s' % (n , l)) + + ## fill the info + if len(args): + info['args'] = args + if len(desc): + info['desc'] = desc + if len(tags): + info['tags'] = tags + + ## read the item (function only for now) + (n, line) = readline_until(lines, (')', ';')) + if len(line): + line.rstrip(';') + #print('function: %4d: %s' % (n, line)) + info['type'] = 'func' + info['func'] = (n, line) + else: + info['type'] = 'bloc' + + return info + +def process_file(f): + docs = [] + lines = Lines(f) + for (n, l) in lines: + #print("%4d: %s" % (n, l)) + if l.startswith('/**') or l.startswith('///'): + info = process_block(lines) + docs.append(info) + + return docs + + +if __name__ == '__main__': + """ extract the doc from stdin """ + import sys + + res = process_file(sys.stdin) + for info in res: + print('###'); + print('type: %s' % (info.get('type', '???'))) + val = info.get('short', None) + if val: + print('short:%4d: %s' % val) + for val in info.get('args', []): + print('para: %4d: @%s: %s' % val) + val = info.get('desc', None) + if val: + n = val[0] + print('desc: %4d:\n\t%s' % (n, '\n\t'.join(val[1:]))) + for val in info.get('tags', []): + print('tags: %4d: @%s: %s' % val) + +# vim: tabstop=4 -- 2.17.0 -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html