#! /usr/bin/perl -w # # Class name: CPPClass # Synopsis: Holds comments pertaining to a C++ class, as parsed by HeaderDoc # from a C++ header # # Author: Matt Morse (matt@apple.com) # Last Updated: $Date: 2001/03/22 02:27:13 $ # # Copyright (c) 1999 Apple Computer, Inc. All Rights Reserved. # The contents of this file constitute Original Code as defined in and are # subject to the Apple Public Source License Version 1.1 (the "License"). # You may not use this file except in compliance with the License. Please # obtain a copy of the License at http://www.apple.com/publicsource and # read it before using this file. # # This Original Code and all software distributed under the License are # distributed on an TAS ISU basis, WITHOUT WARRANTY OF ANY KIND, EITHER # EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, # INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS # FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the License for # the specific language governing rights and limitations under the # License. # ###################################################################### BEGIN { foreach (qw(Mac::Files)) { $MOD_AVAIL{$_} = eval "use $_; 1"; } } package HeaderDoc::CPPClass; use HeaderDoc::Utilities qw(findRelativePath safeName getAPINameAndDisc convertCharsForFileMaker printArray printHash); use HeaderDoc::APIOwner; @ISA = qw( HeaderDoc::APIOwner ); use strict; use vars qw($VERSION @ISA); $VERSION = '1.20'; ################ Portability ################################### my $isMacOS; my $pathSeparator; if ($^O =~ /MacOS/i) { $pathSeparator = ":"; $isMacOS = 1; } else { $pathSeparator = "/"; $isMacOS = 0; } ################ General Constants ################################### my $debugging = 0; my $tracing = 0; my $outputExtension = ".html"; my $tocFrameName = "toc.html"; my $theTime = time(); my ($sec, $min, $hour, $dom, $moy, $year, @rest); ($sec, $min, $hour, $dom, $moy, $year, @rest) = localtime($theTime); $moy++; $year += 1900; my $dateStamp = "$moy/$dom/$year"; ###################################################################### sub new { my($param) = shift; my($class) = ref($param) || $param; my $self = {}; bless($self, $class); $self->SUPER::_initialize(); $self->_initialize(); print "Created new CPPClass object\n" if ($debugging); return($self); } sub _initialize { my($self) = shift; $self->{HEADEROBJECT} = undef; } sub headerObject { my $self = shift; if (@_) { $self->{HEADEROBJECT} = shift; } return $self->{HEADEROBJECT}; } sub createTOCFile { my $self = shift; my $rootDir = $self->outputDir(); my $outputFileName = "toc.html"; my $outputFile = "$rootDir$pathSeparator$outputFileName"; my $fileString = $self->tocString(); my $filename = $self->name(); open(OUTFILE, ">$outputFile") || die "Can't write $outputFile.\n$!\n"; if ($isMacOS) {MacPerl::SetFileInfo('MSIE', 'TEXT', "$outputFile");}; print OUTFILE "Draft Documentation for $filename\n"; print OUTFILE "\n"; print OUTFILE "\n"; print OUTFILE "\n"; print OUTFILE "\n"; print OUTFILE "
Class:
$filename

\n"; print OUTFILE $fileString; print OUTFILE "\n"; close OUTFILE; } sub tocString { my $self = shift; my $contentFrameName = $self->name(); $contentFrameName =~ s/(.*)\.h/$1/; # for now, always shorten long names since some files may be moved to a Mac for browsing if (1 || $isMacOS) {$contentFrameName = &safeName($contentFrameName);}; $contentFrameName = $contentFrameName . ".html"; my $header = $self->headerObject(); my @funcs = $self->functions(); my @constants = $self->constants(); my @typedefs = $self->typedefs(); my @structs = $self->structs(); my @enums = $self->enums(); my @vars = $self->vars(); my $compositePageName = HeaderDoc::APIOwner->compositePageName(); my $defaultFrameName = HeaderDoc::APIOwner->defaultFrameName(); my $tocString = "

Introduction

\n"; # output list of functions as TOC if (@funcs) { my @publics; my @protecteds; my @privates; $tocString .= "

Member Functions


