|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 1/4] docs/html/: Initial cut of header documentation massager
On Tue, 2011-11-29 at 15:01 +0000, Ian Jackson wrote:
> "xen-headers" generates HTML from header files. So far this generates
> just some type cross-references, if you say
> make -C docs html/hypercall/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>
> [...]
> +GetOptions("O|output-dir=s" => \$outdir,
> + "D+" => \$debug,
> + "T=s" => \$xtitle,
> + "I=s" => sub { includeexclude(1, @_); },
> + "X=s" => sub { includeexclude(0, @_); })
Indentation is messed up (you've got a hard tab from somewhere).
With that fixed:
Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
(insofar as I can review Perl code...)
> + 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/\&/\&/g;
> + s/\</\</g;
> + s/\>/\>/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 (!m/^(?: __attribute__ | __pragma__ )\b/x &&
> + 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+)\* \=\>\; (\w+)\*\(\),) {
> + in_enum($1,'Func',$2)
> + } elsif (m,/[/*] (\w+)\* \=\>\; (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);
> +}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |