From 874cebb63d452ff414c221c8d391c17d5468030b Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 30 Aug 2012 00:55:22 -0500 Subject: [PATCH] Change dbdToHtml.pl to parse POD from DBD comments --- src/tools/Makefile | 3 + src/tools/dbdToHtml.pl | 290 +++++++++------------------ src/tools/style.css | 433 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 531 insertions(+), 195 deletions(-) create mode 100644 src/tools/style.css diff --git a/src/tools/Makefile b/src/tools/Makefile index 496b0e4d1..88707df47 100644 --- a/src/tools/Makefile +++ b/src/tools/Makefile @@ -51,5 +51,8 @@ PERL_SCRIPTS += dbdExpand.pl PERL_SCRIPTS += dbdToHtml.pl PERL_SCRIPTS += registerRecordDeviceDriver.pl +HTMLS_DIR = std +HTMLS = style.css + include $(TOP)/configure/RULES diff --git a/src/tools/dbdToHtml.pl b/src/tools/dbdToHtml.pl index 936cbf48c..f41e656a9 100644 --- a/src/tools/dbdToHtml.pl +++ b/src/tools/dbdToHtml.pl @@ -1,5 +1,4 @@ #!/usr/bin/perl - #************************************************************************* # Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne # National Laboratory. @@ -17,6 +16,7 @@ use DBD::Parser; use EPICS::Getopts; use EPICS::macLib; use EPICS::Readfile; +use Pod::Simple::HTML; my $tool = 'dbdToHtml'; getopts('DI@o:') or @@ -31,6 +31,12 @@ $infile =~ m/\.dbd$/ or &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; @@ -39,214 +45,108 @@ if ($opt_D) { # Output dependencies only exit 0; } -my $out; -if ($opt_o) { - $out = $opt_o; -} else { - ($out = $infile) =~ s/\.dbd$/.html/; - $out =~ s/^.*\///; - $out =~ s/dbCommonRecord/dbCommon/; -} -open $out, '>', $opt_o or die "Can't create $opt_o: $!\n"; +open my $out, '>', $opt_o or die "Can't create $opt_o: $!\n"; -print $out "

$infile

\n"; +my @pod = map { s/^ //; $_ } $dbd->comments; my $rtypes = $dbd->recordtypes; -my ($rn, $rtyp) = each %{$rtypes}; -print $out "

Record Name $rn

\n"; - -my @fields = $rtyp->fields; - -#create a Hash to store the table of field information for each GUI type -%dbdTables = ( - "GUI_COMMON" => "", - "GUI_COMMON" => "", - "GUI_ALARMS" => "", - "GUI_BITS1" => "", - "GUI_BITS2" => "", - "GUI_CALC" => "", - "GUI_CLOCK" => "", - "GUI_COMPRESS" => "", - "GUI_CONVERT" => "", - "GUI_DISPLAY" => "", - "GUI_HIST" => "", - "GUI_INPUTS" => "", - "GUI_LINKS" => "", - "GUI_MBB" => "", - "GUI_MOTOR" => "", - "GUI_OUTPUT" => "", - "GUI_PID" => "", - "GUI_PULSE" => "", - "GUI_SELECT" => "", - "GUI_SEQ1" => "", - "GUI_SEQ2" => "", - "GUI_SEQ3" => "", - "GUI_SUB" => "", - "GUI_TIMER" => "", - "GUI_WAVE" => "", - "GUI_SCAN" => "", - "GUI_NONE" => "" -); - - -#Loop over all of the fields. Build a string that contains the table body -#for each of the GUI Types based on which fields go with which GUI type. -foreach $fVal (@fields) { - my $pg = $fVal->attribute('promptgroup'); - while ( ($typ1, $content) = each %dbdTables) { - if ( $pg eq $typ1 or ($pg eq "" and $typ1 eq "GUI_NONE")) { - buildTableRow($fVal, $dbdTables{$typ1} ); - } +while (my ($rn, $rtyp) = each %{$rtypes}) { + foreach my $_ ($rtyp->comments) { + s/^ //; + if (m/^=fields (.*)/) { + my @names = split /,\s*/, $1; + my @fields = map { + my $field = $rtyp->field($_); + print STDERR "Unknown field name '$_' in $infile POD\n" unless $field; + $field; + } @names; + my $html; + foreach $field (@fields) { + $html .= $field->htmlTableRow if $field; + } + push @pod, podTable($html); + } + else { + push @pod, $_; + } } } -#Write out each table -while ( ($typ2, $content) = each %dbdTables) { - printHtmlTable($typ2, $content); +my $podHtml = Pod::Simple::HTML->new(); +$podHtml->html_css('style.css'); +$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", + "
\n", + "", + "\n", + $content, "
FieldSummaryTypeDCTDefaultReadWriteCA PP
\n", + "\n", "=end html\n"); } - -#add a field to a table body. The specified field and table body are passed -#in as parameters -sub buildTableRow { - my ( $fld, $outStr) = @_; - $longDesc = " "; - %htmlCellFmt = ( - rowStart => "", - nextCell => "", - endRow => "", - nextRow => "" - ); - my %cellFmt = %htmlCellFmt; - my $rowStart = $cellFmt{rowStart}; - my $nextCell = $cellFmt{nextCell}; - my $endRow = $cellFmt{endRow}; - my $nextRow = $cellFmt{nextRow}; - $outStr = $outStr . $rowStart; - $outStr = $outStr . $fld->name; - $outStr = $outStr . $nextCell; - $outStr = $outStr . $fld->attribute('prompt'); - $outStr = $outStr . $nextCell; - my $recType = $fld->dbf_type; - $typStr = $recType; - if ($recType eq "DBF_STRING") { - $typStr = $recType . " [" . $fld->attribute('size') . "]"; - } - - $outStr = $outStr . $typStr; - $outStr = $outStr . $nextCell; - $outStr = $outStr . design($fld); - $outStr = $outStr . $nextCell; - my $initial = $fld->attribute('initial'); - if ( $initial eq '' ) {$initial = " ";} - $outStr = $outStr . $initial; - $outStr = $outStr . $nextCell; - $outStr = $outStr . readable($fld); - $outStr = $outStr . $nextCell; - $outStr = $outStr . writable($fld); - $outStr = $outStr . $nextCell; - $outStr = $outStr . processPassive($fld); - $outStr = $outStr . $endRow; - $outStr = $outStr . "\n"; - $outStr = $outStr . $nextRow; - $outStr = $outStr . $longDesc; - $outStr = $outStr . $endRow; - $outStr = $outStr . "\n"; - $_[1] = $outStr; +sub DBD::Recfield::htmlTableRow { + my $fld = shift; + my $html = ''; + $html .= $fld->name; + $html .= ''; + $html .= $fld->attribute('prompt'); + $html .= ''; + my $type = $fld->public_type; + $html .= $type; + $html .= ' [' . $fld->attribute('size') . ']' + if $type eq 'STRING'; + $html .= ' (' . $fld->attribute('menu') . ')' + if $type eq 'MENU'; + $html .= ''; + $html .= $fld->attribute('promptgroup') ? 'Yes' : 'No'; + $html .= ''; + $html .= $fld->attribute('initial') || ' '; + $html .= ''; + $html .= $fld->readable; + $html .= ''; + $html .= $fld->writable; + $html .= ''; + $html .= $fld->attribute('pp') eq "TRUE" ? 'Yes' : 'No'; + $html .= "\n"; + return $html; } -#Check if the prompt group is defined so that this can be used by clients -sub design { - my $fld = $_[0]; - my $pg = $fld->attribute('promptgroup'); - if ( $pg eq '' ) { - my $result = 'No'; - } - else { - my $result = 'Yes'; - } +# 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 by clients -sub readable { - my $fld = $_[0]; - if ( $fld->attribute('special') eq "SPC_DBADDR") { - $return = "Probably"; - } - else{ - if ( $fld->dbf_type eq "DBF_NOACCESS" ) { - $return = "No"; - } - else { - $return = "Yes" - } - } +# 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 by clients -sub writable { - my $fld = $_[0]; - my $spec = $fld->attribute('special'); - if ( $spec eq "SPC_NOMOD" ) { - $return = "No"; - } - else { - if ( $spec ne "SPC_DBADDR") { - if ( $fld->dbf_type eq "DBF_NOACCESS" ) { - $return = "No"; - } - else { - $return = "Yes"; - } - } - else { - $return = "Maybe"; - } - } +# 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'; } - -#Check to see if the field is process passive on caput -sub processPassive { - my $fld = $_[0]; - $pp = $fld->attribute('pp'); - if ( $pp eq "YES" or $pp eq "TRUE" ) { - $result = "Yes"; - } - elsif ( $PP eq "NO" or $pp eq "FALSE" or $pp eq "" ) { - $result = "No"; - } -} - -#print the start row to define a table -sub printTableStart { - print $out " \n"; - print $out ""; - print $out "\n"; - print $out "\n"; - print $out "\n"; - print $out "\n"; - print $out "\n"; - print $out "\n"; - print $out "\n"; - print $out "\n"; - -} - -#print the tail end of the table -sub printTableEnd { - print $out "
$_[0]
FieldSummaryTypeDCTDefaultReadWritecaPut=PP
\n"; -} - -# Print the table for a GUI type. The name of the GUI type and the Table body -# for this type are fed in as parameters -sub printHtmlTable { - my ($typ2, $content) = $_; - if ( (length $_[1]) gt 0) { - printTableStart($_[0]); - print $out "$_[1]\n"; - printTableEnd(); - } - -} diff --git a/src/tools/style.css b/src/tools/style.css new file mode 100644 index 000000000..fe0ad441c --- /dev/null +++ b/src/tools/style.css @@ -0,0 +1,433 @@ +BODY, .logo { background: white; } + +BODY { + color: black; + font-family: arial,sans-serif; + margin: 0; + padding: 1ex; +} + +TABLE { + border-collapse: collapse; + border-spacing: 0; + border-width: 0; + color: inherit; +} + +IMG { border: 0; } +FORM { margin: 0; } +input { margin: 2px; } + +.logo { + float: left; + width: 264px; + height: 77px; +} + +.front .logo { + float: none; + display:block; +} + +.front .searchbox { + margin: 2ex auto; + text-align: center; +} + +.front .menubar { + text-align: center; +} + +.menubar { + background: #006699; + margin: 1ex 0; + padding: 1px; +} + +.menubar A { + padding: 0.8ex; + font: bold 10pt Arial,Helvetica,sans-serif; +} + +.menubar A:link, .menubar A:visited { + color: white; + text-decoration: none; +} + +.menubar A:hover { + color: #ff6600; + text-decoration: underline; +} + +A:link, A:visited { + background: transparent; + color: #006699; +} + +A[href="#POD_ERRORS"] { + background: transparent; + color: #FF0000; +} + +TD { + margin: 0; + padding: 0; +} + +DIV { + border-width: 0; +} + +DT { + margin-top: 1em; +} + +.credits TD { + padding: 0.5ex 2ex; +} + +.huge { + font-size: 32pt; +} + +.s { + background: #dddddd; + color: inherit; +} + +.s TD, .r TD { + padding: 0.2ex 1ex; + vertical-align: baseline; +} + +TH { + background: #bbbbbb; + color: inherit; + padding: 0.4ex 1ex; + text-align: left; +} + +TH A:link, TH A:visited { + background: transparent; + color: black; +} + +.box { + border: 1px solid #006699; + margin: 1ex 0; + padding: 0; +} + +.distfiles TD { + padding: 0 2ex 0 0; + vertical-align: baseline; +} + +.manifest TD { + padding: 0 1ex; + vertical-align: top; +} + +.l1 { + font-weight: bold; +} + +.l2 { + font-weight: normal; +} + +.t1, .t2, .t3, .t4, .t5 { + background: #006699; + color: white; +} +.t4 { + padding: 0.2ex 0.4ex; +} +.t1, .t2, .t3 { + padding: 0.5ex 1ex; +} + +/* IE does not support .box>.t1 Grrr */ +.box .t1, .box .t2, .box .t3, .box .t5 { + margin: 0; +} + +.t1 { + font-size: 1.4em; + font-weight: bold; + text-align: center; +} + +.t2 { + font-size: 1.0em; + font-weight: bold; + text-align: left; +} + +.t3 { + font-size: 1.0em; + font-weight: normal; + text-align: left; +} + +.t5 { + font-size: 0.8em; + font-weight: normal; + text-align: center; +} + +/* width: 100%; border: 0.1px solid #FFFFFF; */ /* NN4 hack */ + +.datecell { + text-align: center; + width: 17em; +} + +.cell { + padding: 0.2ex 1ex; + text-align: left; +} + +.label { + background: #aaaaaa; + color: black; + font-weight: bold; + padding: 0.2ex 1ex; + text-align: right; + white-space: nowrap; + vertical-align: baseline; +} + +.categories { + border-bottom: 3px double #006699; + margin-bottom: 1ex; + padding-bottom: 3ex; + padding-top: 2ex; +} + +.categories TABLE { + margin: auto; +} + +.categories TD { + padding: 0.5ex 1ex; + vertical-align: baseline; +} + +.path A { + background: transparent; + color: #006699; + font-weight: bold; +} + +.pages { + background: #dddddd; + color: #006699; + padding: 0.2ex 0.4ex; +} + +.path { + background: #dddddd; + border-bottom: 1px solid #006699; + color: #006699; + /* font-size: 1.4em;*/ + margin: 1ex 0; + padding: 0.5ex 1ex; +} + +.menubar TD { + background: #006699; + color: white; +} + +.menubar { + background: #006699; + color: white; + margin: 1ex 0; + padding: 1px; +} + +.menubar .links { + background: transparent; + color: white; + padding: 0.2ex; + text-align: left; +} + +.menubar .searchbar { + background: black; + color: black; + margin: 0px; + padding: 2px; + text-align: right; +} + +A.m:link, A.m:visited { + background: #006699; + color: white; + font: bold 10pt Arial,Helvetica,sans-serif; + text-decoration: none; +} + +A.o:link, A.o:visited { + background: #006699; + color: #ccffcc; + font: bold 10pt Arial,Helvetica,sans-serif; + text-decoration: none; +} + +A.o:hover { + background: transparent; + color: #ff6600; + text-decoration: underline; +} + +A.m:hover { + background: transparent; + color: #ff6600; + text-decoration: underline; +} + +table.dlsip { + background: #dddddd; + border: 0.4ex solid #dddddd; +} + +.pod, .manifest { margin-right: 20ex; } + +.pod PRE { + background: #eeeeee; + border: 1px solid #888888; + color: black; + padding: 1em; + white-space: pre; +} + +.pod H1 { + background: transparent; + color: #006699; + font-size: large; +} + +.pod H1 A { text-decoration: none; } +.pod H2 A { text-decoration: none; } +.pod H3 A { text-decoration: none; } +.pod H4 A { text-decoration: none; } + +.pod H2 { + background: transparent; + color: #006699; + font-size: medium; +} + +.pod H3 { + background: transparent; + color: #006699; + font-size: medium; + font-style: italic; +} + +.pod H4 { + background: transparent; + color: #006699; + font-size: medium; + font-weight: normal; +} + +.pod IMG { + vertical-align: top; +} + +.pod .toc A { + text-decoration: none; +} + +.pod .toc LI { + line-height: 1.2em; + list-style-type: none; +} + +.faq DT { + font-size: 1.4em; + font-weight: bold; +} + +.chmenu { + background: black; + color: red; + font: bold 1.1em Arial,Helvetica,sans-serif; + margin: 1ex auto; + padding: 0.5ex; +} + +.chmenu TD { + padding: 0.2ex 1ex; +} + +.chmenu A:link, .chmenu A:visited { + background: transparent; + color: white; + text-decoration: none; +} + +.chmenu A:hover { + background: transparent; + color: #ff6600; + text-decoration: underline; +} + +.column { + padding: 0.5ex 1ex; + vertical-align: top; +} + +.datebar { + margin: auto; + width: 14em; +} + +.date { + background: transparent; + color: #008000; +} + +.footer { + margin-top: 1ex; + text-align: right; + color: #006699; + font-size: x-small; + border-top: 1px solid #006699; + line-height: 120%; +} + +.front .footer { + border-top: none; +} + +#permalink { + float: right +} + +#permalink A { + font-size: small; +} + +.sr { + font-size: inherit; + margin: 0; +} + +.cpanstats { + float: left; + text-align: left; + color: #bbb; + white-space: pre; +} + +form.tool { + margin: 1ex; +} + +.styleswitch { + text-align: right; +}