#!/usr/bin/perl
our
$VERSION
=
'3.027'
;
our
$LAST_UPDATE
=
'3.027'
;
my
$all
=
''
;
my
$libtop
=
"../lib"
;
my
$leading
=
"PDF"
;
my
$rootname
=
"Builder"
;
my
$output
=
"."
;
my
$TOC
=
""
;
my
$dirsep
=
'/'
;
my
$abstract_sep
=
' - '
;
my
$no_root_link
=
'0'
;
my
$not_pm
=
'0'
;
my
$help
=
'0'
;
my
(
$i
,
$fname
,
$bname
,
$filename
,
$dirname
);
my
@filelist
;
my
@file_list
;
if
(
scalar
(
@ARGV
) == 0) { help();
exit
(1); }
GetOptions(
'all'
=> \
$all
,
'help'
=> \
$help
,
'h'
=> \
$help
,
'dirsep=s'
=> \
$dirsep
,
'absep=s'
=> \
$abstract_sep
,
'flagorphans'
=> \
$no_root_link
,
'noignore'
=> \
$not_pm
,
'libtop=s'
=> \
$libtop
,
'leading=s'
=> \
$leading
,
'rootname=s'
=> \
$rootname
,
'output=s'
=>\
$output
,
'toc=s'
=> \
$TOC
,
);
$all
= 1;
if
(
$help
) { help();
exit
(2); }
if
(
$leading
eq
'""'
||
$leading
eq
"''"
) {
$leading
=
''
; }
if
(
$leading
ne
''
) {
$leading
=~ s
if
(
$rootname
eq
'""'
||
$rootname
eq
"''"
) {
$rootname
=
''
; }
if
(
$rootname
eq
''
) {
die
"ERROR --rootname must not be empty!\n"
;
}
if
(
$TOC
eq
''
) {
$TOC
=
$rootname
.
"_index.html"
; }
if
(!
$all
&&
scalar
(
@ARGV
) >= 1) {
while
(
$fname
=
$ARGV
[0]) {
if
(
$fname
=~ m
print
"$fname WARNING unknown flag skipped\n"
;
next
;
}
if
(
index
(
$fname
,
'::'
) > -1) {
$filename
= toFP(
$fname
);
}
else
{
$filename
=
$fname
;
}
push
@filelist
,
$filename
;
}
}
if
(
$all
) {
foreach
(
@ARGV
) {
print
"WARNING extra command line content '$_' ignored\n"
;
}
@file_list
= ();
$fname
=
"$libtop/"
;
if
(
$leading
ne
''
) {
$fname
.=
"$leading/"
; }
$fname
.=
$rootname
;
if
(-f
"$fname.pod"
&& -r
"$fname.pod"
) {
$fname
=
"$fname.pod"
;
}
else
{
$fname
=
"$fname.pm"
;
}
if
(!-f
$fname
) {
die
"$fname ERROR no $rootname .pod or .pm files found\n"
;
}
else
{
if
(!-r
$fname
) {
die
"$fname ERROR $rootname .pod or .pm file not readable\n"
;
}
@filelist
= (
$fname
);
}
foreach
(
@filelist
) {
push
@file_list
, {
fpname
=>
$_
,
ofname
=>toOF(
$_
),
pmname
=>toPM(
$_
),
status
=>-1,
accessible
=>1,
abstract
=>
''
,
parents
=>[],
siblings
=>[],
children
=>[],
depth
=>0,
};
}
if
(
$rootname
eq
''
) {
@filelist
= ();
$dirname
=
$libtop
;
if
(
$leading
ne
''
) {
$dirname
.=
"/$leading"
; }
opendir
my
$dh
,
$dirname
or
die
"$dirname ERROR can't open and read directory\n"
;
while
(
my
$direntry
=
readdir
$dh
) {
if
(
$direntry
eq
'.'
||
$direntry
eq
'..'
) {
next
; }
$fname
=
"$dirname/$direntry"
;
if
(-d
$fname
) {
push
@filelist
,
$fname
;
}
}
closedir
$dh
;
}
else
{
$dirname
=
$libtop
;
if
(
$leading
ne
''
) {
$dirname
.=
"/$leading"
; }
if
(-d
"$dirname/$rootname"
) {
@filelist
= (
"$dirname/$rootname"
);
}
else
{
@filelist
= ();
}
}
foreach
(
@filelist
) {
push
@file_list
, buildList(
$_
, toPM(
$_
));
}
}
else
{
if
(
scalar
@filelist
== 0) {
die
"no files given to update\n"
; }
}
for
(
my
$max_i
=
$#file_list
;
$max_i
>0;
$max_i
--) {
my
$swap
= 0;
for
(
my
$i
=0;
$i
<
$max_i
;
$i
++) {
if
(
$file_list
[
$i
]{
'pmname'
} gt
$file_list
[
$i
+1]{
'pmname'
}) {
my
%temp
;
$temp
{
'pmname'
} =
$file_list
[
$i
]{
'pmname'
};
$temp
{
'fpname'
} =
$file_list
[
$i
]{
'fpname'
};
$temp
{
'ofname'
} =
$file_list
[
$i
]{
'ofname'
};
$temp
{
'status'
} =
$file_list
[
$i
]{
'status'
};
$temp
{
'accessible'
} =
$file_list
[
$i
]{
'accessible'
};
$temp
{
'abstract'
} =
$file_list
[
$i
]{
'abstract'
};
$temp
{
'parents'
} =
$file_list
[
$i
]{
'parents'
};
$temp
{
'siblings'
} =
$file_list
[
$i
]{
'siblings'
};
$temp
{
'children'
} =
$file_list
[
$i
]{
'children'
};
$temp
{
'depth'
} =
$file_list
[
$i
]{
'depth'
};
$file_list
[
$i
]{
'pmname'
} =
$file_list
[
$i
+1]{
'pmname'
};
$file_list
[
$i
]{
'fpname'
} =
$file_list
[
$i
+1]{
'fpname'
};
$file_list
[
$i
]{
'ofname'
} =
$file_list
[
$i
+1]{
'ofname'
};
$file_list
[
$i
]{
'status'
} =
$file_list
[
$i
+1]{
'status'
};
$file_list
[
$i
]{
'accessible'
} =
$file_list
[
$i
+1]{
'accessible'
};
$file_list
[
$i
]{
'abstract'
} =
$file_list
[
$i
+1]{
'abstract'
};
$file_list
[
$i
]{
'parents'
} =
$file_list
[
$i
+1]{
'parents'
};
$file_list
[
$i
]{
'siblings'
} =
$file_list
[
$i
+1]{
'siblings'
};
$file_list
[
$i
]{
'children'
} =
$file_list
[
$i
+1]{
'children'
};
$file_list
[
$i
]{
'depth'
} =
$file_list
[
$i
+1]{
'depth'
};
$file_list
[
$i
+1]{
'pmname'
} =
$temp
{
'pmname'
};
$file_list
[
$i
+1]{
'fpname'
} =
$temp
{
'fpname'
};
$file_list
[
$i
+1]{
'ofname'
} =
$temp
{
'ofname'
};
$file_list
[
$i
+1]{
'status'
} =
$temp
{
'status'
};
$file_list
[
$i
+1]{
'accessible'
} =
$temp
{
'accessible'
};
$file_list
[
$i
+1]{
'abstract'
} =
$temp
{
'abstract'
};
$file_list
[
$i
+1]{
'parents'
} =
$temp
{
'parents'
};
$file_list
[
$i
+1]{
'siblings'
} =
$temp
{
'siblings'
};
$file_list
[
$i
+1]{
'children'
} =
$temp
{
'children'
};
$file_list
[
$i
+1]{
'depth'
} =
$temp
{
'depth'
};
$swap
= 1;
}
}
if
(!
$swap
) {
last
; }
}
my
(
$any_minus1
,
$source
,
$target
,
$htmlfile
,
$errorfile
);
do
{
$any_minus1
= 0;
for
(
my
$i
=0;
$i
<
scalar
@file_list
;
$i
++) {
if
(
$file_list
[
$i
]{
'status'
} == -1) {
$any_minus1
= 1;
$source
=
$file_list
[
$i
]{
'fpname'
};
$target
=
$file_list
[
$i
]{
'ofname'
};
mkdir_list(
$target
);
print
STDERR
"processing $source\n"
;
my
$p
= Pod::Simple::XHTML->new();
my
$htmlfile
;
$p
->output_string(\
$htmlfile
);
$p
->html_charset(
'UTF-8'
);
$p
->html_encode_chars(
q{&<>'"}
);
$p
->html_doctype(
'<!DOCTYPE html>'
);
$p
->
index
(1);
$p
->parse_file(
$source
);
if
(
$htmlfile
eq
''
) {
print
"$source INFO no POD content\n"
;
$file_list
[
$i
]{
'status'
} = 0;
$htmlfile
=
"<html>\n<head>\n<title>$source</title>\n</head>\n"
;
$htmlfile
.=
"<body>\nNo documentation (POD) in this module</body>\n</html>\n"
;
}
else
{
$file_list
[
$i
]{
'status'
} = 1;
$htmlfile
=~ s
$htmlfile
=~ s
}
if
(
$htmlfile
=~ m
print
"$source ERROR POD errors reported\n"
;
$file_list
[
$i
]{
'status'
} = 3;
}
my
$pwd
=
$target
;
$pwd
=~ s
my
@pwd_dirs
=
split
/[\\\/]/,
$pwd
;
pop
@pwd_dirs
;
if
(
scalar
@pwd_dirs
> 0 &&
$pwd_dirs
[0] eq
''
) {
shift
@pwd_dirs
;
}
if
(
scalar
@pwd_dirs
> 0 &&
$pwd_dirs
[0] eq
'.'
) {
shift
@pwd_dirs
;
}
while
(
$htmlfile
=~ m
my
$href
= $1;
my
$linkname
= $2;
if
(
$href
=~ m/^
if
(
$href
=~ m
$href
=~ s
my
(
$path
,
$target
) =
split
/
if
(!
defined
$target
) {
$target
=
''
; }
my
@target_dirs
=
split
/[\\\/]/,
$path
;
my
$newhref
=
pop
@target_dirs
;
if
(
scalar
@target_dirs
> 0 &&
$target_dirs
[0] eq
''
) {
shift
@target_dirs
;
}
if
(
scalar
@target_dirs
> 0 &&
$target_dirs
[0] eq
'.'
) {
shift
@target_dirs
;
}
my
@copy_pwd_dirs
=
@pwd_dirs
;
while
(
scalar
@copy_pwd_dirs
> 0 &&
scalar
@target_dirs
> 0) {
if
(
$copy_pwd_dirs
[0] eq
$target_dirs
[0]) {
shift
@copy_pwd_dirs
;
shift
@target_dirs
;
}
else
{
last
;
}
}
if
(
scalar
@target_dirs
> 0) {
$newhref
=
join
(
$dirsep
,
@target_dirs
).
$dirsep
.
$newhref
;
}
if
(
scalar
@copy_pwd_dirs
> 0) {
for
(
my
$i
=0;
$i
<
scalar
@copy_pwd_dirs
;
$i
++) {
$newhref
=
'..'
.
$dirsep
.
$newhref
;
}
}
if
(
$target
eq
''
) {
$htmlfile
=~ s
}
else
{
$htmlfile
=~ s%/
$libtop
/
$href
%$newhref
}
my
$found
= 0;
my
$linkPM
=
$linkname
;
if
(
$linkPM
=~ m
$linkPM
= $1;
}
for
(
my
$j
=0;
$j
<
scalar
@file_list
;
$j
++) {
if
(
$file_list
[
$j
]{
'pmname'
} eq
$linkPM
) {
if
(
$file_list
[
$j
]{
'status'
} == -2) {
$file_list
[
$j
]{
'status'
} = -1;
$any_minus1
= 1;
}
$found
= 1;
last
;
}
}
if
(!
$found
) {
print
"$linkname ERROR does not appear to exist, called from $source\n"
;
}
}
if
(
$htmlfile
=~ m
my
$abstract
= $1;
$abstract
=~ s
$abstract
=~ s
$file_list
[
$i
]{
'abstract'
} =
$abstract
;
}
spew(
$htmlfile
,
$target
);
$file_list
[
$i
]{
'htmlname'
} =
$target
;
}
}
$any_minus1
= 0;
for
(
my
$i
=0;
$i
<
scalar
@file_list
;
$i
++) {
if
(
$file_list
[
$i
]{
'status'
} == -2) {
if
(
$no_root_link
) {
print
"$file_list[$i]{'pmname'} INFO no link from root for this HTML file\n"
;
}
$file_list
[
$i
]{
'accessible'
} = 0;
$file_list
[
$i
]{
'status'
} = -1;
$any_minus1
= 1;
}
}
}
while
(
$any_minus1
);
$fname
=
$output
;
if
(
$leading
ne
''
) {
$fname
.=
"/$leading"
; }
open
my
$fh
,
'>'
,
"$fname/$TOC"
or
die
"$fname/$TOC ERROR unable to open output index file\n"
;
print
$fh
"<!DOCTYPE html>\n"
;
print
$fh
"<html lang=\"en\">\n<head>\n<title>Master index for $file_list[0]{'pmname'}"
;
print
$fh
"</title>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n"
;
print
$fh
"<style>\n"
;
print
$fh
"body { margin: 10px; }\n"
;
print
$fh
"h1, h2, h3 { text-align: center; }\n"
;
print
$fh
".fixedwidth { display: inline-block; width: 2em; }\n"
;
print
$fh
".dummy {color: #999; }\n"
;
print
$fh
".errormsg { color: red; }\n"
;
print
$fh
"div { display: inline-block; }\n"
;
print
$fh
"</style>\n"
;
print
$fh
"</head>\n<body>\n"
;
print
$fh
"<h1>T A B L E O F C O N T E N T S</h1>\n"
;
print
$fh
"X = not accessible from root via chain of links<br>\n"
;
print
$fh
"<span class=\"errormsg\">ERROR</span> = POD errors of some sort reported<br>\n"
;
print
$fh
"(<span class=\"dummy\">no link</span>) = no POD, so empty .html file generated<br>\n"
;
print
$fh
" <br>\n"
;
for
(
my
$i
=0;
$i
<
scalar
@file_list
;
$i
++) {
if
(
$file_list
[
$i
]{
'status'
} < 0) {
print
"$file_list[$i]{'pmname'} ERROR still has status $file_list[$i]{'status'} at $TOC output!\n"
;
next
;
}
$fname
=
$file_list
[
$i
]{
'ofname'
};
if
(
$leading
ne
''
) {
$fname
=~ s
}
if
(
$file_list
[
$i
]{
'status'
} == 0) {
print
$fh
"<span class=\"dummy\">"
;
print
$fh
$file_list
[
$i
]{
'pmname'
}.
"</span>"
;
}
elsif
(
$file_list
[
$i
]{
'status'
} == 1) {
print
$fh
"<a href=\"$fname\">$file_list[$i]{'pmname'}</a>"
;
}
else
{
print
$fh
"<a href=\"$fname\">$file_list[$i]{'pmname'}</a> - <span class=\"errormsg\">ERROR</span>"
;
}
if
(
$file_list
[
$i
]{
'abstract'
} ne
''
) {
my
$string
=
$file_list
[
$i
]{
'abstract'
};
my
$pos
= 0;
while
(
$pos
> -1) {
if
(
$pos
< 0) {
last
; }
$pos
+= 6;
my
$pos2
=
index
$string
,
"\">"
,
$pos
;
my
$strLink
=
substr
(
$string
,
$pos
+25,
$pos2
-
$pos
-25);
my
$pos3
=
index
$strLink
,
"#"
;
if
(
$pos3
>= 0) {
$pos2
-=
length
(
$strLink
)-
$pos3
;
$strLink
=
substr
(
$strLink
, 0,
$pos3
);
}
$strLink
=~ s
$strLink
= go_up(
$file_list
[
$i
]{
'depth'
}) .
"../$strLink.html"
;
$string
=
substr
(
$string
, 0,
$pos
) .
$strLink
.
substr
(
$string
,
$pos2
);
}
print
$fh
" - $string"
;
}
print
$fh
"<br>\n"
;
}
print
$fh
"<h3>###</h3>\n"
;
print
$fh
"</body>\n</html>\n"
;
close
$fh
;
if
(
scalar
(
@file_list
) <= 1) {
print
"Only 0 or 1 file_list entries. Do not create NAVIGATION LINKS.\n"
;
exit
(0);
}
make_pmnameA();
my
(
$j
,
$ref
);
process(0,
scalar
(
@file_list
));
do_parents();
remove_grandchildren();
do_siblings();
update_HTML();
exit
(0);
sub
update_HTML{
my
(
$i
,
$fname
,
$string
,
@count
,
$ref
,
$pos
,
$newstring
,
@list
);
for
(
$i
=0;
$i
<
scalar
(
@file_list
);
$i
++) {
$fname
=
$file_list
[
$i
]{
'htmlname'
};
print
"Updating NAVIGATION LINKS in $fname\n"
;
$string
= slurp(
$fname
);
if
(
length
$string
== 0) {
print
"ERROR: unable to read in file $fname for Navigation Links update!\n"
;
next
;
}
@count
= (0, 0, 0);
$ref
=
$file_list
[
$i
]{
'parents'
};
if
(
defined
$ref
) {
$count
[0] =
scalar
(
@$ref
); }
$count
[0]++;
$ref
=
$file_list
[
$i
]{
'siblings'
};
if
(
defined
$ref
) {
$count
[1] =
scalar
(
@$ref
); }
$ref
=
$file_list
[
$i
]{
'children'
};
if
(
defined
$ref
) {
$count
[2] =
scalar
(
@$ref
); }
$pos
=
index
$string
,
"<div class='indexgroupEmpty'></div>"
;
if
(
$pos
> 0) {
$newstring
=
"<div class='indexgroup'>\n"
.
"<ul class='indexList indexList1'>\n"
.
"</ul>\n</div>"
;
$string
=
substr
(
$string
, 0,
$pos
) .
$newstring
.
substr
(
$string
,
$pos
+36);
}
$pos
=
index
$string
,
"<ul id=\"index\">"
;
if
(
$pos
< 0) {
print
"ERROR: can't find link index in file $fname.\n"
;
next
;
}
$pos
+= 15;
$newstring
=
" <li><a href=\"#NAVIGATION-LINKS\">NAVIGATION LINKS</a>\n"
.
" <ul>\n"
.
" <li><a href=\"#Up-Parents\">Up (Parents)</a></li>\n"
;
if
(
$count
[1]) {
$newstring
.=
" <li><a href=\"#Siblings\">Siblings</a></li>\n"
;
}
if
(
$count
[2]) {
$newstring
.=
" <li><a href=\"#Down-Children\">Down (Children)</a></li>\n"
;
}
$newstring
.=
" </ul>\n"
.
" </li>\n"
;
$string
=
substr
(
$string
, 0,
$pos
+1) .
$newstring
.
substr
(
$string
,
$pos
+1);
$pos
=
index
$string
,
"</body>"
;
$pos
--;
$newstring
=
"<h1 id=\"NAVIGATION-LINKS\">NAVIGATION LINKS</h1>\n"
;
$newstring
.=
"\n<h2 id=\"Up-Parents\">Up (Parents)</h2>\n"
;
$newstring
.=
"\n<p>"
.
"<a href=\""
.go_up(
$file_list
[
$i
]{
'depth'
}-1) .
"${rootname}_index.html\">Master Index</a><br>\n"
;
$ref
=
$file_list
[
$i
]{
'parents'
};
if
(
defined
$ref
&&
scalar
(
@$ref
)) {
@list
=
@$ref
;
foreach
(
@list
) {
$newstring
.=
"<a href=\""
.go_up(
$file_list
[
$i
]{
'depth'
}) .
"$file_list[$_]{'htmlname'}\">$file_list[$_]{'pmname'}</a> -- $file_list[$_]{'abstract'}<br>\n"
;
}
}
$newstring
.=
"</p>\n"
;
if
(
$count
[1]) {
$ref
=
$file_list
[
$i
]{
'siblings'
};
if
(
defined
$ref
&&
scalar
(
@$ref
)) {
$newstring
.=
"\n<h2 id=\"Siblings\">Siblings</h2>\n<p>\n"
;
@list
=
@$ref
;
foreach
(
@list
) {
$newstring
.=
"<a href=\""
.go_up(
$file_list
[
$i
]{
'depth'
}) .
"$file_list[$_]{'htmlname'}\">$file_list[$_]{'pmname'}</a> -- $file_list[$_]{'abstract'}<br>\n"
;
}
$newstring
.=
"</p>\n"
;
}
}
if
(
$count
[2]) {
$ref
=
$file_list
[
$i
]{
'children'
};
if
(
defined
$ref
&&
scalar
(
@$ref
)) {
$newstring
.=
"\n<h2 id=\"Down-Children\">Down (Children)</h2>\n<p>\n"
;
@list
=
@$ref
;
foreach
(
@list
) {
$newstring
.=
"<a href=\""
.go_up(
$file_list
[
$i
]{
'depth'
}) .
"$file_list[$_]{'htmlname'}\">$file_list[$_]{'pmname'}</a> -- $file_list[$_]{'abstract'}<br>\n"
;
}
$newstring
.=
"</p>\n"
;
}
}
$newstring
.=
"<h3>###</h3>\n"
;
$string
=
substr
(
$string
, 0,
$pos
+1) .
$newstring
.
substr
(
$string
,
$pos
+1);
$pos
= 0;
while
(
$pos
> -1) {
if
(
$pos
< 0) {
last
; }
$pos
+= 6;
my
$pos2
=
index
$string
,
"\">"
,
$pos
;
my
$strLink
=
substr
(
$string
,
$pos
+25,
$pos2
-
$pos
-25);
my
$pos3
=
index
$strLink
,
"#"
;
if
(
$pos3
>= 0) {
$pos2
-=
length
(
$strLink
)-
$pos3
;
$strLink
=
substr
(
$strLink
, 0,
$pos3
);
}
$strLink
=~ s
$strLink
= go_up(
$file_list
[
$i
]{
'depth'
}) .
"$strLink.html"
;
$string
=
substr
(
$string
, 0,
$pos
) .
$strLink
.
substr
(
$string
,
$pos2
);
}
$string
=~ s
$pos
= 0;
while
(1) {
$pos
=
index
(
$string
,
"<ul>\n\n<p>"
,
$pos
);
if
(
$pos
< 0) {
last
; }
my
$pos2
=
index
(
$string
,
"\n</ul>\n"
,
$pos
);
if
(
$pos2
< 0) {
last
; }
$newstring
=
substr
(
$string
,
$pos
+6,
$pos2
-
$pos
-7);
$newstring
=~ s
$newstring
=~ s
$string
=
substr
(
$string
, 0,
$pos
) .
$newstring
.
substr
(
$string
,
$pos2
+6);
}
spew(
$string
,
$fname
);
}
return
;
}
sub
go_up {
my
$depth
=
shift
;
if
(
$depth
< 1) {
return
''
; }
if
(
$depth
== 1) {
return
''
; }
return
'../'
x (
$depth
-1);
}
sub
process {
my
(
$start
,
$len
) =
@_
;
if
(
$len
<= 1) {
return
; }
my
(
$i
,
$j
,
$dir
);
my
(
$len2
,
$ref
,
$refc
);
$ref
=
$file_list
[
$start
]{
'pmnameA'
};
if
(
scalar
(
@$ref
) == 0) {
$refc
=
$file_list
[
$start
]{
'children'
};
for
(
$j
=1;
$j
<
$len
;
$j
++) {
push
@$refc
,
$start
+
$j
;
}
process(
$start
+1,
$len
-1);
return
;
}
LOOP:
while
(1) {
$ref
=
$file_list
[
$start
]{
'pmnameA'
};
last
if
!
scalar
(
@$ref
[0]);
$dir
=
@$ref
[0];
for
(
$i
=1;
$i
<
$len
;
$i
++) {
last
LOOP
if
@{
$file_list
[
$start
+
$i
]{
'pmnameA'
} }[0] ne
$dir
;
}
for
(
$i
=0;
$i
<
$len
;
$i
++) {
shift
@{
$file_list
[
$start
+
$i
]{
'pmnameA'
} };
}
process(
$start
,
$len
);
return
;
}
$len2
= 0;
for
(
$i
=
$start
;
$i
<
$start
+
$len
;
$i
++) {
$ref
=
$file_list
[
$i
]{
'pmnameA'
};
if
(
$len2
== 0) {
$dir
=
@$ref
[0];
$len2
++;
next
;
}
if
(
@$ref
[0] eq
$dir
) {
$len2
++;
next
;
}
else
{
process(
$start
,
$len2
);
process(
$start
+
$len2
,
$len
-
$len2
);
return
;
}
}
return
;
}
sub
remove_grandchildren {
my
(
$start
,
$ref
,
$refs
,
$ele
,
$i
,
$j
);
for
(
$start
=1;
$start
<
scalar
(
@file_list
);
$start
++) {
$refs
=
$file_list
[
$start
]{
'children'
};
if
(!
defined
$refs
) {
next
; }
if
(!
scalar
(
@$refs
)) {
next
; }
for
(
$ele
=0;
$ele
<
$start
;
$ele
++) {
$ref
=
$file_list
[
$ele
]{
'children'
};
if
(!
defined
$ref
) {
next
; }
if
(!
scalar
(
@$ref
)) {
next
; }
for
(
$i
=0;
$i
<
scalar
(
@$refs
);
$i
++) {
for
(
$j
=0;
$j
<
scalar
(
@$ref
);
$j
++) {
if
(
@$ref
[
$j
] ==
@$refs
[
$i
]) {
splice
(
@$ref
,
$j
, 1);
}
}
}
}
}
return
;
}
sub
do_parents {
my
(
$i
,
@children
,
$child
);
for
(
$i
=0;
$i
<
scalar
(
@file_list
);
$i
++) {
if
(!
defined
$file_list
[
$i
]{
'children'
}) {
next
; }
@children
= @{
$file_list
[
$i
]{
'children'
} };
if
(!
scalar
(
@children
)) {
next
; }
while
(
scalar
(
@children
)) {
$child
=
shift
@children
;
push
@{
$file_list
[
$child
]{
'parents'
} },
$i
;
}
}
return
;
}
sub
do_siblings {
my
(
$i
,
$j
,
$k
,
$refs
,
@children
,
$child
);
for
(
$i
=0;
$i
<
scalar
(
@file_list
);
$i
++) {
if
(!
defined
$file_list
[
$i
]{
'children'
}) {
next
; }
@children
= @{
$file_list
[
$i
]{
'children'
} };
if
(
scalar
(
@children
) <= 1) {
next
; }
for
(
$j
=0;
$j
<
scalar
(
@children
);
$j
++) {
$child
=
$children
[
$j
];
$refs
=
$file_list
[
$child
]{
'siblings'
};
for
(
$k
=0;
$k
<
scalar
(
@children
);
$k
++) {
push
@$refs
,
$children
[
$k
]
if
$children
[
$k
] !=
$child
;
}
}
}
return
;
}
sub
make_pmnameA {
my
(
@tempA
,
$i
,
$j
);
for
(
$i
=0;
$i
<
scalar
(
@file_list
);
$i
++) {
@tempA
=
split
/::/,
$file_list
[
$i
]{
'pmname'
};
$file_list
[
$i
]{
'depth'
} =
scalar
(
@tempA
);
$file_list
[
$i
]{
'pmnameA'
} = [];
for
(
$j
=0;
$j
<
scalar
(
@tempA
);
$j
++) {
@{
$file_list
[
$i
]{
'pmnameA'
}}[
$j
] =
$tempA
[
$j
];
}
}
return
;
}
sub
spew {
my
(
$string
,
$fname
) =
@_
;
open
(
my
$fh
,
'>'
,
$fname
) or
die
"$fname ERROR can't open file for output\n"
;
my
$first
= 1;
for
(
my
$i
=0;
$i
<
length
(
$string
);
$i
++) {
if
(
ord
(
substr
(
$string
,
$i
, 1)) > 127) {
if
(
$first
) {
print
"String: '$string'\n"
;
$first
= 0;
}
print
"Wide character "
.
ord
(
substr
(
$string
,
$i
, 1)).
" found at $i\n"
;
}
}
print
$fh
$string
;
close
$fh
;
return
;
}
sub
slurp {
my
$file
=
shift
;
open
(
my
$fh
,
'<'
,
$file
) or
die
"$file ERROR can't open file for input\n"
;
local
$/ =
undef
;
my
$cont
= <
$fh
>;
close
$fh
;
return
$cont
;
}
sub
mkdir_list {
my
$target
=
$_
[0];
my
@dirlist
=
split
/[\\\/]/,
$target
;
my
$dirstring
=
''
;
for
(
my
$i
=0;
$i
<
$#dirlist
;
$i
++) { # note skips
last
element, which is filename.html
if
(
$dirstring
eq
''
) {
$dirstring
=
$dirlist
[
$i
];
}
else
{
$dirstring
.=
'/'
.
$dirlist
[
$i
];
}
if
(
$dirlist
[
$i
] eq
'.'
||
$dirlist
[
$i
] eq
'..'
) {
next
; }
if
(!-d
$dirstring
) {
mkdir
$dirstring
;
}
}
return
;
}
sub
buildList {
my
(
$dirname
,
$PMname
) =
@_
;
my
@list
;
opendir
my
$dh
,
$dirname
or
die
"$dirname ERROR can't open and read directory\n"
;
while
(
my
$direntry
=
readdir
$dh
) {
if
(
$direntry
eq
'.'
||
$direntry
eq
'..'
) {
next
; }
if
(-f
"$dirname/$direntry"
) {
if
(!-r
"$dirname/$direntry"
) {
die
"$dirname/$direntry ERROR unreadable file\n"
; }
if
(
$direntry
!~ m
if
(
$not_pm
) {
print
"$dirname/$direntry INFO not .pod or .pm, ignored\n"
;
}
next
;
}
push
@list
, {
fpname
=>
"$dirname/$direntry"
,
ofname
=>toOF(
"$dirname/$direntry"
),
pmname
=>toPM(
"$dirname/$direntry"
),
status
=>-2,
accessible
=>1,
abstract
=>
''
,
parents
=>[],
siblings
=>[],
children
=>[],
depth
=>0
};
}
else
{
if
(!-d
"$dirname/$direntry"
) {
print
"$dirname/$direntry WARNING is not a directory or file, ignored\n"
;
next
; }
push
@list
, buildList(
"$dirname/$direntry"
,
"$PMname${direntry}::"
);
}
}
closedir
$dh
;
return
@list
;
}
sub
toPM {
my
$fname
=
$_
[0];
$fname
=~ s
$fname
=~ s
$fname
=~ s
$fname
=~ s
return
$fname
;
}
sub
toOF {
my
$fname
=
$_
[0];
$fname
=~ s
$fname
=~ s
return
$fname
;
}
sub
toFP {
my
$fname
=
$_
[0];
my
$filename
;
substr
(
$fname
, 0,
length
(
$leading
)+2) =
''
;
$filename
=
$fname
;
$filename
=~ s/::/
$dirsep
/g;
if
(-f
"$filename.pod"
&& -r
"$filename.pod"
) {
$filename
.=
".pod"
;
}
else
{
$filename
.=
'.pm'
;
}
return
$filename
;
}
sub
help {
my
$message
=
<<"END_OF_TEXT";
buildDoc.pl: build, using the Pod::Simple::XHTML utility, all the .html
documentation files for a package, from all the .pm (or .pod) files in
the package.
Using buildDoc.pl
input files from <libtop>/<leading>/<rootname>.pm
<rootname>/*.pm
<leading> may be empty string
output files to <output>/<rootname>/*.html
buildDoc.pl -h
**NOTE** When running on Windows, it is possible in some cases for a
directory separator / on the command line to be mistaken for an
option (flag). In such cases, surround the term with quotation
marks ".
--help this help text
--all process all .pod and .pm files at and below current directory.
this is the default, but is needed if no other command
line options are given
--dirsep=string default: "/" directory separator. As Windows
accepts the Unixy /, you should not have to change this
(except on the command line, where / means "option")
--absep=string default: " - ", the abstract separator found between
the module name and its abstract (description) in the POD NAME
section (as implemented for PDF::Builder)
--flagorphans default: off. If 'on', a warning will be given during
processing that the module appears to be unreachable from the "root"
.pod or .pm file. However, it can always be accessed from the TOC
index file
--noignore default: off. If 'on', a warning is given when a file
without a .pod or .pm filetype is encountered (and skipped).
This can help you to clean out junk like editor backup files.
--libtop=string default: "../lib". This is the directory path to get to the
top of the .pod/.pm source tree from wherever you are running this
documentation program. For PDF::Builder, the default is that you are
running this program in docs/, which is a sibling to the lib/PDF/
tree.
--leading=string default: "PDF" for PDF::Builder. This is the OPTIONAL top
module (and directory) name. It will be omitted (= '') if there is
only one name of interest for some package, or it is the top part
of a multipart name (e.g., PDF for PDF::Builder). For example, there
are several PDF:: products and --rootname is used to distinguish
among them. If a package name includes three or more parts (A::B::C,
etc.), give --leading either in the form of Perl style (A::B) or as
directories (A/B, in this case).
Note that "leading" is pronounced "leeding", as in "up front". Do not
confuse it with typographic leading, pronounced "ledding", which is
the space between text baselines.
--rootname=string default: "Builder" for PDF::Builder. --rootname must be
given (not an empty string). For example, there are also PDF::API2
and PDF::Report, among others.
--output=string default: "." for PDF::Builder. It is the location of the new
<leading>/ directory, under docs/ in this case (./PDF/) as this
program is typically run under docs/. All HTML files will be in the
<output>/<leading>/ directory, unless leading is empty '', in which
case output is to <output>/<rootname>/.
--toc=string default: "<rootname>_index.html" for most applications. This
is the name of the master index (table of contents) file that will
be written to with links to all modules, in the top level output
directory (e.g., PDF/).
EXAMPLES:
To build PDF::Builder's documentation, in Builder/docs just run
buildDoc.pl --all
All the defaults are set up for building PDF::Builder's documentation from
docs/. '-all' is the default, but no entries at all is interpreted as a
request for help.
To build the documentation directory 'SVG' under docs, from an installation
in Strawberry Perl, with the .pm/.pod files under lib/. Naturally, if you
are building from an installed Perl package, your --libtop would point to
the directory /Strawberry/perl/site/lib/SVG/lib (or wherever):
buildDoc.pl --leading='' --libtop=/Strawberry/perl/site/lib -rootname=SVG
**CAUTION** If there are multiple packages under SVG (e.g., not only ./SVG.pm
and its children under SVG/, but also SVG::Parser and SVG::Reader packages),
buildDoc may become confused and attempt to build all of them under SVG,
resulting in spurious error messages and misorganized .html files (as it
processes everything under SVG/). In this care, it is better to either manually
copy just SVG's .pm and .pod file structure to a temporary directory, or
obtain a temporary copy of just the desired package from a repository such as
CPAN or GitHub. See the following example:
To build package SVG's documentation, from a Desktop directory 'SVG-2.87',
in Builder/docs (also on the Desktop), run
buildDoc.pl --leading='' --libtop=../../SVG-2.87/lib -rootname=SVG
Another example would be HTML::Tree and HTML::TreeBuilder. Note that they are
in 'vendor', not 'site', and comprise a number of distinct modules that must
be handled separately:
buildDoc.pl --leading=HTML --libtop=/Strawberry/perl/vendor/lib -rootname=Tree
buildDoc.pl --leading=HTML --libtop=/Strawberry/perl/vendor/lib -rootname=TreeBuilder
buildDoc.pl --leading=HTML --libtop=/Strawberry/perl/vendor/lib -rootname=Parse
buildDoc.pl --leading=HTML --libtop=/Strawberry/perl/vendor/lib -rootname=Element
buildDoc.pl --leading=HTML --libtop=/Strawberry/perl/vendor/lib -rootname=Tagset
buildDoc.pl --leading=HTML --libtop=/Strawberry/perl/vendor/lib -rootname=AsSubs
If you do not have a standalone spelling checker, to find typos in the
documentation, such as "lintian", you can bring up each HTML page in a browser,
copy and paste into an email client, and ask for a spelling check. This will
occasionally find a bona-fide spelling error that can be corrected.
The .pod or .pm file(s) are fed to Pod::Simple::XHTML utility to produce
.html files stored in the current directory or below (see configuration
section). .html files with any links in them (L<> tag) are fixed up to correct
the href (path) to the referenced HTML files.
If there are both .pod and .pm versions of a given filename, the .pod version
will be preferably used. Presumably it has the documentation in it.
If the resulting .html file has no content, it has a line added to inform anyone
looking at it that there is no documentation for that module (rather than a
blank page).
If all .pod and .pm files are being processed, an attempt will be made to check
that .html target files actually exist (cross reference check). In addition, a
check will be made that some other file links to this one so that there is a
chain of links from the root.
References to other packages via L<> may result in error messages ("does not
appear to exist" or even a Severe Error), and will have to be manually cleaned
up to either eliminate the bogus links (<a>Bad::Package</a>) or point them to
the correct place.
Messages:
<PMname> INFO no link from root for this HTML file
There does not appear to be a chain of links from the root down to this
file. It is still usable and can be accessed explicitly, and possibly via
other non-root paths, but it may be an orphan. You might want to add an
L<> link from another module. All HTML files are still accessible from the
master Table of Contents (docs/index.html). As this is such a common event,
by default the message is suppressed. The --flagorphans flag will show it
during processing.
<filename> INFO no POD content
There was no POD content in the .pod or .pm input file, so there is no
documentation in the file. A grayed-out dummy link will be given in the
master index file.
<filename> INFO not .pod or .pm, ignored
The file found is not a Perl Documentation (.pod) or Module (.pm) file,
so it is ignored. This message is suppressed by the --noignore flag.
<item> WARNING extra command line content ignored
The indicated item was on the command line, but its purpose is not known,
and it has been skipped over. Invalid flags or options get their own
error message: Unknown option: <flag>.
<flag> WARNING unknown flag skipped
A flag (command line item) starting with - or -- was seen, but not
recognized as a valid flag. It is skipped over.
<filename> WARNING top-level .pod or .pm file not readable
One or more of the top level .pod or .pm files (<rootname> .pod or .pm)
was missing or not readable.
<filename> WARNING internal POD errors reported by Pod::Simple::XHTML
At the end of the .html file, problems are listed. You should examine them
and attempt to correct the issue(s). Usually these are formatting issues.
<filename> WARNING is not a directory or file, ignored
This program tried to process a directory entry that wasn't a regular
file or a subdirectory. It is skipped over.
ERROR --rootname must not be empty!
The <rootname> is the top level name of the package being documented,
and cannot be an empty string. It must be a name.
<filename> ERROR no <rootname> .pod or .pm files found
The specified file(s) were not found.
<filename> ERROR POD errors reported by Pod::Simple::XHTML
One or more error messages were written to STDERR. You should examine them
and attempt to correct the issue(s).
<PMname> ERROR does not appear to exist, called from <sourcefile>
You have a L<> link to a target .html file that does not appear to exist.
<filename> ERROR <rootname> .pod or .pm file not readable
The input file could not be read, the output file could not be created or
written, the output directory could not be created, etc. Check for
filesystem (disk) full, and incorrectly set permissions.
<PMname> ERROR still has status <n> at <TOCfile> output!
A .pod or .pm file got through the process and to the point of output to
the TOC (index.html) file still having a status of -2 or -1, when it
should be 0 or higher by this point.
<TOC index file> ERROR unable to open output index file
There was an error trying to open the output <TOC>.html to write out the
master index page.
<filename> ERROR can't open file for output
Can't open the file to write it out. This is usually seen with an .html
file to be written back out after modifications. Check permissions.
<filename> ERROR can't open file for input
Can't open the file to read it in. This is usually seen with an .html file
to be read in for modifications. Check permissions.
<dirname> ERROR can't open and read directory
While exploring the file tree, the program was unable to open a directory
in order to read its contents (files and subdirectories). Check
permissions.
<dirname/direntry> ERROR unreadable file
While exploring the file tree, the program found a file that it wants to
read, but is unable to do so. Check permissions.
END_OF_TEXT
print
$message
;
return
;
}
sub
empty {
my
$content
=
<<"END_OF_TEXT";
<?xml version="1.0" ?>
<head>
<title></title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rev="made" href="mailto:">
</head>
<body>
</body>
</html>
END_OF_TEXT
return
$content
;
}