WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 1/4] docs/html/hcall: Initial cut of header documenta

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 1/4] docs/html/hcall: Initial cut of header documentation massager
From: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Date: Sun, 13 Nov 2011 19:21:03 +0000
Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Delivery-date: Sun, 13 Nov 2011 11:23:23 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <1321212066-10648-1-git-send-email-ian.jackson@xxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <1321212066-10648-1-git-send-email-ian.jackson@xxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
"xen-headers" generates HTML from header files.  So far this generates
just some type cross-references, if you say
   make -C docs html/hcall/stamp

An index page, proper wiring into the build system, and a few more
annotations in the headers, and will be forthcoming.

Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
---
 docs/Makefile    |    8 ++
 docs/xen-headers |  281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 289 insertions(+), 0 deletions(-)
 create mode 100755 docs/xen-headers

diff --git a/docs/Makefile b/docs/Makefile
index 2054541..fc42859 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -129,6 +129,14 @@ html/%.html: %.markdown
        $(MARKDOWN) $< > $@.tmp ; \
        $(call move-if-changed,$@.tmp,$@) ; fi
 
+html/hcall/stamp:
+       @$(INSTALL_DIR) $(@D)
+       ./xen-headers -O $(@D) \
+               -T 'arch-x86_64 - Xen public headers' \
+               -X arch-ia64 -X arch-x86_32 -X xen-x86_32 \
+               ../xen include/public
+       touch $@
+
 txt/%.txt: %.txt
        $(INSTALL_DIR) $(@D)
        cp $< $@.tmp
diff --git a/docs/xen-headers b/docs/xen-headers
new file mode 100755
index 0000000..6918380
--- /dev/null
+++ b/docs/xen-headers
@@ -0,0 +1,281 @@
+#!/usr/bin/perl -w
+# usage: xen-headers [ -X GLOB -I GLOB ... [-D...] ] \
+#                    -O HTML-DIR PUBLIC-INCLUDE-DIR
+
+# enum values --> selected function or struct
+# type & function names --> definition
+# function or struct selected by enum ++> ref to enum value
+
+# definitions must start in LH column
+# extra syntax:
+#    /* ` <definition>                          } parse as if <definition>
+#     * ` <definition>                          }  was not commented
+#   enum <name> { // <pattern>* => <func>()     } cross-reference
+#   enum <name> { // <pattern>* => struct <s>   }  enum values
+
+# 1st pass: find where things are defined and what references are wanted
+# 2rd pass: write out output
+
+use strict;
+use warnings;
+
+use Getopt::Long;
+use File::Find;
+use IO::File;
+
+Getopt::Long::Configure('bundling');
+
+our $outdir;
+our $debug=0;
+our $xtitle='';
+our @fglobs;
+
+sub includeexclude {
+    my ($yn, $optobj, $value) = @_;
+    push @fglobs, [ $value, $yn ];
+}
+
+GetOptions("O|output-dir=s" => \$outdir,
+           "D+" => \$debug,
+           "T=s" => \$xtitle,
+          "I=s" => sub { includeexclude(1, @_); },
+          "X=s" => sub { includeexclude(0, @_); })
+    or die;
+
+die unless defined $outdir;
+@ARGV>=2 or die;
+
+my ($basedir,@indirs) = @ARGV;
+
+# general globals
+our $pass;
+our %sdef; 
+# $sdef{$type}{$name} => {
+#     DefLocs => { "$leaf_path:$lineno" => $leaf_opath ,... }
+#     Xrefs => { "$leaf_path,$lineno" => "$xref", ... }
+#     Used => 1
+# }
+# $type might be  Func Struct Union Enum EnumVal
+
+# provided by the find() function
+our $leaf;
+our $leaf_opath;
+
+# reset at the start of each file
+our $o;
+our $in_enum;
+our @pending_xrefs;
+
+sub compile_fglobs () {
+    local ($_);
+    my $f = "sub file_wanted (\$) {\n    local (\$_) = \"/\$leaf\";\n";
+    foreach my $fglob (@fglobs) {
+       $_ = $fglob->[0];
+       $_ = "**$_**" unless m/[?*]/;
+       s/\W/\\$&/g;
+       s,\\\*\\\*,.*,g;
+       s,\\\*,[^/]*,g;
+       s,\\\?,[^/],g;
+       $f .= "    return $fglob->[1] if m,$_,o;\n";
+    }
+    $f .= "    return 1;\n}\n1;\n";
+    debug(3, $f);
+    eval $f or die "$@ ";
+}
+
+compile_fglobs();
+
+
+sub warning {
+    print STDERR "$leaf:$.: @_\n";
+}
+
+sub debug {
+    my $msglevel = scalar shift @_;
+    return unless $debug >= $msglevel;
+    print STDERR "DEBUG $pass $msglevel @_\n" or die $!;
+}
+
+sub in_enum ($$$) { $in_enum = [ @_ ]; } # [ $enumvalpfx, RefType, $refnamepfx 
]
+
+sub aelem ($$$) {
+    my ($ntext,$ytext,$hparams) = @_;
+    return $ntext unless $hparams =~ m/\S/;
+    return "<a $hparams>$ytext</a>";
+}
+
+sub defn ($$$;$) {
+    my ($text,$type,$name,$hparams) = @_;
+    $hparams='' if !defined $hparams;
+    debug(2,"DEFN $. $type $name $hparams");
+    $sdef{$type}{$name}{DefLocs}{"$leaf:$."} = $leaf_opath;
+    my $xrefs = $sdef{$type}{$name}{Xrefs};
+    push @pending_xrefs, values %$xrefs if $xrefs;
+    $hparams .= " name=\"${type}_$name\"" if $sdef{$type}{$name}{Used};
+    return aelem($text, "<strong>$text</strong>", $hparams);
+}
+
+sub norm ($) {
+    local ($_) = @_;
+    my $no = '';
+    while (length) {
+       if (s/^(?:\s|^\W)+//) {
+           $no .= $&;
+       } elsif (s/^(struct|union|enum)\s+(\w+)\b//) {
+           $no .= ahref($&, (ucfirst $1), $2);
+       } elsif (s/^\w+\b//) {
+           $no .= ahref($&, 'Func', $&);
+       } else {
+           die "$_ ?";
+       }
+    }
+    return $no;
+}
+
+sub refhref ($$) {
+    my ($type,$name) = @_;
+    $sdef{$type}{$name}{Used} = 1;
+    my $locs = $sdef{$type}{$name}{DefLocs};
+    return '' unless $locs;
+    if ((scalar keys %$locs) != 1 && !$sdef{$type}{$name}{MultiWarned}) {
+       warning("multiple definitions of $type $name: $_")
+           foreach keys %$locs;
+       $sdef{$type}{$name}{MultiWarned}=1;
+    }
+    my ($loc) = values %$locs;
+    return "href=\"$loc#${type}_$name\"";
+}
+
+sub ahref ($$$) {
+    my ($text,$type,$name) = @_;
+    return aelem($text,$text, refhref($type,$name));
+}
+
+sub defmacro ($) {
+    my ($valname) = @_;
+    if (!$in_enum) {
+       return $valname;
+    } elsif (substr($valname, 0, (length $in_enum->[0])) ne $in_enum->[0]) {
+       warning("in enum expecting $in_enum->[0]* got $valname");
+       return $valname;
+    } else {
+       my $reftype = $in_enum->[1];
+       my $refname = $in_enum->[2].substr($valname, (length $in_enum->[0]));
+       $sdef{$reftype}{$refname}{Xrefs}{$leaf,$.} =
+           "[see <a href=\"$leaf_opath#EnumVal_$valname\">$valname</a>]";
+       $sdef{EnumVal}{$valname}{Used} = 1;
+       return defn($valname,'EnumVal',$valname, refhref($reftype,$refname));
+    }
+}
+
+sub out_xrefs ($) {
+    my ($linemapfunc) = @_;
+    foreach my $xref (@pending_xrefs) {
+       $o .= $linemapfunc->($xref);
+       $o .= "\n";
+    }
+    @pending_xrefs = ();
+}
+
+sub write_file ($$) {
+    my ($opath, $odata) = @_;
+    my $out = new IO::File "$opath.new", '>' or die "$opath $!";
+    print $out $odata or die $!;
+    rename "$opath.new", "$opath" or die "$opath $!";
+}
+
+sub process_file ($$) {
+    my ($infile, $outfile) = @_;
+    debug(1,"$pass $infile => $outfile");
+    my $in = new IO::File "$infile", '<' or die "$infile $!";
+
+    $o = '';
+    $in_enum = undef;
+    @pending_xrefs = ();
+
+    $o .= "<html><head><title>$leaf - $xtitle</title></head><body><pre>\n";
+    
+    while (<$in>) {
+       s/\&/\&amp;/g;
+       s/\</\&lt;/g;
+       s/\>/\&gt;/g;
+
+       if (m/^(.*\`)[ \t]*$/) {
+           my $lhs = $1;
+           out_xrefs(sub { "$1 $_[0]"; });
+       } elsif (m/^\s*$/) {
+           out_xrefs(sub { sprintf "/* %70s */", $_[0]; });
+       }
+
+       # In case of comments, strip " /* ` " and " * ` ";
+       my $lstripped = s,^ \s* /? \* \s* \` \  ,,x ? $&: '';
+
+       # Strip trailing whitespace and perhaps trailing "*/" or "*"
+       s,(?: \s* \* /? )? \s* $,,x or die;
+       my $rstripped = $&;
+
+       # Now the actual functionality:
+
+       debug(3,"$. $_");
+
+       if (s/^( (?: \w+\  )? ) (\w+[a-z]\w+) ( \( .*)$
+             / $1.defn($2,'Func',$2).norm($3) /xe) {
+       } elsif (s/^((struct|union|enum) \  (\w+)) ( \s+ \{ .* )$
+                  / defn($1,(ucfirst $2),$3).norm($4) /xe) {
+           if ($2 eq 'enum') {
+               if (m,/[/*] (\w+)\* \=\&gt\; (\w+)\*\(\),) { 
+                   in_enum($1,'Func',$2)
+               } elsif (m,/[/*] (\w+)\* \=\&gt\; (struct) (\w+)\*,) { 
+                   in_enum($1,(ucfirst $2),$3);
+               }
+           }
+       } elsif (s/^( \s* \#define \s+ ) (\w+) ( \s+\S )
+                  / $1.defmacro($2).norm($3) /xe) {
+       } else {
+           if (m/^\s*\}/) {
+               $in_enum = undef;
+           }
+           $_ = norm($_);
+       }
+
+       # Write the line out
+
+       if ($pass == 2) {
+           $o .= $lstripped;
+           $o .= $_;
+           $o .= $rstripped;
+       }
+    }
+
+    warning("pending xrefs at end of file") if @pending_xrefs;
+
+    if ($pass == 2) {
+       $o .= "</pre></body></html>";
+       write_file($outfile, $o);
+    }
+}
+
+
+foreach $pass (qw(1 2)) {
+    find({ wanted => 
+              sub {
+                  return unless m/\.h$/;
+                  lstat $File::Find::name or die "$File::Find::name $!";
+                  -f _ or die "$File::Find::name";
+                  substr($File::Find::name, 0, 1+length $basedir) 
+                      eq "$basedir/"
+                      or die "$File::Find::name $basedir";
+                  $leaf = substr($File::Find::name, 1+length $basedir);
+                  if (!file_wanted()) {
+                      debug(1,"$pass $File::Find::name excluded");
+                      return;
+                  }
+                  $leaf_opath = $leaf;
+                  $leaf_opath =~ s#/#,#g;
+                  $leaf_opath .= ".html";
+                  process_file($File::Find::name, $outdir.'/'.$leaf_opath);
+          },
+          no_chdir => 1,
+        },
+        map { "$basedir/$_" } @indirs);
+}
-- 
1.7.2.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel