#! /usr/bin/perl #t: make a Documentation of Functions, Methods and Objects. #t: Read Section VI for detailed information # those vars can be given by the commandline use warnings; use strict; my $verbose = ("@ARGV" =~ /\-v/) ? 1 : 0; #: verbose mode if ("@ARGV" =~ /\-v/) my @F = getFiles( @ARGV ); #: (mixed) list of Files or Dirs, default: local dir (/.) my $fHTML = 'DocTool.html'; # HTML-File to create my $isa = ''; # is set to '' in the package detet. section my $tp = '^ top'; # goto Top tag my $pack = "\n\n

\n". "V  The Detailed Packages and Programs\n"; my $li = ''; # line ident my $top = ' add. Perl Documentary Tool (an idea of C.A. Schreiber) Sections in this Web-page:
    I  Programs
    II  Package-Overview
    III  Packages with their Subs
    IV  All Subs with their Descriptions
    V  The Detailed Packages and Programs
    VI  How to Use this Program: DocTool.pl
'."

\n\n\n"; # my %CT = (); # the content is put here for later: foreach (sort keys %CT) # 1st Part: only if it is a Program-File (.pl) and not a Packege-File (.pm) my $prgTop = ''; # 2st Part: only Packages + description (sorted); kind of content my $contSort = "

\n\n \n$tp
\nII  Package-Overview (with Descriptions)\n"; # start with '.' # 3nd Part: (sorted) Packages with their (sorted) subs my $pacSort = "

\n\n\n$tp
\nIII  Packages with their Subs\n

\n$tp
\nIV  All Subs with Descriptions\n"; # 5th Part: (sorted) Packages with their (sorted) subs and their req. or opt. Variables and what they return my @ret = (); my $totalNoPack = 0; # 6th Part: Help (How to read this page) #$helpHelp = &help(); foreach my $fPL (@F) { # Perl-File print "\n\n#############\n#############\n\n\t<=\t$fPL\n" if $verbose; my $PerlProgramTop = ($fPL =~ /\.pl$|\.cgi$/) ? 1 : 0; my $_prgTop = "
$fPL (File)\n\n\t\n"; } $PerlProgramTop = 0; # not anymore top of prg. my $color = (exists $expSubs{$1}) ? '"red"' : '"blue"'; unless ($NoPack) { push @tmp, "$pack
      \n" if ($PerlProgramTop); my $is_prgTopText = 0; # for DocTool Text at the begin of the pl-file #read Perl-File open F, "< $fPL" or die "Can'T open to read $fPL: $!\n\n"; my @L = ; close(F); next if ("@L" =~ /NoDocTool/ && $fPL !~ /DocTool\.pl/); # not fast but save my $LC = 0; # Line Counter my $isPOD = 0; # to skip the lines between =pod .. =cut my %expSubs = (); # exported subs to def. color my @tmp = (); # to be pushed into @ret after the file my $isDocTool = 0; # is this firle setup for DocTool? my $NoPack = 0; my $sub = 0; my $StopDocTool = 0; my $packName = $fPL; # is replaced in the package-section, used if a script with subs, but no packages!! for my $l (@L) { # go through all lines $LC++; if ($l =~ /#.+?StopDocTool/ && $l !~ /\s*last\sif\s\(/) { # 2. question: to make it self-analysable $StopDocTool = 1; # must be menat to be documtented last; } # not to read nromal comment ines but those if spec. varibles are meant for DocTool.pl # but not used in that way but by Perls sys.-Vars: @_ or $_[0].. next if ($l =~ /\s*#\s/ && $l !~ /#\s(my|our)\s+.+?#:/); $isPOD = 1 if ($l =~ /^=pod$/); $isPOD = 0 if ($l =~ /^=cut$/ && $isPOD); next if ($isPOD); # detect different tags for the documentation: # Commentaries => print this line if ($l =~ /#t\:\s*(\S.+?)\s*$/) { # just print this line print "#t\t$1\n" if $verbose; my $t = $1; if ($PerlProgramTop) { if ( $is_prgTopText == 0 ) { $_prgTop .= "\t\t $t \n"; $is_prgTopText = 1; } else { $_prgTop .= "\t\t $t \n"; } } else { push @tmp, "$isa
$t$li"; } $isa = ''; $isDocTool = 1; next; } if ($l =~ /\@EXPORT[\s\=\(]+(.+)\);/) { my $s = $1; $s =~ s/\'//g; push @tmp, "
exported subs: $s$li
\n"; %expSubs = map { $_ => 1 } split /\,\s*/, $s; } # is A: @ISA = qw(AI); if ($l =~ /\@ISA[\s\=qw]+\((.+?)\)/) { # isa link # $me->{'eD'} = DBar::new($me->{'SYM'}, $me->{'toSave'}, $max); #HasA: text my $v = "Is a:   $1",; print $l ,"\t\t1:$1; v:$v;\n" if $verbose; if ($v !~ /Exporter/i) { push @tmp, "
$v$li"; $isa = "
 
