Files
epics-base/src/tools/dbdToHtml.pl
Andrew Johnson 29a9ad3f90 Make the DBD parser recognize Pod syntax directly
Source DBD files can include Pod blocks, as long as the dbdExpand.pl
script doesn't try and include it in expanded DBD output files.
This makes it easier to write the Pod, and perldoc can parse most
of the result for checking (it complains about the =field directives
though, which dbdToHtml.pl handles itself).
2012-09-04 00:35:17 -05:00

160 lines
4.6 KiB
Perl

#!/usr/bin/perl
#*************************************************************************
# Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
# $Id$
use FindBin qw($Bin);
use lib "$Bin/../../lib/perl";
use DBD;
use DBD::Parser;
use EPICS::Getopts;
use EPICS::macLib;
use EPICS::Readfile;
use Pod::Simple::HTML;
my $tool = 'dbdToHtml';
getopts('DI@o:') or
die "Usage: $tool [-D] [-I dir] [-o file.html] file.dbd\n";
my $dbd = DBD->new();
my $infile = shift @ARGV;
$infile =~ m/\.dbd$/ or
die "$tool: Input file '$infile' must have '.dbd' extension\n";
&ParseDBD($dbd, &Readfile($infile, 0, \@opt_I));
if (!$opt_o) {
($opt_o = $infile) =~ s/\.dbd$/.html/;
$opt_o =~ s/^.*\///;
$opt_o =~ s/dbCommonRecord/dbCommon/;
}
if ($opt_D) { # Output dependencies only
my %filecount;
my @uniqfiles = grep { not $filecount{$_}++ } @inputfiles;
print "$opt_o: ", join(" \\\n ", @uniqfiles), "\n\n";
print map { "$_:\n" } @uniqfiles;
exit 0;
}
open my $out, '>', $opt_o or die "Can't create $opt_o: $!\n";
# Grab the Pod text from the root DBD object
my @pod = $dbd->pod;
my $rtypes = $dbd->recordtypes;
# Append the processed Pod text from any record types defined
while (my ($rn, $rtyp) = each %{$rtypes}) {
foreach my $_ ($rtyp->pod) {
# Handle our 'fields' Pod directive
if (m/^=fields (.*)/) {
my @names = split /\s*,\s*/, $1;
# Look up every named field
my @fields = map {
my $field = $rtyp->field($_);
print STDERR "Unknown field name '$_' in $infile POD\n" unless $field;
$field;
} @names;
my $html;
# Generate a HTML table row for each field
foreach $field (@fields) {
$html .= $field->htmlTableRow if $field;
}
# Add the complete table
push @pod, podTable($html);
}
else {
# Add other Pod text
push @pod, $_;
}
}
}
my $podHtml = Pod::Simple::HTML->new();
$podHtml->html_css('style.css');
$podHtml->perldoc_url_prefix('');
$podHtml->perldoc_url_postfix('.html');
$podHtml->set_source(\@pod);
# $podHtml->index(1);
$podHtml->output_string(\my $html);
$podHtml->run;
print $out $html;
close $out;
sub podTable {
my $content = shift;
return ("=begin html\n", "\n",
"<blockquote><table border =\"1\"><tr>\n",
"<th>Field</th><th>Summary</th><th>Type</th><th>DCT</th>",
"<th>Default</th><th>Read</th><th>Write</th><th>CA PP</th></tr>\n",
$content, "</table></blockquote>\n",
"\n", "=end html\n");
}
sub DBD::Recfield::htmlTableRow {
my $fld = shift;
my $html = '<tr><td class="cell">';
$html .= $fld->name;
$html .= '</td><td class="cell">';
$html .= $fld->attribute('prompt');
$html .= '</td><td class="cell">';
my $type = $fld->public_type;
$html .= $type;
$html .= ' [' . $fld->attribute('size') . ']'
if $type eq 'STRING';
$html .= ' (' . $fld->attribute('menu') . ')'
if $type eq 'MENU';
$html .= '</td><td class="cell">';
$html .= $fld->attribute('promptgroup') ? 'Yes' : 'No';
$html .= '</td><td class="cell">';
$html .= $fld->attribute('initial') || '&nbsp;';
$html .= '</td><td class="cell">';
$html .= $fld->readable;
$html .= '</td><td class="cell">';
$html .= $fld->writable;
$html .= '</td><td class="cell">';
$html .= $fld->attribute('pp') eq "TRUE" ? 'Yes' : 'No';
$html .= "</td></tr>\n";
return $html;
}
# Native type presented to dbAccess users
sub DBD::Recfield::public_type {
my $fld = shift;
m/^=type (.+)$/i && return $1 for $fld->comments;
my $type = $fld->dbf_type;
$type =~ s/^DBF_//;
return $type;
}
# Check if this field is readable
sub DBD::Recfield::readable {
my $fld = shift;
m/^=read (Yes|No)$/i && return $1 for $fld->comments;
return 'Probably'
if $fld->attribute('special') eq "SPC_DBADDR";
return $fld->dbf_type eq 'DBF_NOACCESS' ? 'No' : 'Yes';
}
# Check if this field is writable
sub DBD::Recfield::writable {
my $fld = shift;
m/^=write (Yes|No)$/i && return $1 for $fld->comments;
my $special = $fld->attribute('special');
return 'No'
if $special eq "SPC_NOMOD";
return 'Maybe'
if $special eq "SPC_DBADDR";
return $fld->dbf_type eq "DBF_NOACCESS" ? 'No' : 'Yes';
}