From: Jani Nikula <jani.nik...@intel.com>

Add new -asciidoc option to produce asciidoc output from kernel-doc. The
output is formatted internally, with no dependencies on external
tools. Any asciidoc formatting present in kernel-doc will naturally be
present in the resulting asciidoc as well.

Highlighting of functions(), &struct structures, &enum enumerations,
@parameters, etc. will be done by means of asciidoc. Anchors and
cross-references are added as well, providing hyperlinking support in
the result processed by asciidoc(1).

This support is non-conflicting and orthogonal to the patches adding
asciidoc support to the kernel-doc DocBook output [1]. Those patches
bolt on to the current document generation pipeline; there is currently
none for native asciidoc in the kernel (though ideas have been discussed
[2]). At this time, this patch should be considered a worthwhile
standalone improvement to kernel-doc, independent of the rest.

[1] 
http://mid.gmane.org/1448471279-19748-1-git-send-email-daniel.vet...@ffwll.ch
[2] http://mid.gmane.org/20160114131823.2ff43...@lwn.net

Cc: Jonathan Corbet <cor...@lwn.net>
Cc: Daniel Vetter <dan...@ffwll.ch>
Signed-off-by: Jani Nikula <jani.nik...@intel.com>
Signed-off-by: Jonathan Corbet <cor...@lwn.net>
---
 scripts/kernel-doc | 237 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 237 insertions(+)

diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index c37255b..06f1649 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -201,6 +201,8 @@ my $type_param = '\@(\w+)';
 my $type_struct = '\&((struct\s*)*[_\w]+)';
 my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
 my $type_env = '(\$\w+)';
+my $type_enum_full = '\&(enum)\s*([_\w]+)';
+my $type_struct_full = '\&(struct)\s*([_\w]+)';
 
 # Output conversion substitutions.
 #  One for each output format
@@ -266,6 +268,17 @@ my @highlights_text = (
                      );
 my $blankline_text = "";
 
+# asciidoc-mode
+my @highlights_asciidoc = (
+                       [$type_constant, "`\$1`"],
+                       [$type_func, "<<func_\$1,`\$1()`>>"],
+                       [$type_struct_full, "<<\$1_\$2,`\$1 \$2`>>"],
+                       [$type_enum_full, "<<\$1_\$2,`\$1 \$2`>>"],
+                       [$type_struct, "<<struct_\$1,`\$1`>>"],
+                       [$type_param, "*\$1*"]
+                     );
+my $blankline_asciidoc = "\n";
+
 # list mode
 my @highlights_list = (
                        [$type_constant, "\$1"],
@@ -402,6 +415,10 @@ while ($ARGV[0] =~ m/^-(.*)/) {
        $output_mode = "text";
        @highlights = @highlights_text;
        $blankline = $blankline_text;
+    } elsif ($cmd eq "-asciidoc") {
+       $output_mode = "asciidoc";
+       @highlights = @highlights_asciidoc;
+       $blankline = $blankline_asciidoc;
     } elsif ($cmd eq "-docbook") {
        $output_mode = "xml";
        @highlights = @highlights_xml;
@@ -1713,6 +1730,214 @@ sub output_blockhead_text(%) {
     }
 }
 
+##
+# output in asciidoc
+sub output_highlight_asciidoc {
+    my $contents = join "\n",@_;
+    my $line;
+
+    # undo the evil effects of xml_escape() earlier
+    $contents = xml_unescape($contents);
+
+    eval $dohighlight;
+    die $@ if $@;
+
+    foreach $line (split "\n", $contents) {
+       if ($line eq "") {
+           print $lineprefix, $blankline;
+       } else {
+           $line =~ s/\\\\\\/\&/g;
+           print $lineprefix, $line;
+       }
+       print "\n";
+    }
+}
+
+sub output_function_asciidoc(%) {
+    my %args = %{$_[0]};
+    my ($parameter, $section);
+    my $start;
+
+    print "[[func_$args{'function'}]]\n";
+    print "=== " . $args{'function'} . " ===\n";
+    print $args{'purpose'} . "\n\n";
+
+    print "----------\n";
+    if ($args{'functiontype'} ne "") {
+       $start = $args{'functiontype'} . " " . $args{'function'} . " (";
+    } else {
+       $start = $args{'function'} . " (";
+    }
+    print $start;
+
+    my $count = 0;
+    foreach my $parameter (@{$args{'parameterlist'}}) {
+       $type = $args{'parametertypes'}{$parameter};
+       if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+           # pointer-to-function
+           print $1 . $parameter . ") (" . $2;
+       } else {
+           print $type . " " . $parameter;
+       }
+       if ($count != $#{$args{'parameterlist'}}) {
+           $count++;
+           print ",\n";
+           print " " x length($start);
+       } else {
+           print ");\n\n";
+       }
+    }
+    print "----------\n";
+
+    print ".Parameters\n";
+    print "[horizontal]\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+       $type = $args{'parametertypes'}{$parameter};
+
+       print "`$type $parameter`::\n";
+       if ($args{'parameterdescs'}{$parameter_name} ne $undescribed) {
+           $blankline = "+";
+           output_highlight_asciidoc($args{'parameterdescs'}{$parameter_name});
+           $blankline = "\n";
+       } else {
+           print "_undescribed_\n";
+       }
+       print "\n";
+    }
+    output_section_asciidoc(@_);
+}
+
+sub output_section_asciidoc(%) {
+    my %args = %{$_[0]};
+    my $section;
+
+    foreach $section (@{$args{'sectionlist'}}) {
+       print ".$section\n\n";
+       output_highlight_asciidoc($args{'sections'}{$section});
+       print "\n";
+    }
+    print "\n";
+}
+
+sub output_enum_asciidoc(%) {
+    my %args = %{$_[0]};
+    my ($parameter);
+    my $count;
+
+    print "[[enum_$args{'enum'}]]\n";
+    print "=== enum " . $args{'enum'} . " ===\n";
+    print $args{'purpose'} . "\n\n";
+
+    print "----------\n";
+    print "enum " . $args{'enum'} . " {\n";
+    $count = 0;
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print "\t$parameter";
+       if ($count != $#{$args{'parameterlist'}}) {
+           $count++;
+           print ",";
+       }
+       print "\n";
+    }
+    print "};\n";
+    print "----------\n";
+
+    print ".Constants\n";
+    print "[horizontal]\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       print "`$parameter`::\n";
+       if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
+           $blankline = "+";
+           output_highlight_asciidoc($args{'parameterdescs'}{$parameter});
+           $blankline = "\n";
+       } else {
+           print "_undescribed_\n";
+       }
+       print "\n";
+    }
+
+    output_section_asciidoc(@_);
+}
+
+sub output_typedef_asciidoc(%) {
+    my %args = %{$_[0]};
+    my ($parameter);
+    my $count;
+
+    print "[[$args{'typedef'}]]\n";
+    print "=== typedef " . $args{'typedef'} . " ===\n";
+    print $args{'purpose'} . "\n\n";
+
+    output_section_asciidoc(@_);
+}
+
+sub output_struct_asciidoc(%) {
+    my %args = %{$_[0]};
+    my ($parameter);
+
+    print "[[$args{'type'}_$args{'struct'}]]\n";
+    print "=== " . $args{'type'} . " " . $args{'struct'} . " ===\n";
+    print $args{'purpose'} . "\n\n";
+
+    print "----------\n";
+    print $args{'type'} . " " . $args{'struct'} . " {\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       if ($parameter =~ /^#/) {
+           print "$parameter\n";
+           next;
+       }
+
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       $type = $args{'parametertypes'}{$parameter};
+       if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+           # pointer-to-function
+           print "\t$1 $parameter) ($2);\n";
+       } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
+           # bitfield
+           print "\t$1 $parameter$2;\n";
+       } else {
+           print "\t" . $type . " " . $parameter . ";\n";
+       }
+    }
+    print "};\n";
+    print "----------\n";
+
+    print ".Members\n";
+    print "[horizontal]\n";
+    foreach $parameter (@{$args{'parameterlist'}}) {
+       ($parameter =~ /^#/) && next;
+
+       my $parameter_name = $parameter;
+       $parameter_name =~ s/\[.*//;
+
+       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+       $type = $args{'parametertypes'}{$parameter};
+       print "`$type $parameter`" . "::\n";
+       $blankline = "+";
+       output_highlight_asciidoc($args{'parameterdescs'}{$parameter_name});
+       $blankline = "\n";
+       print "\n";
+    }
+    print "\n";
+    output_section_asciidoc(@_);
+}
+
+sub output_blockhead_asciidoc(%) {
+    my %args = %{$_[0]};
+    my ($parameter, $section);
+
+    foreach $section (@{$args{'sectionlist'}}) {
+       print "=== $section ===\n";
+       output_highlight_asciidoc($args{'sections'}{$section});
+       print "\n";
+    }
+}
+
 ## list mode output functions
 
 sub output_function_list(%) {
@@ -2414,6 +2639,18 @@ sub xml_escape($) {
        return $text;
 }
 
+# xml_unescape: reverse the effects of xml_escape
+sub xml_unescape($) {
+       my $text = shift;
+       if (($output_mode eq "text") || ($output_mode eq "man")) {
+               return $text;
+       }
+       $text =~ s/\\\\\\amp;/\&/g;
+       $text =~ s/\\\\\\lt;/</g;
+       $text =~ s/\\\\\\gt;/>/g;
+       return $text;
+}
+
 # convert local escape strings to html
 # local escape strings look like:  '\\\\menmonic:' (that's 4 backslashes)
 sub local_unescape($) {
-- 
2.7.0

Reply via email to