From patchwork Fri Aug 12 14:48:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Heiser X-Patchwork-Id: 36354 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bYDls-0003mS-H8; Fri, 12 Aug 2016 14:49:16 +0000 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.84_2/mailfrontend-7) with esmtp id 1bYDlp-0004lG-2w; Fri, 12 Aug 2016 16:49:16 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751561AbcHLOtJ (ORCPT + 1 other); Fri, 12 Aug 2016 10:49:09 -0400 Received: from smtp3-1.goneo.de ([85.220.129.38]:57506 "EHLO smtp3-1.goneo.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751022AbcHLOtH (ORCPT ); Fri, 12 Aug 2016 10:49:07 -0400 Received: from localhost (localhost [127.0.0.1]) by smtp3.goneo.de (Postfix) with ESMTP id 4188523F9FD; Fri, 12 Aug 2016 16:49:05 +0200 (CEST) X-Virus-Scanned: by goneo X-Spam-Flag: NO X-Spam-Score: -2.8 X-Spam-Level: X-Spam-Status: No, score=-2.8 tagged_above=-999 tests=[ALL_TRUSTED=-1, AWL=0.100, BAYES_00=-1.9] autolearn=unavailable Received: from smtp3.goneo.de ([127.0.0.1]) by localhost (smtp3.goneo.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id LkxzdQQBCp8n; Fri, 12 Aug 2016 16:48:54 +0200 (CEST) Received: from ubu1604.fritz.box (dyndsl-095-033-019-091.ewe-ip-backbone.de [95.33.19.91]) by smtp3.goneo.de (Postfix) with ESMTPSA id A3D8223F979; Fri, 12 Aug 2016 16:48:53 +0200 (CEST) From: Markus Heiser To: Mauro Carvalho Chehab , Jani Nikula Cc: Markus Heiser , Jonathan Corbet , Linux Media Mailing List Subject: [PATCH 2/3] doc-rst: parseheaders directive (inital) Date: Fri, 12 Aug 2016 16:48:43 +0200 Message-Id: <1471013324-18914-3-git-send-email-markus.heiser@darmarit.de> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1471013324-18914-1-git-send-email-markus.heiser@darmarit.de> References: <1471013324-18914-1-git-send-email-markus.heiser@darmarit.de> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 6.0.0.2142326, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2016.8.12.144217 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report=' MULTIPLE_RCPTS 0.1, HTML_00_01 0.05, HTML_00_10 0.05, BODY_SIZE_10000_PLUS 0, IN_REP_TO 0, LEGITIMATE_NEGATE 0, LEGITIMATE_SIGNS 0, MSG_THREAD 0, MULTIPLE_REAL_RCPTS 0, NO_URI_HTTPS 0, REFERENCES 0, __ANY_URI 0, __CC_NAME 0, __CC_NAME_DIFF_FROM_ACC 0, __CC_REAL_NAMES 0, __CP_NAME_BODY 0, __FRAUD_MONEY_CURRENCY 0, __FRAUD_MONEY_CURRENCY_DOLLAR 0, __FROM_DOMAIN_IN_ANY_CC2 0, __FROM_DOMAIN_IN_RCPT 0, __HAS_CC_HDR 0, __HAS_FROM 0, __HAS_MSGID 0, __HAS_X_MAILER 0, __HAS_X_MAILING_LIST 0, __IN_REP_TO 0, __MIME_TEXT_ONLY 0, __MULTIPLE_RCPTS_CC_X2 0, __REFERENCES 0, __SANE_MSGID 0, __STOCK_PHRASE_7 0, __TO_MALFORMED_2 0, __TO_NAME 0, __TO_NAME_DIFF_FROM_ACC 0, __TO_REAL_NAMES 0, __URI_NO_WWW 0, __URI_NS ' From: Markus Heiser The parse-header directive includes contend from Linux kernel header files. The python-side of this feature is only an adapter of the ``parse-headers.pl`` Perl script. Overview of directive's argument and options. .. parse-header:: :exceptions: :debug: The parse-headers directive uses the ``kerneldoc_srctree`` setting from the kernel-doc directive and adds a new config value ``parseheader_bin`` pointing to the ``parse-headers.pl`` Perl script. Signed-off-by: Markus Heiser --- Documentation/conf.py | 2 +- Documentation/sphinx-static/theme_overrides.css | 8 + Documentation/sphinx/parse-headers.pl | 17 +-- Documentation/sphinx/parseheaders.py | 190 ++++++++++++++++++++++++ 4 files changed, 206 insertions(+), 11 deletions(-) create mode 100644 Documentation/sphinx/parseheaders.py diff --git a/Documentation/conf.py b/Documentation/conf.py index 96b7aa6..e85b74ae 100644 --- a/Documentation/conf.py +++ b/Documentation/conf.py @@ -28,7 +28,7 @@ sys.path.insert(0, os.path.abspath('sphinx')) # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['kernel-doc', 'rstFlatTable', 'kernel_include'] +extensions = ['kernel-doc', 'rstFlatTable', 'kernel_include', 'parseheaders'] # Gracefully handle missing rst2pdf. try: diff --git a/Documentation/sphinx-static/theme_overrides.css b/Documentation/sphinx-static/theme_overrides.css index 3a2ac4b..5843833 100644 --- a/Documentation/sphinx-static/theme_overrides.css +++ b/Documentation/sphinx-static/theme_overrides.css @@ -42,6 +42,14 @@ caption a.headerlink { opacity: 0; } caption a.headerlink:hover { opacity: 1; } + + /* literal blocks (e.g. parsed-literal directive) */ + + pre.literal-block { + font-size: 12px; + line-height: 1.5; + } + /* inline literal: drop the borderbox and red color */ code, .rst-content tt, .rst-content code { diff --git a/Documentation/sphinx/parse-headers.pl b/Documentation/sphinx/parse-headers.pl index 34bd9e2..5fd3d12 100755 --- a/Documentation/sphinx/parse-headers.pl +++ b/Documentation/sphinx/parse-headers.pl @@ -9,10 +9,10 @@ use Text::Tabs; my $debug = 0; if (scalar @ARGV < 2 || scalar @ARGV > 3) { - die "Usage:\n\t$0 []\n"; + die "Usage:\n\t$0 []\n"; } -my ($file_in, $file_out, $file_exceptions) = @ARGV; +my ($file_in, $file_exceptions) = @ARGV; my $data; my %ioctls; @@ -306,16 +306,13 @@ foreach my $r (keys %typedefs) { $data =~ s/\\ \n/\n/g; # -# Generate output file +# print generated content to stdout # my $title = $file_in; $title =~ s,.*/,,; -open OUT, "> $file_out" or die "Can't open $file_out"; -print OUT ".. -*- coding: utf-8; mode: rst -*-\n\n"; -print OUT "$title\n"; -print OUT "=" x length($title); -print OUT "\n\n.. parsed-literal::\n\n"; -print OUT $data; -close OUT; +print "$title\n"; +print "=" x length($title); +print "\n\n.. parsed-literal::\n\n"; +print $data; diff --git a/Documentation/sphinx/parseheaders.py b/Documentation/sphinx/parseheaders.py new file mode 100644 index 0000000..9211b93 --- /dev/null +++ b/Documentation/sphinx/parseheaders.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8; mode: python -*- +u""" + parseheaders + ~~~~~~~~~~~~ + + Implementation of the ``parse-header`` reST-directive. + + :copyright: Copyright (C) 2016 Markus Heiser + :license: GPL Version 2, June 1991 see Linux/COPYING for details. + + The ``parse-header`` (:py:class:`ParseHeader`) directive includes contend + from Linux kernel header files. The python side of this feature is only an + adapter of the ``parse-headers.pl`` Perl script. This script parses a header + file and converts it into a parsed-literal block, creating references for + ioctls, defines, typedefs, enums and structs. It also allow an external file + to modify the rules, in order to fix the expressions. Usage of the Perl + script:: + + parse-headers.pl [] + + Overview of directive's argument and options. + + .. code-block:: rst + + .. parse-header:: + :exceptions: + :debug: + + The argument ```` is required, it points to a source file in the + kernel source tree. The pathname is relative to kernel's root folder. The + options have the following meaning: + + ``exceptions `` + + Pathname of file where the *exceptions* are defined. The pathname is + relative to the reST file contain the parse-header directive. At this + time the Perl script supports two kinds of *exceptions*. These are + *ignore* and *replace*. + + * ignore [ioctl|define|typedef|enum|struct|symbol] + * replace [ioctl|define|typedef|enum|struct|symbol] + + Here are some examples for those:: + + # Ignore header name + ignore define _DVBAUDIO_H_ + + # Typedef pointing to structs + replace typedef audio_karaoke_t audio-karaoke + + ``debug`` + Inserts a code-block with the generated reST source. Sometimes it be + helpful to see what reST is generated. + + .. note:: + + The parse-headers directive uses the ``kerneldoc_srctree`` setting from + the kernel-doc directive and adds a new config value ``parseheader_bin`` + pointing to the ``parse-headers.pl`` Perl script. + +""" + +# ============================================================================== +# imports +# ============================================================================== + +import sys +from os import path +import subprocess + +# Since Sphinx 1.2 does not require six, we can't assume that six is installed +# from six impot text_type + +from docutils import nodes +from docutils.parsers.rst import Directive, directives +from docutils.statemachine import ViewList +from docutils.utils.error_reporting import ErrorString + +from sphinx.ext.autodoc import AutodocReporter + +# ============================================================================== +# common globals +# ============================================================================== + +__version__ = '1.0' + +# We can't assume that six is installed +PY3 = sys.version_info[0] == 3 +PY2 = sys.version_info[0] == 2 +if PY3: + # pylint: disable=C0103, W0622 + unicode = str + basestring = str + +# ============================================================================== +def setup(app): +# ============================================================================== + + app.add_directive("parse-header", ParseHeader) + app.add_config_value( + 'parseheader_bin' + , path.join(path.dirname(__file__), 'parse-headers.pl') + , 'env') + + return dict( + version = __version__ + , parallel_read_safe = True + , parallel_write_safe = True + ) + +# ============================================================================== +class ParseHeader(Directive): +# ============================================================================== + + u"""ParseHeader (``parse-header``) directive""" + + required_arguments = 1 + optional_arguments = 0 + has_content = False + final_argument_whitespace = True + + option_spec = { + "exceptions" : directives.unchanged + , "debug" : directives.flag # insert generated reST as code-block + } + + def run(self): + env = self.state.document.settings.env + doc = self.state.document + fname = env.config.kerneldoc_srctree + '/' + self.arguments[0] + env.note_dependency(path.abspath(fname)) + + if not doc.settings.file_insertion_enabled: + raise self.warning("docutils: file insertion disabled") + + cmd = [ env.config.parseheader_bin, fname ] + if "exceptions" in self.options: + cmd.append( + path.join(path.dirname(doc.current_source) + , self.options.get("exceptions")) + ) + + lines = self.runCmd(cmd) + nodeList = self.nestedParse(lines, fname) + 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 + , universal_newlines = True + , **kwargs + ) + out, _none = proc.communicate() + + if proc.returncode != 0: + raise self.severe( + u"command '%s' failed with return code %d" + % (" ".join(cmd), proc.returncode) + ) + except OSError as exc: + raise self.severe(u"problems with '%s' directive: %s." + % (self.name, ErrorString(exc))) + return unicode(out) + + def nestedParse(self, lines, fname): + content = ViewList() + node = nodes.section() + + if "debug" in self.options: + code_block = "\n\n.. code-block:: rst\n :linenos:\n" + for l in lines.split("\n"): + code_block += "\n " + l + lines = code_block + "\n\n" + + for c, l in enumerate(lines.split("\n")): + content.append(l, fname, c) + + buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter + 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 + return node.children