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",
+ "| Field | Summary | Type | DCT | ",
+ "Default | Read | Write | CA PP |
\n",
+ $content, "
\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 "$_[0]";
- print $out "| Field | \n";
- print $out "Summary | \n";
- print $out "Type | \n";
- print $out "DCT | \n";
- print $out "Default | \n";
- print $out "Read | \n";
- print $out "Write | \n";
- print $out "caPut=PP | \n";
-
-}
-
-#print the tail end of the table
-sub printTableEnd {
- print $out "
\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;
+}