\n"; } next; } # Returns if ($l =~ /\#\#\:\s*([A-Za-z\$\%\&\(\'\-].+)/) { # return value print $l if $verbose; push @tmp, " returns:   $1 $li"; $isDocTool = 1; next; } # Has another Object if ($l =~ /[\smy]+([\$\@\%\&\'\-].+?)[\s\=].*?\s([A-Za-z\_]+)\:\:.+?\s*\#\:\s*(\S.+)\s/) { # Has an Object # incl our: if ($l =~ /[mo][uyr\s]+([\$\@\%\&\'\-].+?)[\s\=].*?\s([A-Za-z\_]+)\:\:.+?\#\:\s*(\S.+)\s/) { # Has an Object my ($v,$o,$t) = (sprintf("%-16s",$1) ,sprintf("has a: %s",$2,$2),$3); print $l ,"\t1:$1; 2:$2; 3:$3; v:$v; o:$o\n" if $verbose; $t = (($t=~/^[A-Z]/) ? "$t" : $t); push @tmp, "
  • $v$o: $t
  • $li"; next; } # SUBS if ($l =~ /^\s*sub\s+(\w.+?)\s*\{\s*\#\:\s*(\S.+)/) { # sub new { #: create new Stat analysing tool print "sub\t$1\n\t$2\n\t$packName\t*\t$1\n" if $verbose; if ( $is_prgTopText == 1 ) { $is_prgTopText = 0; $_prgTop .= "
    $tp\n
    $fPL
    "; $NoPack--; } if ($sub) { $li = "\n "; push @tmp, "

  • $li
    $1 (l:$LC) $2
      $li"; } else { push @tmp, "$isa
      • $1 (l:$LC) $2
          $li"; $sub = 1; $isa = ''; } $CT{":$packName*$1"} = "
        1. $1 $2
        2. \n" if ($NoPack>0); $CT{";$1*$packName"} = "   $1 $packName (File) $2\n";# if ($NoPack>0); $isDocTool = 1; next; } # Variables if ($l =~ /(our\s+|my\s+)([\$\@\%\&\'\-].+?)[\s\=]+.+?\#\:\s*(\S.+?)\s*$/) { # variables # $me->{'INF'} = (@_) ? shift : '-/-'; #: Inf. to take and to print print $l ,"\t\t1:$2; 2:$3\n" if $verbose; my ($v,$t) = ($2,$3); if ($PerlProgramTop) { if ( $is_prgTopText ) { $is_prgTopText = 0; $_prgTop .= "\t\n"; } $_prgTop .= "\n\n" unless ($_prgTop =~ //); $_prgTop .= "\n\t\t". (($t =~ /^[A-Z]/) ? " $v = $t " : " $v = $t " ) ."$li"; } else { push @tmp, "$isa
        3. ". (($t =~ /^[A-Z]/) ? " $v = $t " : " $v = $t " ) ."
        4. $li"; } $isa = ''; $isDocTool = 1; next; } #PACKAGES if ($l =~ /package\s(.+);.*?\#\:\s*(\S.+)/) { # new package print "pack\t$1\n\t$2\n\t$packName\t-\t$fPL\n" if $verbose; $NoPack++; $totalNoPack++; $PerlProgramTop = 0; # not anymore top of prg. if ( $is_prgTopText ) { $is_prgTopText = 0; $_prgTop .= "\n"; } $sub = 0; # to start new ul for subs my $pN = sprintf("%-6s",$1); $li = "\n "; push @tmp, "$pack$tp\n
          $pN  $2
          "; $packName = $1; $li .= ' '; $CT{".$2"} = "
        5. $1
        6. (File): $2\n"; $CT{":$1"} = "\n
        7. $1 (File) $2
            \n"; $pack = "
        \n
      \n

       
       
      \n\n

      \n"; $isa = ''; next; } } # foreach line of a file #if ($_prgTop) { if ($_prgTop) { #$_prgTop .= "

    \n" if ( $_prgTop =~ /\/); print $_prgTop if $verbose; $prgTop = "\n

    \nI  Programs\n" unless ($prgTop); $prgTop .= "$_prgTop\n\n

    \n" if ($_prgTop =~ /\<\/tr\>/ or $StopDocTool); } push @ret, @tmp if ($isDocTool); } # foreach file my $go = 0; foreach my $i (sort keys %CT) { $i =~ /^(.)/; if ($1 eq ':') { $pacSort .= " \n


  • " if ($go && $CT{$i} =~ /
  • .+?
      /); $pacSort .= $CT{$i}; $go++; } $subSort .= $CT{$i} if ($1 eq ';'); $contSort .= $CT{$i} if ($1 eq '.'); } # write the end of the Parts; #$prgTop .= "\n\n" if ($prgTop); $pacSort .= "
    \n
  • \n\n

    \n"; $subSort .= '
    '; $contSort .= '

    '; # open HTML File to write the html-file open (F, "> $fHTML") or die "\nCan't open to write $fHTML: $!\n\n"; print F $top, $prgTop, (($totalNoPack) ? ($contSort , $pacSort) : ''), $subSort, "

    \n\n\n", @ret, "\n$pack\n", &help(), "\n$tp\n"; close(F); # that's it ###### subs ###### sub getFiles { #: creates a list of Perl-files to go through # my @f = @_; #: list of file- or dir-names if omitted local dir (/.) is read. my @ret; if (@_) { foreach (@_) { push @ret, $_ if (-f $_); push @ret, _rdDir($_) if (-d $_); # '-v' is skipped here: no file, no dir!! } } else { push @ret, _rdDir('.'); } print map { "\t$_\n" } @ret if $verbose; return @ret; ##: Perl-file list } sub _rdDir { #: read all files in $dir that end with .pm, .pl, .cgi. my $dir = shift; #: Dir to read if ( opendir(DIR, $dir) ) { my @d = map { "$dir/$_" } grep { -f "$dir/$_" && /.+\.p[ml]$/ } readdir(DIR); closedir DIR; # print map { "\t$_\n" } @d; return @d; ##: list of file-names or an empty list } else { warn "can't opendir $dir: $!"; return (); } } sub help { #: this is needed, because the examples to use DocTool.pl confuse DocTool.pl if it anayses itself. my $n = 1; return ##: the help-text as html-formated string # StopDocTool "

    \n\n\n\n$tp
    \nVI  How to Use this Program: DocTool.pl\n" ."" ."" ."" ."" ."" ."" ."" ."" ."" ."" ."" ."" ."" ."" ."" ."" ."" ."" .'
      ${\($n++)})Basic Intention The main intentions for this is: to get easily and quick the information needed to (re-)use packages, methods, subs and scripts. Larger projects leed to a lot of modules and methods, and by the time it can become difficult to retain everything in mind that has been programmed. So it might be usefull to have a quick way to get the information about: how is a method called, what variables are required or optional, what would be the default value and what is returned. Beside that it might be nice to look into that method just with one klick. And finally it might be usefull in some cases to find a method not only by knowing its module.

    It is not meant to replace good program-documentation!.
    Due to intention for this program the examples ChatServer.pl and DocTool.pl itself should not be documented as they are! Only the 1st section 'I Scripts' are necessary to (re-)use them. All functions packages and methods are internally used and there is no need to document them. If you want to follow this idea, just eliminate the tags of DocTool.pl, but on the other hand you can use this tool as a sturtup for your program documentation.
      ${\($n++)})Red and Blue Method Names Methods are presented in the 5th section as lexically sorted list within the module they are defined. Red method names indicates that the method is exported (see below the package name where you find all exported methods).
    Blue method names indicate that the method is not exported.
      ${\($n++)})Line Numbers After the method - in brackets - you find the line number, where the method start.
    (Maybe this can be replaced by a direct link to that line later on)
      ${\($n++)})Normal and Bold Variable Names Due to the convention of DocTool.pl a capital letter after the tag  #:  indicates required variables. In this case the variable name is printed in bold letters. If the variable is optional its name is printed normally and a default value (if not given) for this variable should be mentioned. The varibales ar presented as ordered list, so that the number indicates the place where the variable put calling this method.
    (By the way, the variable-tag for DocTool.pl is not only '#:' but a my or an our before the valiable.)
      ${\($n++)})Tags of DocTool.pl DocTool.pl uses only 3 + 2 tags:
    #t: Comment to be printed for additional information. Mainly for executable Perl-Scripts to get what they are meant for or what it is doing.
    #: This is used for packages, methods subs and variables. In the same line with either package, sub, my, our you can describe in this line what they are meant for or what it is doing. examples:
  • package Reader; #: detached process to receive the Client's Input
    prints: Reader detached process to receive the Client's Input (see above).
  • sub run { #: runs until the socket of this object brokes, ..
    prints: run (l:78) runs until the socket of this object brokes, .. (s.a.)
  • my \$ID = shift; #: The ID for this module
    prints: \$ID = The ID for this module
  • Capital-letter(s) right after the tag indicates that this variable is required.
  • non capital-letters: a-z.0-9,(,[,{, .. indicates optional values/variables, please use default:0 to explain what happens if omitted.
  • commeted variables
    If you want to use the Perl-Vars \@_ of \$_[0], \$_[1], .. you can comment-out the description (used in s2T in Writer):
    # my \$dur = shift #: Duration in sec. transfrmd into Days hh:mm:ss
    prints: \$dur = Duration in sec. transfrmd into Days hh:mm:ss
  • ##: is used for the returnd value(s):
    return \@l; ##:   list of file-names or an empty list
    prints: returns:   list of file-names or an empty list
    (remark: 'returns' is not needed to write again)
    StopDocTool This is used by DocToll to stop analysing the lines hereafter.
    NoDocTool The file is not analyzed if this is written somewhere in the file.
      ${\($n++)})Hide and/or Show As this is meant for (re-)using packages, methods and so on you can hide all what is not needed to know using the package, method,.. So, here all packages and subs should be hided, but to demonstrate how this works they are prepared to be presented in this web-page. That means that only what has been written to section 'I Programs' should be seen. But of course, you can use it as you like it.
      ${\($n++)})
      ${\($n++)})
      ${\($n++)})
    '; }