From: Jan T. <de...@us...> - 2002-02-05 00:30:40
|
Update of /cvsroot/net-script/netscript2/src/tools/IPdoc In directory usw-pr-cvs1:/tmp/cvs-serv3695 Modified Files: IPdoc.pm Added Files: Class.pm NSDoclet.pm Sub.pm wipeout.project Log Message: * nearly finished IPdoc 1.0 --- NEW FILE: Class.pm --- #-------------------------------------------------------- # This class represents IPdoc, the insOMnia Perl documenting # system. # $Id: Class.pm,v 1.1 2002/02/05 00:30:37 derkork Exp $ # # DOM2 and all related materials, such as documentation, # are protected under the terms and conditions of the Artistic License. # (C) 2000-2001 by Jan Thomä, insOMnia # mailto: ko...@in... #-------------------------------------------------------- package IPdoc::Class; use vars qw($VERSION); use strict; #-------------------------------------------------------- # Globals #-------------------------------------------------------- $VERSION = '1.0'; #/** # Represents a class # @public #*/ sub new { my ($proto) = shift; my $class = ref( $proto ) || $proto;# get the Classname # Create a Class using the Hash-As-An-Object-Idiom my $this = {}; bless( $this, $class ); # create Object my @subs = (); my @params = (); my @paramValues = (); $this -> { m_subs } = \@subs; $this -> { m_params } = \@params; $this -> { m_paramValues } = \@paramValues; $this; } #/** # Sets/returns a comment for this class # @optional a comment for this class # @return a comment for this class #*/ sub comment { my ($this, $comment) = @_; if (defined($comment)) { $this -> { m_comment } = $comment; } $this -> { m_comment }; } #/** # Returns a hash reference containing all params set for this class. # Mapping is names => list reference containing the names, and # values => list reference containing the values. # @return all params for this class. #*/ sub params { my ($this) = @_; my @params = @{$this -> { m_params } }; my @values = @{$this -> { m_paramValues } }; return { names => \@params, values => \@values }; } #/** # Adds a new param to this class. # @param the name of the parameter # @param the value of the parameter #*/ sub newParam { my ($this, $name, $value) = @_; push( @{$this->{m_params}},$name); push( @{$this->{m_paramValues}},$value); } #/** # Sets/returns the name of the class # @optional the name of the class # @return the name of the class #*/ sub name { my ($this, $name) = @_; if ( defined($name) ) { $this -> { m_name } = $name; } $this -> { m_name }; } #/** # Sets/returns the filename where this class documentation is stored in # @optional the filename where the class documentation is stored in # @return the filename where the class documentation is stored in #*/ sub filename { my ($this, $filename ) = @_; if (defined($filename)) { $this -> { m_filename } = $filename; # change the filename to be a relative one my $relativeName = $filename; $relativeName =~ s/\.pm$/\.html/; $relativeName =~ s/\/[^\/]+\//\/..\//g; $relativeName =~ s/^\///; $this -> { m_relativeName } = $relativeName; } $this -> { m_filename }; } #/** # Returns the relative filename where this class documentation is stored # in. # @return the relative filename #*/ sub relativeFileName { my ($this) = @_; $this -> { m_relativeName }; } #/** # Sets/returns the parent class object. This is undef, if the parent class # is UNIVERSAL. # @optional the parent class object # @returns the parent class object #*/ sub parent { my ($this, $parent) = @_; if (defined($parent)) { $this -> { m_parent } = $parent; } $this -> { m_parent }; } #/** # Returns all subs this class has. # @return a list reference holding all sub objects of this class #*/ sub subs { my ($this) = @_; $this -> { m_subs }; } #/** # Adds a sub object to this class. # @param a sub object reference #*/ sub newSub { my ($this, $sub) = @_; push ( @{$this -> { m_subs }}, $sub ); $sub -> parent($this); } --- NEW FILE: NSDoclet.pm --- #-------------------------------------------------------- # This class is a basic doclet for IPDoc. # # $Id: NSDoclet.pm,v 1.1 2002/02/05 00:30:37 derkork Exp $ # # DOM2 and all related materials, such as documentation, # are protected under the terms and conditions of the Artistic License. # (C) 2000-2001 by Jan Thomä, insOMnia # mailto: ko...@in... #-------------------------------------------------------- package IPdoc::NSDoclet; use vars qw($VERSION); #-------------------------------------------------------- # Globals #-------------------------------------------------------- $VERSION = '1.0'; #/** # Creates a new IPdoc parser, # @param ipdoc version # @public #*/ sub new { my ($proto) = shift; my $class = ref( $proto ) || $proto;# get the Classname # Create a Class using the Hash-As-An-Object-Idiom my $this = {}; bless( $this, $class ); # create Object $this -> { m_ipdoc_version } = shift; $this; } #/** # Renders the head. # @param title # @return the rendered head # @public #*/ sub renderHead { my ($this, $title) = @_; "<html><head><title>$title</title></head><body>"; } #/** # Renders the foot. # @return the rendered foot #*/ sub renderFoot { my ($this) = @_; "<hr><small>Created by IPDoc v".$this -> { m_ipdoc_version }. " using the NSDoclet doclet.</small></body></html>"; } #/** # Renders a class. # @param the class object to render # @return the rendered string # @public #*/ sub renderClass { my ($this, $class) = @_; my $classname = $class -> name(); my $result = ""; # render a class hierarchy tree my @classlist = (); my $parent = $class -> parent();; while (defined($parent)) { unshift(@classlist, $parent); $parent = $parent -> parent(); } push (@classlist, $class); $result .= "<pre>+- UNIVERSAL\n"; my $indent = 0; while (@classlist) { $parent = shift @classlist; $result .= " " x $indent; $result .="|___+- "; $result .="<a href=\"".$parent -> relativeFileName()."\">" if $parent -> relativeFileName(); $result .= $parent -> name(); $result .= "</a>" if $parent -> relativeFileName(); $result .= "\n"; $indent += 4; } $result .= "</pre>"; #render the class definition. $parent = $class -> parent(); my $parentName = "UNIVERSAL"; if (defined($parent)) { $parentName = $parent -> name(); } $result .= "<h1>Class $classname</h1><small>extends $parentName</small><br><br>"; $result .= $class -> comment() ."<br><br>"; $result .= "<br><br>". $this -> renderParams($class -> params()); $result .= "<hr>"; #render a method table $result .= "<table width=\"100%\" border=\"1\"><tr><th>Subs</th></tr>"; for ( @{$class -> subs()} ) { my $subName = $_ -> name(); my $subComment = $_ -> comment(); # cut comment down to the first line or sentence. $subComment =~ /^([^\.]+)/; $result .= "<tr><td><a href=\"#sub_$subName\"><b>$subName</b></a><br>$1...</td></tr>"; } $result .= "</table>"; $result; } #/** # Renders all subs of the given class object. # @param a class object # @return the rendered subs # @public #*/ sub renderSubs { my ($this, $class) = @_; my $result = ""; for (@{$class -> subs()}) { $result .= $this -> renderSub( $_ ); } $result; } #/** # Renders a sub. # @param the sub object to render # @return the rendered string # @private #*/ sub renderSub { my ($this, $sub ) = @_; my $name = $sub -> name(); my $description = $sub -> comment(); my $result = "<hr><h3><a name=\"sub_$name\">$name</a></h3>$description<br><br>"; $result .= $this -> renderParams( $sub -> params()); $result; } #/** # Renders parameters. # @param a hash reference holding the parameter hash from a sub or class object. # @return the rendered parameters # @private #*/ sub renderParams { my ($this, $paramRef) = @_; my $result = ""; my %mappings = ( "param" => "parameter:", "optional" => "optional parameter:", "not-implemented" => "This feature is not yet implemented.", "not-standard" => "This implementation is non-standard.", "return" => "return value:", "public" => "This sub can be used from outside.", "private" => "This sub should not be used from outside.", "abstract" => "This implementation is abstract.", "note" => "Implementation note:", "fixme" => "To be fixed:", "author" => "Author:", "version" => "Version:" ); my @paramNames = @{$paramRef -> { names }}; my @paramValues = @{$paramRef -> { values }}; while (@paramNames) { $result .= "<b>".$mappings{(shift @paramNames)}."</b>".(shift @paramValues)."<br>"; } $result; } --- NEW FILE: Sub.pm --- #-------------------------------------------------------- # This class represents IPdoc, the insOMnia Perl documenting # system. # $Id: Sub.pm,v 1.1 2002/02/05 00:30:37 derkork Exp $ # # DOM2 and all related materials, such as documentation, # are protected under the terms and conditions of the Artistic License. # (C) 2000-2001 by Jan Thomä, insOMnia # mailto: ko...@in... #-------------------------------------------------------- package IPdoc::Sub; use vars qw($VERSION); use strict; #-------------------------------------------------------- # Globals #-------------------------------------------------------- $VERSION = '1.0'; #/** # Represents a class # @public #*/ sub new { my ($proto) = shift; my $class = ref( $proto ) || $proto;# get the Classname # Create a Class using the Hash-As-An-Object-Idiom my $this = {}; bless( $this, $class ); # create Object my @subs = (); my @params = (); my @paramValues = (); $this -> { m_params } = \@params; $this -> { m_paramValues } = \@paramValues; $this; } #/** # Sets/returns a comment for this sub # @optional a comment for this sub # @return a comment for this sub #*/ sub comment { my ($this, $comment) = @_; if (defined($comment)) { $this -> { m_comment } = $comment; } $this -> { m_comment }; } #/** # Returns a hash reference containing all params set for this sub. # Mapping is names => list reference containing the names, and # values => list reference containing the values. # @return all params for this sub. #*/ sub params { my ($this) = @_; my @params = @{$this -> { m_params } }; my @values = @{$this -> { m_paramValues } }; return { names => \@params, values => \@values }; } #/** # Adds a new param to this sub. # @param the name of the parameter # @param the value of the parameter #*/ sub newParam { my ($this, $name, $value) = @_; push( @{$this->{m_params}},$name); push( @{$this->{m_paramValues}},$value); } #/** # Sets/returns the name of the class # @optional the name of the class # @return the name of the class #*/ sub name { my ($this, $name) = @_; if ( defined($name) ) { $this -> { m_name } = $name; } $this -> { m_name }; } #/** # Sets/returns the parent class object. # @optional the parent class object # @returns the parent class object #*/ sub parent { my ($this, $parent) = @_; if (defined($parent)) { $this -> { m_parent } = $parent; } $this -> { m_parent }; } --- NEW FILE: wipeout.project --- b C DmDictionary 0 3dceb 8 c 0 3ddcf 9 C Category 1 881b c 0 3de09 4 C DmString 2 3de10 2 e3 c 2 3de0f a defaultExe C DmSet 3 3de12 1 c 2 882a 2 e3 L 882a c 2 3de11 b executables c 3 3de0d 3 c 2 8831 3 *.C L 8831 c 2 8834 4 *.cc L 8834 c 2 8837 5 *.cpp L 8837 c 2 3de0c a extensions c 2 3de0b a CPP_source c 2 3de0a 4 name c 2 3ddd1 a CPP_source c 1 884c c 0 3de4f 4 c 2 3de56 2 e3 c 2 3de55 a defaultExe c 3 3de58 1 c 2 8859 2 e3 L 8859 c 2 3de57 b executables c 3 3de53 1 c 2 8860 3 *.c L 8860 c 2 3de52 a extensions c 2 3de51 8 C_source c 2 3de50 4 name c 2 3ddd2 8 C_source c 1 8875 c 0 3de89 4 c 2 3de90 2 e3 c 2 3de8f a defaultExe c 3 3de92 1 c 2 8882 2 e3 L 8882 c 2 3de91 b executables c 3 3de8d 1 c 2 8889 3 *.e L 8889 c 2 3de8c a extensions c 2 3de8b 6 Eiffel c 2 3de8a 4 name c 2 3ddd3 6 Eiffel c 1 889e c 0 3dec3 4 c 2 3deca 2 e3 c 2 3dec9 a defaultExe c 3 3decc 1 c 2 88ab 2 e3 L 88ab c 2 3decb b executables c 3 3dec7 4 c 2 88b2 3 *.F L 88b2 c 2 88b5 3 *.f L 88b5 c 2 88b8 5 *.for L 88b8 c 2 88bb 5 *.fpp L 88bb c 2 3dec6 a extensions c 2 3dec5 7 Fortran c 2 3dec4 4 name c 2 3ddd4 7 Fortran c 1 88d0 c 0 3df09 4 c 2 3df10 2 e3 c 2 3df0f a defaultExe c 3 3df12 1 c 2 88dd 2 e3 L 88dd c 2 3df11 b executables c 3 3df0d 2 c 2 88e4 3 *.H L 88e4 c 2 88e7 3 *.h L 88e7 c 2 3df0c a extensions c 2 3df0b 6 Header c 2 3df0a 4 name c 2 3ddd5 6 Header c 1 88fc c 0 3df47 4 c 2 3df4e 9 surfboard c 2 3df4d a defaultExe c 3 3df50 2 c 2 8909 2 e3 L 8909 c 2 890c 9 surfboard L 890c c 2 3df4f b executables c 3 3df4b 2 c 2 8913 5 *.htm L 8913 c 2 8916 6 *.html L 8916 c 2 3df4a a extensions c 2 3df49 4 Html c 2 3df48 4 name c 2 3ddd6 4 Html c 1 892b c 0 3df89 4 c 2 3df90 2 e3 c 2 3df8f a defaultExe c 3 3df92 1 c 2 8938 2 e3 L 8938 c 2 3df91 b executables c 3 3df8d 1 c 2 893f 6 *.java L 893f c 2 3df8c a extensions c 2 3df8b 4 Java c 2 3df8a 4 name c 2 3ddd7 4 Java c 1 8954 c 0 3dfc3 4 c 2 3dfca 2 e3 c 2 3dfc9 a defaultExe c 3 3dfcc 1 c 2 8961 2 e3 L 8961 c 2 3dfcb b executables c 3 3dfc7 1 c 2 8968 5 *.tex L 8968 c 2 3dfc6 a extensions c 2 3dfc5 5 Latex c 2 3dfc4 4 name c 2 3ddd8 5 Latex c 1 897d c 0 3dffd 4 c 2 3e004 2 e3 c 2 3e003 a defaultExe c 3 3e006 1 c 2 898a 2 e3 L 898a c 2 3e005 b executables c 3 3e001 0 c 2 3e000 a extensions c 2 3dfff 5 Other c 2 3dffe 4 name c 2 3ddd9 5 Other c 2 3ddce a categories c 0 3dddb 1 C ProjectDir 4 89a7 c 2 89a8 1b netscript2/src/tools/IPdoc/ 11 81 c 2 89a9 0 0 c 2 3dddd 1b netscript2/src/tools/IPdoc/ c 2 3ddda b directories C DmBag 5 3dcf7 4 c 2 3dd2d da b C DmDictionary 0 3dcf9 3 C DmString 1 3dd0b 39 b C DmSet 0 3b497 1 C DmString 1 3b601 5 Other L 3b601 c 1 3dd0a a categories c 1 3dcfb 8 Class.pm c 1 3dcfa 4 name C DmInteger 2 3dd0d 1 c 1 3dd0c 9 substMode c 2 3dd62 d7 b C DmDictionary 0 3dd2e 3 C DmString 1 3dd40 36 b C DmSet 0 89dd 1 C DmString 1 8a0b 5 Other L 8a0b c 1 3dd3f a categories c 1 3dd30 8 IPdoc.pm c 1 3dd2f 4 name C DmInteger 2 3dd42 1 c 1 3dd41 9 substMode c 2 3dd97 dd b C DmDictionary 0 3dd63 3 C DmString 1 3dd75 39 b C DmSet 0 3bcc2 1 C DmString 1 3be2c 5 Other L 3be2c c 1 3dd74 a categories c 1 3dd65 b NSDoclet.pm c 1 3dd64 4 name C DmInteger 2 3dd77 1 c 1 3dd76 9 substMode c 2 3ddcc d8 b C DmDictionary 0 3dd98 3 C DmString 1 3ddaa 39 b C DmSet 0 3db76 1 C DmString 1 3dce0 5 Other L 3dce0 c 1 3dda9 a categories c 1 3dd9a 6 Sub.pm c 1 3dd99 4 name C DmInteger 2 3ddac 1 c 1 3ddab 9 substMode c 2 3ddcd 5 files c 2 3dcf3 94 xterm -ls -fn -*-lucidatypewriter-medium-r-normal-*-12-* -bg gray90 -T Program -geometry 80x10+0+0 -e "[set command with 'Project->Launch Command']" c 2 3dcf2 6 launch c 2 3dcef 4 make c 2 3dcee 4 make c 2 3dcf1 0 c 2 3dcf0 8 makeFile c 5 3dcf4 0 c 2 3dcf6 7 modules c 2 3dced 5 IPdoc c 2 3dcec 4 name Index: IPdoc.pm =================================================================== RCS file: /cvsroot/net-script/netscript2/src/tools/IPdoc/IPdoc.pm,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** IPdoc.pm 2002/01/26 14:06:27 1.1.1.1 --- IPdoc.pm 2002/02/05 00:30:37 1.2 *************** *** 12,17 **** package IPdoc::IPdoc; use vars qw($VERSION); ! use XML::Parser; #-------------------------------------------------------- --- 12,21 ---- package IPdoc::IPdoc; use vars qw($VERSION); + use IPdoc::NSDoclet; + use IPdoc::Class; + use IPdoc::Sub; ! use Carp; ! use strict; #-------------------------------------------------------- *************** *** 20,24 **** --- 24,259 ---- $VERSION = '1.0'; + #/** + # Creates a new IPdoc parser, + # @public + #*/ + sub new { + my ($proto) = shift; + my $class = ref( $proto ) || $proto;# get the Classname + + # Create a Class using the Hash-As-An-Object-Idiom + my $this = {}; + bless( $this, $class ); # create Object + my @fileList = (); + my @baseDirs = (); + $this -> { m_doclet } = "IPdoc::NSDoclet"; + $this -> { m_destDir } = ""; + $this -> { m_fileList } = \@fileList; + $this -> { m_baseDirs } = \@baseDirs; + $this; + } + #/** + # Reads the given config file and then parses all given files and + # directories, creating documentation. + # @param a hash reference containing the following key-value-pairs: + # files - a comma separated list of files and/or directories + # which should be documented + # destination - the destination directory into which the + # documentation should be placed + # @public + #*/ + sub start { + my ($this, $paramRef) = @_; + $this -> { m_destDir } = $paramRef -> { "destination" }; + my @fileList = split(/,/, $paramRef -> {"files"}); + for (@fileList) { + $this -> loadFiles($_); + } + my %classes = (); + while (@{$this -> { m_fileList }}) { + my $fileName = shift @{$this -> {m_fileList}}; + my $baseDir = shift @{$this -> {m_baseDirs}}; + my $class = $this -> processFile( $fileName, $baseDir ); + $classes{$class->name()} = $class; + } + + # now create a hierarchy + for ( values(%classes)) { + my $class = $_; + my $parentName = $class -> parent(); + if (defined($parentName)) { + my $parentClass = $classes{$parentName}; + if (defined($parentClass)) { + $class -> parent($parentClass); + } + else { + # class has a parent, but we didn't scan it so we + # create a dummy parent + $parentClass = IPdoc::Class -> new(); + $parentClass -> name($parentName); + $class -> parent($parentClass); + } + } + } + # now we can render the classes to the destination directory + for ( values(%classes) ) { + $this -> renderClass( $_ ) ; + } + } + + #/** + # Parses the given file list and fills the internal list of files + # with all files which should be documented. + # @param a comma separated list of files + # @private + #*/ + sub loadFiles { + my ($this, $file) = @_; + my $baseDir = ""; + my @fileList = (); + if ( -d $file ) { + $baseDir = $file; + $baseDir .= "/" unless $file =~ /\/$/; + push (@fileList, ""); + } + else { + $file =~ /(.*\/)([^\/])$/; + $baseDir = $1; + push(@fileList, $2); + } + + + for ( @fileList ) { + if ( -d "$baseDir/$_" ) { + my $dirname = $_; + opendir( DIR, "$baseDir/$dirname" ) or carp "Cannot open directory: $baseDir/$dirname. Skipping...\n"; + while( defined(my $file = readdir(DIR)) ) { + if ($file =~ /pm$/ && -f "$baseDir/$dirname/$file") { + push ( @{$this -> { m_fileList } }, "$dirname/$file" ); + push ( @{$this -> { m_baseDirs}}, $baseDir); + } + if (-d "$baseDir/$dirname/$file" && $file ne "." && $file ne "..") { + push(@fileList, "$dirname/$file"); + } + } + closedir( DIR ); + } + else { + if ( $_ =~ /pm$/ && -f "$baseDir/$_") { + push ( @{$this -> { m_fileList}}, $_); + push ( @{$this -> { m_baseDirs}}, $_); + } + else { + carp "The file $_ is not a perl file. Skipping...\n"; + } + } + } + } + + #/** + # This processes the given file and creates documentation for it. + # @param the filename of the file to process + # @param the base dir of the file to process + # @return a class object representing the file + #*/ + sub processFile { + my ($this, $filename, $baseDir) = @_; + my $classname = ""; + my $comment = ""; + my $lastComment = ""; + my $commentRunning = 0; + + my $class = IPdoc::Class -> new(); + $class -> filename($filename); + + open( AFILE, "<$baseDir/$filename" ); + while (<AFILE>) { + my $line = $_; + if ( $line =~ /[^#]*package[\s]*([^;]+);/ && $class -> name() eq "" && !$commentRunning) { + $class -> name($1); + # find parameters in comment + while ( $lastComment =~ /@[a-z]+/ ) { + $lastComment =~ s/@([a-z_A-Z-]+)([^@]*)//; + $class -> newParam($1, $2); + } + $class -> comment($lastComment); + } + + if ($line =~ /use[ ]+base[ ]+qw\(([^\)]+)\)/ && ! $commentRunning ) { + $class -> parent($1); + } + + if ($line =~ /#\/\*\*/) { + if ($commentRunning) { + carp "Error in $filename (line $.). Looks like you forgot to close a comment. Skipping..."; + return; + } + $commentRunning = 1; + } + + if ($commentRunning) { + $comment .= $line; + } + + if ($line =~ /#\*\// ) { + $commentRunning = 0; + $lastComment = $comment; + $lastComment =~ s/#\/\*\*//g; + $lastComment =~ s/#\*\///g; + $lastComment =~ s/#//g; + $comment = ""; + } + + if ($line =~ /^[ ]*sub[ ]+([a-zA-Z0-9_]+)/ && ! $commentRunning) { + my $sub = IPdoc::Sub -> new(); + $sub -> name($1); + # find parameters in comment + while ( $lastComment =~ /@[a-z]+/ ) { + $lastComment =~ s/@([a-z_A-Z-]+)([^@]*)//; + $sub -> newParam($1, $2); + } + $sub -> comment($lastComment); + $class -> newSub($sub); + } + } + close (AFILE); + return $class; + } + + #/** + # Renders a class to a file using a doclet. + # @param the class object to render + #*/ + sub renderClass { + my ($this, $class) = @_; + + #first of all we need to create the directory + my $dir = $this -> { m_destDir } . "/"; + $class -> filename() =~ /(.*\/)([^\/]+)/; + $dir .= $1; + my $filename = $2; + $this -> mkdirs($dir); + + $filename =~ s/\.pm$/\.html/; + + my $doclet = $this -> { m_doclet } -> new($VERSION); + + open( AFILE, ">$dir/$filename" ); + print AFILE $doclet -> renderHead( $class -> name() . " Documentation" ); + print AFILE $doclet -> renderClass( $class ); + print AFILE $doclet -> renderSubs( $class ); + print AFILE $doclet -> renderFoot(); + close(AFILE); + } + + #/** + # Convenience function. Creates all subdirectories. + #*/ + sub mkdirs { + my ($this, $dir) = @_; + + my @dirs = split(/\//, $dir); + + my $currentDir = $dir =~ /^\// ? "/" : ""; + + for (@dirs) { + $currentDir .= $_; + if ( ! -e $currentDir ) { + mkdir "$currentDir";# | croak "Cannot create directory $currentDir ($!)"; + } + $currentDir .= "/"; + } + } |