\n"; foreach my $obj (sort byAccessControl @funcs) { my $access = $obj->accessControl(); if ($access =~ /public/){ push (@publics, $obj); } elsif ($access =~ /protected/){ push (@protecteds, $obj); } elsif ($access =~ /private/){ push (@privates, $obj); } } if (@publics) { $tocString .= "
Public
\n"; foreach my $obj (sort objName @publics) { my $name = $obj->name(); $tocString .= " $name
\n"; } } if (@protecteds) { $tocString .= "
Protected
\n"; foreach my $obj (sort objName @protecteds) { my $name = $obj->name(); $tocString .= " $name
\n"; } } if (@privates) { $tocString .= "
Private
\n"; foreach my $obj (sort objName @privates) { my $name = $obj->name(); $tocString .= " $name
\n"; } } } if (@typedefs) { $tocString .= "

Defined Types

\n"; foreach my $obj (sort objName @typedefs) { my $name = $obj->name(); $tocString .= " $name
\n"; } } if (@structs) { $tocString .= "

Structs

\n"; foreach my $obj (sort objName @structs) { my $name = $obj->name(); $tocString .= " $name
\n"; } } if (@constants) { $tocString .= "

Constants

\n"; foreach my $obj (sort objName @constants) { my $name = $obj->name(); $tocString .= " $name
\n"; } } if (@enums) { $tocString .= "

Enumerations

\n"; foreach my $obj (sort objName @enums) { my $name = $obj->name(); $tocString .= " $name
\n"; } } if (@vars) { my @publics; my @protecteds; my @privates; $tocString .= "

Member Data


\n"; foreach my $obj (sort byAccessControl @vars) { my $access = $obj->accessControl(); if ($access =~ /public/){ push (@publics, $obj); } elsif ($access =~ /protected/){ push (@protecteds, $obj); } elsif ($access =~ /private/){ push (@privates, $obj); } } if (@publics) { $tocString .= "
Public
\n"; foreach my $obj (sort objName @publics) { my $name = $obj->name(); $tocString .= " $name
\n"; } } if (@protecteds) { $tocString .= "
Protected
\n"; foreach my $obj (sort objName @protecteds) { my $name = $obj->name(); $tocString .= " $name
\n"; } } if (@privates) { $tocString .= "
Private
\n"; foreach my $obj (sort objName @privates) { my $name = $obj->name(); $tocString .= " $name
\n"; } } } $tocString .= "

Other Reference


\n"; $tocString .= " Header
\n"; $tocString .= "

[Printable HTML Page]\n"; return $tocString; } sub _getCompositePageString { my $self = shift; my $name = $self->name(); my $compositePageString; my $contentString; my $abstract = $self->abstract(); if (length($abstract)) { $compositePageString .= "

Abstract

\n"; $compositePageString .= $abstract; } my $discussion = $self->discussion(); if (length($discussion)) { $compositePageString .= "

Discussion

\n"; $compositePageString .= $discussion; } if ((length($abstract)) || (length($discussion))) { $compositePageString .= "

"; } $contentString= $self->_getFunctionDetailString(); if (length($contentString)) { $compositePageString .= "

Member Functions

\n"; $compositePageString .= $contentString; } $contentString= $self->_getVarDetailString(); if (length($contentString)) { $compositePageString .= "

Member Data

\n"; $compositePageString .= $contentString; } $contentString= $self->_getConstantDetailString(); if (length($contentString)) { $compositePageString .= "

Constants

\n"; $compositePageString .= $contentString; } $contentString= $self->_getTypedefDetailString(); if (length($contentString)) { $compositePageString .= "

Typedefs

\n"; $compositePageString .= $contentString; } $contentString= $self->_getStructDetailString(); if (length($contentString)) { $compositePageString .= "

Structs

\n"; $compositePageString .= $contentString; } $contentString= $self->_getEnumDetailString(); if (length($contentString)) { $compositePageString .= "

Enumerations

\n"; $compositePageString .= $contentString; } $contentString= $self->_getPDefineDetailString(); if (length($contentString)) { $compositePageString .= "

#defines

\n"; $compositePageString .= $contentString; } return $compositePageString; } # overriding inherited method to add access type on line above declaration sub _getFunctionDetailString { my $self = shift; my @funcObjs = $self->functions(); my $className = $self->name(); my $contentString; my $apiUIDPrefix = HeaderDoc::APIOwner->apiUIDPrefix(); foreach my $obj (sort objName @funcObjs) { my $name = $obj->name(); my $desc = $obj->discussion(); my $abstract = $obj->abstract(); my $declaration = $obj->declarationInHTML(); my $declarationRaw = $obj->declaration(); my $accessControl = $obj->accessControl(); my @params = $obj->taggedParameters(); my $result = $obj->result(); if ($declaration !~ /#define/) { # not sure how to handle apple_refs with macros yet my $paramSignature = $self->getParamSignature($declarationRaw); my $methodType = $self->getMethodType($declarationRaw); $contentString .= "\n"; } $contentString .= "

