this patch adds a command to auto-generate documentation from kernel's source tree.:: scripts/kerneldoc-src2rst --help E.g. to autodoc the kernel's ./include folder use:: scripts/kerneldoc-src2rst ./include /tmp/test123 >From the resulting reST-doctree you can build HTML rendered output like the one in [1]. I use it to see, if patches on the kernel_doc.py parser cause a regression (compare reST before/after the patch). Autodoc the whole source tree takes a long time. To speed up, the src2rst module uses multiprocessing from [2]. This means, it consumes all your CPUs. If you don't want this, use option '--threads=n'. [1] https://h2626237.stratoserver.net/kernel/linux_src_doc/index.html [2] https://docs.python.org/3.6/library/multiprocessing.html Signed-off-by: Markus Heiser <markus.heiser@xxxxxxxxxxx> --- Documentation/sphinx/src2rst.py | 229 ++++++++++++++++++++++++++++++++++++++++ scripts/kerneldoc-src2rst | 11 ++ 2 files changed, 240 insertions(+) create mode 100755 Documentation/sphinx/src2rst.py create mode 100755 scripts/kerneldoc-src2rst diff --git a/Documentation/sphinx/src2rst.py b/Documentation/sphinx/src2rst.py new file mode 100755 index 0000000..d8d6e7b --- /dev/null +++ b/Documentation/sphinx/src2rst.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8; mode: python -*- +# pylint: disable=C0103 + +u""" + src2rst + ~~~~~~~ + + Implementation of the ``kerneldoc-src2rst`` command. + + :copyright: Copyright (C) 2016 Markus Heiser + :license: GPL Version 2, June 1991 see Linux/COPYING for details. + + The ``kerneldoc-src2rst`` command extracts documentation from Linux kernel's + source code comments, see ``--help``:: + + $ kerneldoc-src2rst --help + +""" + +# ------------------------------------------------------------------------------ +# imports +# ------------------------------------------------------------------------------ + +import sys +import argparse +import re +import multiprocessing + +import six + +from fspath import FSPath, OS_ENV +import kernel_doc as kerneldoc + +# ------------------------------------------------------------------------------ +# config +# ------------------------------------------------------------------------------ + +MARKUP = "kernel-doc" # "reST" +MSG = lambda msg: sys.__stderr__.write("INFO : %s\n" % msg) +ERR = lambda msg: sys.__stderr__.write("ERROR: %s\n" % msg) +FATAL = lambda msg: sys.__stderr__.write("FATAL: %s\n" % msg) +IGNORE = ['kernel-doc.rst'] + +TEMPLATE_INDEX=u"""\ +.. -*- coding: utf-8; mode: rst -*- + +================================================================================ +%(title)s +================================================================================ + +.. toctree:: + :maxdepth: 1 + +""" + +CMD = None # global used by multiprocessing +SRCTREE = FSPath(OS_ENV.get("srctree", "")) + +# ------------------------------------------------------------------------------ +def main(): +# ------------------------------------------------------------------------------ + + global CMD # pylint: disable=W0603, W0621 + + CLI = argparse.ArgumentParser( + description = ("Parse *kernel-doc* comments from source code") + , formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + CLI.add_argument( + "srctree" + , help = "Folder of source code." + , type = lambda x: FSPath(x).ABSPATH) + + CLI.add_argument( + "doctree" + , help = "Folder to place reST documentation." + , type = lambda x: FSPath(x).ABSPATH) + + CLI.add_argument( + "--sloppy" + , action = "store_true" + , help = "Sloppy comment check, reports only severe errors.") + + CLI.add_argument( + "--force" + , action = "store_true" + , help = "Don't stop if doctree exists.") + + CLI.add_argument( + "--threads" + , type = int + , default = multiprocessing.cpu_count() + , help = "Use up to n threads.") + + CLI.add_argument( + "--markup" + , choices = ["reST", "kernel-doc", "auto"] + , default = "auto" + , help = ( + "Markup of the comments. Change this option only if you know" + " what you do. New comments must be marked up with reST!")) + + CMD = CLI.parse_args() + + if not CMD.srctree.EXISTS: + ERR("%s does not exists." % CMD.srctree) + sys.exit(42) + + if not CMD.srctree.ISDIR: + ERR("%s is not a folder." % CMD.srctree) + sys.exit(42) + + if not CMD.force and CMD.doctree.EXISTS: + ERR("%s is in the way, remove it first" % CMD.doctree) + sys.exit(42) + + CMD.rst_files = set() + if CMD.markup == "auto": + CMD.rst_files = docgrep(SRCTREE/"Documentation") + + pool = multiprocessing.Pool(CMD.threads) + pool.map(autodoc_file, gather_filenames(CMD)) + pool.close() + pool.join() + + insert_index_files(CMD.doctree) + +# ------------------------------------------------------------------------------ +def gather_filenames(cmd): +# ------------------------------------------------------------------------------ + MSG("gather files ...") + + for fname in cmd.srctree.reMatchFind(r"^.*\.[ch]$"): + if fname.startswith(CMD.srctree/"Documentation"): + continue + yield fname + +# ------------------------------------------------------------------------------ +def autodoc_file(fname): +# ------------------------------------------------------------------------------ + + fname = fname.relpath(CMD.srctree) + markup = CMD.markup + + if CMD.markup == "kernel-doc" and fname in CMD.rst_files: + markup = "reST" + + opts = kerneldoc.ParseOptions( + rel_fname = fname + , src_tree = CMD.srctree + , verbose_warn = not (CMD.sloppy) + , markup = markup ) + + parser = kerneldoc.Parser(opts, kerneldoc.NullTranslator()) + try: + parser.parse() + except Exception: # pylint: disable=W0703 + FATAL("kernel-doc markup of %s seems buggy / can't parse" % opts.fname) + return + + if not parser.ctx.dump_storage: + # no kernel-doc comments found + MSG("parsed: NONE comments: %s" % opts.fname) + return + + MSG("parsed: %4d comments: %s" % (len(parser.ctx.dump_storage), opts.fname)) + + try: + rst = six.StringIO() + translator = kerneldoc.ReSTTranslator() + opts.out = rst + + # First try to output reST, this might fail, because the kernel-doc + # parser part is to tollerant ("bad lines", "function name and function + # declaration are different", etc ...). + parser.parse_dump_storage(translator=translator) + + outFile = CMD.doctree / fname.replace(".","_") + ".rst" + outFile.DIRNAME.makedirs() + with outFile.openTextFile(mode="w") as out: + out.write(rst.getvalue()) + + except Exception: # pylint: disable=W0703 + FATAL("kernel-doc markup of %s seems buggy / can't parse" % opts.fname) + return + +# ------------------------------------------------------------------------------ +def insert_index_files(folder): +# ------------------------------------------------------------------------------ + + for folder, dirnames, filenames in folder.walk(): + ctx = kerneldoc.Container( title = folder.FILENAME ) + dirnames.sort() + filenames.sort() + indexFile = folder / "index.rst" + MSG("create index: %s" % indexFile) + with indexFile.openTextFile(mode="w") as index: + index.write(TEMPLATE_INDEX % ctx) + for d in dirnames: + index.write(" %s/index\n" % d.FILENAME) + for f in filenames: + if f.FILENAME == "index": + continue + index.write(" %s\n" % f.FILENAME) + +# ------------------------------------------------------------------------------ +def docgrep(folder): +# ------------------------------------------------------------------------------ + + # Hackisch script to grep all '.. kernel-doc::' directives. The assumption + # is, that comments from the source files used in those directives are + # allready migratetd to the reST format. I guess that (ATM) 95-99% of the + # comments are not migrated, those will be parsed with the old kernel-doc + # comment style introduced by the old DocBook toolchain. + + pat = re.compile(r"^\s*\.\.\s+kernel-doc::\s*([^\s]+)\s*$") + out = set() + for rstFile in folder.reMatchFind(r".*\.rst"): + if rstFile.BASENAME in IGNORE: + continue + #print(rstFile) + with rstFile.openTextFile() as f: + for l in f: + match = pat.search(l) + if match: + #print(match.group(1)) + out.add(match.group(1)) + return sorted(out) diff --git a/scripts/kerneldoc-src2rst b/scripts/kerneldoc-src2rst new file mode 100755 index 0000000..6c5e8b1 --- /dev/null +++ b/scripts/kerneldoc-src2rst @@ -0,0 +1,11 @@ +#!/usr/bin/python + +import sys +from os import path + +linuxdoc = path.abspath(path.join(path.dirname(__file__), '..')) +linuxdoc = path.join(linuxdoc, 'Documentation', 'sphinx') +sys.path.insert(0, linuxdoc) + +import src2rst +src2rst.main() -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html