$name

\n"; if (length($abstract)) { $contentString .= "Abstract: $abstract\n"; } $contentString .= "
$accessControl\n
$declaration
\n"; $contentString .= "

$desc

\n"; my $arrayLength = @params; if ($arrayLength > 0) { my $paramContentString; foreach my $element (@params) { my $pName = $element->name(); my $pDesc = $element->discussion(); if (length ($pName)) { $paramContentString .= "$pName$pDesc\n"; } } if (length ($paramContentString)){ $contentString .= "

Parameters

\n"; $contentString .= "
\n"; $contentString .= "\n"; $contentString .= "\n"; $contentString .= $paramContentString; $contentString .= "
NameDescription
\n
\n"; } } if (length($result)) { $contentString .= "Result: $result\n"; } $contentString .= "
\n"; } return $contentString; } sub _getVarDetailString { my $self = shift; my @varObjs = $self->vars(); my $contentString; foreach my $obj (sort objName @varObjs) { my $name = $obj->name(); my $desc = $obj->discussion(); my $declaration = $obj->declarationInHTML(); my $accessControl = $obj->accessControl(); my @fields = (); my $fieldHeading; if ($obj->can('fields')) { # for Structs and Typedefs @fields = $obj->fields(); $fieldHeading = "Fields"; } elsif ($obj->can('constants')) { # for enums @fields = $obj->constants(); $fieldHeading = "Constants"; } if ($obj->can('isFunctionPointer')) { if ($obj->isFunctionPointer()) { $fieldHeading = "Parameters"; } } $contentString .= "

$name

\n"; $contentString .= "
$accessControl$declaration
\n"; $contentString .= "

$desc

\n"; my $arrayLength = @fields; if ($arrayLength > 0) { $contentString .= "

$fieldHeading

\n"; $contentString .= "
\n"; $contentString .= "\n"; $contentString .= "\n"; foreach my $element (@fields) { my $fName = $element->name(); my $fDesc = $element->discussion(); $contentString .= "\n"; } $contentString .= "
NameDescription
$fName$fDesc
\n
\n"; } $contentString .= "
\n"; } return $contentString; } sub getParamSignature { my $self = shift; my $declaration = shift; my $sig; my @params; $declaration =~ s/^[^(]+\(([^)]*)\).*/$1/; @params = split (/,/, $declaration); foreach my $paramString (@params) { my @paramElements = split (/\s+/, $paramString); my $lastElement = pop @paramElements; $sig .= join ("", @paramElements); if ($lastElement =~ /^\*.*/) {$sig .= "*";}; #if the arg was a pointer } return $sig; } sub getMethodType { my $self = shift; my $declaration = shift; my $methodType = "instm"; if ($declaration =~ /^\s*static/) { $methodType = "clm"; } return $methodType; } sub docNavigatorComment { my $self = shift; my $name = $self->name(); return "<-- headerDoc=CPPClass; name=$name-->"; } ################## Misc Functions ################################### sub objName { # used for sorting my $obj1 = $a; my $obj2 = $b; return ($obj1->name() cmp $obj2->name()); } sub byLinkage { # used for sorting my $obj1 = $a; my $obj2 = $b; return ($obj1->linkageState() cmp $obj2->linkageState()); } sub byAccessControl { # used for sorting my $obj1 = $a; my $obj2 = $b; return ($obj1->accessControl() cmp $obj2->accessControl()); } sub linkageAndObjName { # used for sorting my $obj1 = $a; my $obj2 = $b; my $linkAndName1 = $obj1->linkageState() . $obj1->name(); my $linkAndName2 = $obj2->linkageState() . $obj2->name(); return ($linkAndName1 cmp $linkAndName2); } ##################### Debugging #################################### sub printObject { my $self = shift; print "CPPClass\n"; $self->SUPER::printObject(); print "headerObject: $self->{HEADEROBJECT}\n"; print "\n"; } 1;