#! /usr/bin/perl -w
#
# Class name: APIOwner
# Synopsis: Abstract superclass for Header and CPPClass classes
#
# Author: Matt Morse (matt@apple.com)
# Last Updated: $Date: 2001/06/06 18:02:45 $
#
# 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.
#
######################################################################
package HeaderDoc::APIOwner;
BEGIN {
foreach (qw(Mac::Files)) {
$MOD_AVAIL{$_} = eval "use $_; 1";
}
}
use HeaderDoc::HeaderElement;
use HeaderDoc::DBLookup;
use HeaderDoc::Utilities qw(findRelativePath safeName getAPINameAndDisc convertCharsForFileMaker printArray printHash);
@ISA = qw(HeaderDoc::HeaderElement);
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 $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";
######################################################################
# class variables and accessors
{
my $_copyrightOwner;
my $_defaultFrameName;
my $_compositePageName;
my $_apiUIDPrefix;
sub copyrightOwner {
my $class = shift;
if (@_) {
$_copyrightOwner = shift;
}
return $_copyrightOwner;
}
sub defaultFrameName {
my $class = shift;
if (@_) {
$_defaultFrameName = shift;
}
return $_defaultFrameName;
}
sub compositePageName {
my $class = shift;
if (@_) {
$_compositePageName = shift;
}
return $_compositePageName;
}
sub apiUIDPrefix {
my $class = shift;
if (@_) {
$_apiUIDPrefix = shift;
}
return $_apiUIDPrefix;
}
}
sub new {
my($param) = shift;
my($class) = ref($param) || $param;
my $self = {};
bless($self, $class);
$self->SUPER::_initialize();
$self->_initialize();
return($self);
}
sub _initialize {
my($self) = shift;
$self->{OUTPUTDIR} = undef;
$self->{CONSTANTS} = [];
$self->{FUNCTIONS} = [];
$self->{TYPEDEFS} = [];
$self->{STRUCTS} = [];
$self->{VARS} = [];
$self->{PDEFINES} = [];
$self->{ENUMS} = [];
$self->{CONSTANTSDIR} = undef;
$self->{DATATYPESDIR} = undef;
$self->{STRUCTSDIR} = undef;
$self->{VARSDIR} = undef;
$self->{FUNCTIONSDIR} = undef;
$self->{PDEFINESDIR} = undef;
$self->{ENUMSDIR} = undef;
$self->{EXPORTSDIR} = undef;
$self->{EXPORTINGFORDB} = 0;
}
sub outputDir {
my $self = shift;
if (@_) {
my $rootOutputDir = shift;
if (-e $rootOutputDir) {
if (! -d $rootOutputDir) {
die "Error: $rootOutputDir is not a directory. Exiting.\n\t$!\n";
} elsif (! -w $rootOutputDir) {
die "Error: Output directory $rootOutputDir is not writable. Exiting.\n$!\n";
}
} else {
unless (mkdir ("$rootOutputDir", 0777)) {
die ("Error: Can't create output folder $rootOutputDir.\n$!\n");
}
}
$self->{OUTPUTDIR} = $rootOutputDir;
$self->constantsDir("$rootOutputDir$pathSeparator"."Constants");
$self->datatypesDir("$rootOutputDir$pathSeparator"."DataTypes");
$self->structsDir("$rootOutputDir$pathSeparator"."Structs");
$self->functionsDir("$rootOutputDir$pathSeparator"."Functions");
$self->varsDir("$rootOutputDir$pathSeparator"."Vars");
$self->pDefinesDir("$rootOutputDir$pathSeparator"."PDefines");
$self->enumsDir("$rootOutputDir$pathSeparator"."Enums");
$self->exportsDir("$rootOutputDir$pathSeparator"."Exports");
}
return $self->{OUTPUTDIR};
}
sub exportingForDB {
my $self = shift;
if (@_) {
$self->{EXPORTINGFORDB} = shift;
}
return $self->{EXPORTINGFORDB};
}
sub exportsDir {
my $self = shift;
if (@_) {
$self->{EXPORTSDIR} = shift;
}
return $self->{EXPORTSDIR};
}
sub constantsDir {
my $self = shift;
if (@_) {
$self->{CONSTANTSDIR} = shift;
}
return $self->{CONSTANTSDIR};
}
sub datatypesDir {
my $self = shift;
if (@_) {
$self->{DATATYPESDIR} = shift;
}
return $self->{DATATYPESDIR};
}
sub structsDir {
my $self = shift;
if (@_) {
$self->{STRUCTSDIR} = shift;
}
return $self->{STRUCTSDIR};
}
sub varsDir {
my $self = shift;
if (@_) {
$self->{VARSDIR} = shift;
}
return $self->{VARSDIR};
}
sub pDefinesDir {
my $self = shift;
if (@_) {
$self->{PDEFINESDIR} = shift;
}
return $self->{PDEFINESDIR};
}
sub enumsDir {
my $self = shift;
if (@_) {
$self->{ENUMSDIR} = shift;
}
return $self->{ENUMSDIR};
}
sub functionsDir {
my $self = shift;
if (@_) {
$self->{FUNCTIONSDIR} = shift;
}
return $self->{FUNCTIONSDIR};
}
sub tocString {
my $self = shift;
my $contentFrameName = $self->name();
$contentFrameName =~ s/(.*)\.h/$1/;
$contentFrameName = &safeName($contentFrameName);
$contentFrameName = $contentFrameName . ".html";
my @funcs = $self->functions();
my @constants = $self->constants();
my @typedefs = $self->typedefs();
my @structs = $self->structs();
my @enums = $self->enums();
my @pDefines = $self->pDefines();
my $tocString = "
\n";
# output list of functions as TOC
if (@funcs) {
$tocString .= "Functions
\n";
foreach my $obj (sort objName @funcs) {
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 (@pDefines) {
$tocString .= "#defines
\n";
foreach my $obj (sort objName @pDefines) {
my $name = $obj->name();
$tocString .= " $name
\n";
}
}
return $tocString;
}
sub enums {
my $self = shift;
if (@_) {
@{ $self->{ENUMS} } = @_;
}
return @{ $self->{ENUMS} };
}
sub addToEnums {
my $self = shift;
if (@_) {
foreach my $item (@_) {
push (@{ $self->{ENUMS} }, $item);
}
}
return @{ $self->{ENUMS} };
}
sub pDefines {
my $self = shift;
if (@_) {
@{ $self->{PDEFINES} } = @_;
}
return @{ $self->{PDEFINES} };
}
sub addToPDefines {
my $self = shift;
if (@_) {
foreach my $item (@_) {
push (@{ $self->{PDEFINES} }, $item);
}
}
return @{ $self->{PDEFINES} };
}
sub constants {
my $self = shift;
if (@_) {
@{ $self->{CONSTANTS} } = @_;
}
return @{ $self->{CONSTANTS} };
}
sub addToConstants {
my $self = shift;
if (@_) {
foreach my $item (@_) {
push (@{ $self->{CONSTANTS} }, $item);
}
}
return @{ $self->{CONSTANTS} };
}
sub functions {
my $self = shift;
if (@_) {
@{ $self->{FUNCTIONS} } = @_;
}
return @{ $self->{FUNCTIONS} };
}
sub addToFunctions {
my $self = shift;
if (@_) {
foreach my $item (@_) {
push (@{ $self->{FUNCTIONS} }, $item);
}
}
return @{ $self->{FUNCTIONS} };
}
sub typedefs {
my $self = shift;
if (@_) {
@{ $self->{TYPEDEFS} } = @_;
}
return @{ $self->{TYPEDEFS} };
}
sub addToTypedefs {
my $self = shift;
if (@_) {
foreach my $item (@_) {
push (@{ $self->{TYPEDEFS} }, $item);
}
}
return @{ $self->{TYPEDEFS} };
}
sub structs {
my $self = shift;
if (@_) {
@{ $self->{STRUCTS} } = @_;
}
return @{ $self->{STRUCTS} };
}
sub addToStructs {
my $self = shift;
if (@_) {
foreach my $item (@_) {
push (@{ $self->{STRUCTS} }, $item);
}
}
return @{ $self->{STRUCTS} };
}
sub vars {
my $self = shift;
if (@_) {
@{ $self->{VARS} } = @_;
}
return @{ $self->{VARS} };
}
sub addToVars {
my $self = shift;
if (@_) {
foreach my $item (@_) {
push (@{ $self->{VARS} }, $item);
}
}
return @{ $self->{VARS} };
}
##################################################################
sub createFramesetFile {
my $self = shift;
my $docNavigatorComment = $self->docNavigatorComment();
my $class = ref($self);
my $defaultFrameName = $class->defaultFrameName();
my $filename = $self->name();
my $outDir = $self->outputDir();
my $outputFile = "$outDir$pathSeparator$defaultFrameName";
my $rootFileName = $self->name();
$rootFileName =~ s/(.*)\.h/$1/;
$rootFileName = &safeName($rootFileName);
open(OUTFILE, ">$outputFile") || die "Can't write $outputFile. \n$!\n";
if ($isMacOS) {MacPerl::SetFileInfo('MSIE', 'TEXT', "$outputFile");};
print OUTFILE "Documentation for $filename\n";
print OUTFILE "\n";
print OUTFILE "$docNavigatorComment\n";
close OUTFILE;
}
# Overridden by subclasses to return HTML comment that identifies the
# index file (Header vs. Class, name, etc.)
sub docNavigatorComment {
return "";
}
sub createContentFile {
my $self = shift;
my $class = ref($self);
my $copyrightOwner = $class->copyrightOwner();
my $headerName = $self->name();
my $rootFileName = $headerName;
$rootFileName =~ s/(.*)\.h/$1/;
# for now, always shorten long names since some files may be moved to a Mac for browsing
if (1 || $isMacOS) {$rootFileName = &safeName($rootFileName);};
my $outputFileName = "$rootFileName.html";
my $rootDir = $self->outputDir();
my $outputFile = "$rootDir$pathSeparator$outputFileName";
open (OUTFILE, ">$outputFile") || die "Can't write header-wide content page $outputFile. \n$!\n";
if ($isMacOS) {MacPerl::SetFileInfo('MSIE', 'TEXT', "$outputFile");};
my $headerDiscussion = $self->discussion();
my $headerAbstract = $self->abstract();
if ((length($headerDiscussion)) || (length($headerAbstract))) {
print OUTFILE "API Documentation\n\n";
print OUTFILE "$headerName
\n";
if (length($headerAbstract)) {
print OUTFILE "Abstract: $headerAbstract
\n";
}
print OUTFILE "$headerDiscussion
\n";
} else {
# warn "No header-wide comment found. Creating dummy file for default content page.\n";
print OUTFILE "API Documentation\n\n";
print OUTFILE "Documentation for $headerName
\n";
print OUTFILE "
Use the links in the table of contents to the left to access documentation.
\n";
}
print OUTFILE "
";
print OUTFILE "© $copyrightOwner " if (length($copyrightOwner));
print OUTFILE "(Last Updated $dateStamp)\n";
print OUTFILE "
";
print OUTFILE "HTML documentation generated by HeaderDoc\n";
print OUTFILE "\n";
print OUTFILE "\n\n";
close OUTFILE;
}
sub writeHeaderElements {
my $self = shift;
my $rootOutputDir = $self->outputDir();
my $functionsDir = $self->functionsDir();
my $dataTypesDir = $self->datatypesDir();
my $structsDir = $self->structsDir();
my $constantsDir = $self->constantsDir();
my $varsDir = $self->varsDir();
my $enumsDir = $self->enumsDir();
my $pDefinesDir = $self->pDefinesDir();
if (! -e $rootOutputDir) {
unless (mkdir ("$rootOutputDir", 0777)) {die ("Can't create output folder $rootOutputDir. \n$!");};
}
if ($self->functions()) {
if (! -e $functionsDir) {
unless (mkdir ("$functionsDir", 0777)) {die ("Can't create output folder $functionsDir. \n$!");};
}
$self->writeFunctions();
}
if ($self->constants()) {
if (! -e $constantsDir) {
unless (mkdir ("$constantsDir", 0777)) {die ("Can't create output folder $constantsDir. \n$!");};
}
$self->writeConstants();
}
if ($self->typedefs()) {
if (! -e $dataTypesDir) {
unless (mkdir ("$dataTypesDir", 0777)) {die ("Can't create output folder $dataTypesDir. \n$!");};
}
$self->writeTypedefs();
}
if ($self->structs()) {
if (! -e $structsDir) {
unless (mkdir ("$structsDir", 0777)) {die ("Can't create output folder $structsDir. \n$!");};
}
$self->writeStructs();
}
if ($self->vars()) {
if (! -e $varsDir) {
unless (mkdir ("$varsDir", 0777)) {die ("Can't create output folder $varsDir. \n$!");};
}
$self->writeVars();
}
if ($self->enums()) {
if (! -e $enumsDir) {
unless (mkdir ("$enumsDir", 0777)) {die ("Can't create output folder $enumsDir. \n$!");};
}
$self->writeEnums();
}
if ($self->pDefines()) {
if (! -e $pDefinesDir) {
unless (mkdir ("$pDefinesDir", 0777)) {die ("Can't create output folder $pDefinesDir. \n$!");};
}
$self->writePDefines();
}
}
sub writeHeaderElementsToCompositePage { # All API in a single HTML page -- for printing
my $self = shift;
my $class = ref($self);
my $compositePageName = $class->compositePageName();
my $rootOutputDir = $self->outputDir();
my $name = $self->name();
my $compositePageString = $self->_getCompositePageString();
my $outputFile = $rootOutputDir.$pathSeparator.$compositePageName;
if (! -e $rootOutputDir) {
unless (mkdir ("$rootOutputDir", 0777)) {die ("Can't create output folder $rootOutputDir. $!");};
}
$self->_createHTMLOutputFile($outputFile, $compositePageString, "$name");
}
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 .= "Functions
\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->_getVarDetailString();
if (length($contentString)) {
$compositePageString .= "Globals
\n";
$compositePageString .= $contentString;
}
$contentString= $self->_getPDefineDetailString();
if (length($contentString)) {
$compositePageString .= "#defines
\n";
$compositePageString .= $contentString;
}
return $compositePageString;
}
sub writeFunctions {
my $self = shift;
my $functionFile = $self->functionsDir().$pathSeparator."Functions.html";
$self->_createHTMLOutputFile($functionFile, $self->_getFunctionDetailString(), "Functions");
}
sub _getFunctionDetailString {
my $self = shift;
my @funcObjs = $self->functions();
my $contentString = "";
foreach my $obj (sort objName @funcObjs) {
my $documentationBlock = $obj->documentationBlock();
$contentString .= $documentationBlock;
}
return $contentString;
}
sub writeConstants {
my $self = shift;
my $constantsFile = $self->constantsDir().$pathSeparator."Constants.html";
$self->_createHTMLOutputFile($constantsFile, $self->_getConstantDetailString(), "Constants");
}
sub _getConstantDetailString {
my $self = shift;
my @constantObjs = $self->constants();
my $contentString;
foreach my $obj (sort objName @constantObjs) {
my $documentationBlock = $obj->documentationBlock();
$contentString .= $documentationBlock;
}
return $contentString;
}
sub writeTypedefs {
my $self = shift;
my $typedefsFile = $self->datatypesDir().$pathSeparator."DataTypes.html";
$self->_createHTMLOutputFile($typedefsFile, $self->_getTypedefDetailString(), "Defined Types");
}
sub _getTypedefDetailString {
my $self = shift;
my @typedefObjs = $self->typedefs();
my $contentString;
foreach my $obj (sort objName @typedefObjs) {
my $documentationBlock = $obj->documentationBlock();
$contentString .= $documentationBlock;
}
return $contentString;
}
sub writeStructs {
my $self = shift;
my $structsFile = $self->structsDir().$pathSeparator."Structs.html";
$self->_createHTMLOutputFile($structsFile, $self->_getStructDetailString(), "Structs");
}
sub _getStructDetailString {
my $self = shift;
my @structObjs = $self->structs();
my $contentString;
foreach my $obj (sort objName @structObjs) {
my $documentationBlock = $obj->documentationBlock();
$contentString .= $documentationBlock;
}
return $contentString;
}
sub writeVars {
my $self = shift;
my $varsFile = $self->varsDir().$pathSeparator."Vars.html";
$self->_createHTMLOutputFile($varsFile, $self->_getVarDetailString(), "Data Members");
}
sub _getVarDetailString {
my $self = shift;
my @varObjs = $self->vars();
my $contentString;
foreach my $obj (sort objName @varObjs) {
my $documentationBlock = $obj->documentationBlock();
$contentString .= $documentationBlock;
}
return $contentString;
}
sub writeEnums {
my $self = shift;
my $enumsFile = $self->enumsDir().$pathSeparator."Enums.html";
$self->_createHTMLOutputFile($enumsFile, $self->_getEnumDetailString(), "Enumerations");
}
sub _getEnumDetailString {
my $self = shift;
my @enumObjs = $self->enums();
my $contentString;
foreach my $obj (sort objName @enumObjs) {
my $documentationBlock = $obj->documentationBlock();
$contentString .= $documentationBlock;
}
return $contentString;
}
sub writePDefines {
my $self = shift;
my $pDefinesFile = $self->pDefinesDir().$pathSeparator."PDefines.html";
$self->_createHTMLOutputFile($pDefinesFile, $self->_getPDefineDetailString(), "#defines");
}
sub _getPDefineDetailString {
my $self = shift;
my @pDefineObjs = $self->pDefines();
my $contentString;
foreach my $obj (sort objName @pDefineObjs) {
my $documentationBlock = $obj->documentationBlock();
$contentString .= $documentationBlock;
}
return $contentString;
}
sub writeExportsWithName {
my $self = shift;
my $name = shift;
my $exportsDir = $self->exportsDir();
my $functionsFile = $exportsDir.$pathSeparator.$name.".ftab";
my $parametersFile = $exportsDir.$pathSeparator.$name.".ptab";
my $structsFile = $exportsDir.$pathSeparator.$name.".stab";
my $fieldsFile = $exportsDir.$pathSeparator.$name.".mtab";
my $enumeratorsFile = $exportsDir.$pathSeparator.$name.".ktab";
my $funcString;
my $paramString;
my $dataTypeString;
my $typesFieldString;
my $enumeratorsString;
if (! -e $exportsDir) {
unless (mkdir ("$exportsDir", 0777)) {die ("Can't create output folder $exportsDir. $!");};
}
($funcString, $paramString) = $self->_getFunctionsAndParamsExportString();
($dataTypeString, $typesFieldString) = $self->_getDataTypesAndFieldsExportString();
$enumeratorsString = $self->_getEnumeratorsExportString();
$self->_createExportFile($functionsFile, $funcString);
$self->_createExportFile($parametersFile, $paramString);
$self->_createExportFile($structsFile, $dataTypeString);
$self->_createExportFile($fieldsFile, $typesFieldString);
$self->_createExportFile($enumeratorsFile, $enumeratorsString);
}
sub _getFunctionsAndParamsExportString {
my $self = shift;
my @funcObjs = $self->functions();
my $tmpString = "";
my @funcLines;
my @paramLines;
my $funcString;
my $paramString;
my $sep = "";
foreach my $obj (sort objName @funcObjs) {
my $funcName = $obj->name();
my $desc = $obj->discussion();
my $abstract = $obj->abstract();
my $declaration = $obj->declaration();
my @taggedParams = $obj->taggedParameters();
my @parsedParams = $obj->parsedParameters();
my $result = $obj->result();
my $funcID = HeaderDoc::DBLookup->functionIDForName($funcName);
# unused fields--declaring them for visibility in the string below
my $managerID = "";
my $funcEnglishName = "";
my $specialConsiderations = "";
my $versionNotes = "";
my $groupName = "";
my $order = "";
# Replace single internal carriage returns in fields with one space
# headerDoc2HTML already changes two \n's to \n
\n, so we'll
# just remove the breaks
foreach my $string ($desc, $abstract, $declaration, $result) {
$string =~ s/\n
\n/\n\n/g;
$string =~ s/([^\n])\n([^\n])/$1 $2/g;
}
$tmpString = $managerID.$sep.$funcID.$sep.$funcName.$sep.$funcEnglishName.$sep.$abstract.$sep.$desc.$sep.$result.$sep.$specialConsiderations.$sep.$versionNotes.$sep.$groupName.$sep.$order;
$tmpString = &convertCharsForFileMaker($tmpString);
$tmpString =~ s/$sep/\t/g;
push (@funcLines, "$tmpString");
if (@taggedParams) {
my %parsedParmNameToObjHash;
# make lookup hash of parsed params
foreach my $parsedParam (@parsedParams) {
$parsedParmNameToObjHash{$parsedParam->name()} = $parsedParam;
}
foreach my $taggedParam (@taggedParams) {
my $tName = $taggedParam->name();
my $pObj;
my $pos = "UNKNOWN_POSITION";
my $type = "UNKNOWN_TYPE";
if (exists $parsedParmNameToObjHash{$tName}) {
$pObj = $parsedParmNameToObjHash{$tName};
$pos = $pObj->position();
$type = $pObj->type();
} else {
print "---------------------------------------------------------------------------\n";
warn "Tagged parameter '$tName' not found in declaration of function $funcName.\n";
warn "Parsed declaration for $funcName is:\n$declaration\n";
warn "Parsed params for $funcName are:\n";
foreach my $pp (@parsedParams) {
my $n = $pp->name();
print "$n\n";
}
print "---------------------------------------------------------------------------\n";
}
my $paramName = $taggedParam->name();
my $disc = $taggedParam->discussion();
$disc =~ s/\n
\n/\n\n/g;
$disc =~ s/([^\n])\n([^\n])/$1 $2/g;
my $tmpParamString = "";
$tmpParamString = $funcID.$sep.$funcName.$sep.$pos.$sep.$disc.$sep.$sep.$sep.$paramName.$sep.$type;
$tmpParamString = &convertCharsForFileMaker($tmpParamString);
$tmpParamString =~ s/$sep/\t/g;
push (@paramLines, "$tmpParamString");
}
}
}
$funcString = join ("\n", @funcLines);
$paramString = join ("\n", @paramLines);
$funcString .= "\n";
$paramString .= "\n";
return ($funcString, $paramString);
}
sub _getDataTypesAndFieldsExportString {
my $self = shift;
my @structObjs = $self->structs();
my @typedefs = $self->typedefs();
my @constants = $self->constants();
my @enums = $self->enums();
my @dataTypeLines;
my @fieldLines;
my $dataTypeString;
my $fieldString;
my $sep = "";
my $tmpString = "";
my $contentString = "";
# unused fields -- here for clarity
my $englishName = "";
my $specialConsiderations = "";
my $versionNotes = "";
# get Enumerations
foreach my $obj (sort objName @enums) {
my $name = $obj->name();
my $desc = $obj->discussion();
my $abstract = $obj->abstract();
my $declaration = $obj->declaration();
my $enumID = HeaderDoc::DBLookup->typeIDForName($name);
# Replace single internal carriage returns in fields with one space
# headerDoc2HTML already changes two \n's to \n
\n, so we'll
# just remove the breaks
foreach my $string ($desc, $abstract, $declaration) {
$string =~ s/\n
\n/\n\n/g;
$string =~ s/([^\n])\n([^\n])/$1 $2/g;
}
$tmpString = $enumID.$sep.$name.$sep.$englishName.$sep.$abstract.$sep.$desc.$sep.$specialConsiderations.$sep.$versionNotes."\n";
$tmpString = &convertCharsForFileMaker($tmpString);
$tmpString =~ s/$sep/\t/g;
push (@dataTypeLines, "$tmpString");
}
# get Constants
foreach my $obj (sort objName @constants) {
my $name = $obj->name();
my $desc = $obj->discussion();
my $abstract = $obj->abstract();
my $constID = HeaderDoc::DBLookup->typeIDForName($name);
# Replace single internal carriage returns in fields with one space
# headerDoc2HTML already changes two \n's to \n
\n, so we'll
# just remove the breaks
foreach my $string ($desc, $abstract) {
$string =~ s/\n
\n/\n\n/g;
$string =~ s/([^\n])\n([^\n])/$1 $2/g;
}
$tmpString = $constID.$sep.$name.$sep.$englishName.$sep.$abstract.$sep.$desc.$sep.$specialConsiderations.$sep.$versionNotes."\n";
$tmpString = &convertCharsForFileMaker($tmpString);
$tmpString =~ s/$sep/\t/g;
push (@dataTypeLines, "$tmpString");
}
# get Structs
foreach my $obj (sort objName @structObjs) {
my $name = $obj->name();
my $desc = $obj->discussion();
my $abstract = $obj->abstract();
my $declaration = $obj->declaration();
my @fields = $obj->fields();
my $structID = HeaderDoc::DBLookup->typeIDForName($name);
# Replace single internal carriage returns in fields with one space
# headerDoc2HTML already changes two \n's to \n
\n, so we'll
# just remove the breaks
foreach my $string ($desc, $abstract, $declaration) {
$string =~ s/\n
\n/\n\n/g;
$string =~ s/([^\n])\n([^\n])/$1 $2/g;
}
$tmpString = $structID.$sep.$name.$sep.$englishName.$sep.$abstract.$sep.$desc.$sep.$specialConsiderations.$sep.$versionNotes."\n";
$tmpString = &convertCharsForFileMaker($tmpString);
$tmpString =~ s/$sep/\t/g;
push (@dataTypeLines, "$tmpString");
if (@fields) {
foreach my $field (@fields) {
my $fName = $field->name();
my $discussion = $field->discussion();
$discussion =~ s/\n
\n/\n\n/g;
$discussion =~ s/([^\n])\n([^\n])/$1 $2/g;
my $pos = 0;
$pos = $self->_positionOfNameInBlock($fName, $declaration);
if (!$pos) {
print "---------------------------------------------------------------------------\n";
warn "Tagged parameter '$fName' not found in declaration of struct $name.\n";
warn "Declaration for $name is:\n$declaration\n";
print "---------------------------------------------------------------------------\n";
$pos = "UNKNOWN_POSITION";
}
my $tmpFieldString = "";
$tmpFieldString = $structID.$sep.$name.$sep.$pos.$sep.$discussion.$sep.$sep.$sep.$fName;
$tmpFieldString = &convertCharsForFileMaker($tmpFieldString);
$tmpFieldString =~ s/$sep/\t/g;
push (@fieldLines, "$tmpFieldString");
}
}
}
# get Typedefs
foreach my $obj (sort objName @typedefs) {
my $name = $obj->name();
my $desc = $obj->discussion();
my $abstract = $obj->abstract();
my $declaration = $obj->declaration();
my @fields = $obj->fields();
my $isFunctionPointer = $obj->isFunctionPointer();
my $typedefID = HeaderDoc::DBLookup->typeIDForName($name);
# Replace single internal carriage returns in fields with one space
# headerDoc2HTML already changes two \n's to \n
\n, so we'll
# just remove the breaks
foreach my $string ($desc, $abstract, $declaration) {
$string =~ s/\n
\n/\n\n/g;
$string =~ s/([^\n])\n([^\n])/$1 $2/g;
}
$tmpString = $typedefID.$sep.$name.$sep.$englishName.$sep.$abstract.$sep.$desc.$sep.$specialConsiderations.$sep.$versionNotes."\n";
$tmpString = &convertCharsForFileMaker($tmpString);
$tmpString =~ s/$sep/\t/g;
push (@dataTypeLines, "$tmpString");
if (@fields) {
foreach my $field (@fields) {
my $fName = $field->name();
my $discussion = $field->discussion();
$discussion =~ s/\n
\n/\n\n/g;
$discussion =~ s/([^\n])\n([^\n])/$1 $2/g;
my $pos = 0;
if ($isFunctionPointer) {
$pos = $self->_positionOfNameInFuncPtrDec($fName, $declaration);
} else {
$pos = $self->_positionOfNameInBlock($fName, $declaration);
}
if (!$pos) {
print "---------------------------------------------------------------------------\n";
warn "Tagged parameter '$fName' not found in declaration of struct $name.\n";
warn "Declaration for $name is:\n$declaration\n";
print "---------------------------------------------------------------------------\n";
$pos = "UNKNOWN_POSITION";
}
my $tmpFieldString = "";
$tmpFieldString = $typedefID.$sep.$name.$sep.$pos.$sep.$discussion.$sep.$sep.$sep.$fName;
$tmpFieldString = &convertCharsForFileMaker($tmpFieldString);
$tmpFieldString =~ s/$sep/\t/g;
push (@fieldLines, "$tmpFieldString");
}
}
}
$dataTypeString = join ("\n", @dataTypeLines);
$fieldString = join ("\n", @fieldLines);
$dataTypeString .= "\n";
$fieldString .= "\n";
return ($dataTypeString, $fieldString);
}
sub _getEnumeratorsExportString {
my $self = shift;
my @enums = $self->enums();
my @fieldLines;
my $fieldString;
my $sep = "";
my $tmpString = "";
my $contentString = "";
# get Enumerations
foreach my $obj (sort objName @enums) {
my $name = $obj->name();
my @constants = $obj->constants();
my $declaration = $obj->declaration();
my $enumID = HeaderDoc::DBLookup->typeIDForName($name);
if (@constants) {
foreach my $enumerator (@constants) {
my $fName = $enumerator->name();
my $discussion = $enumerator->discussion();
my $pos = 0;
$discussion =~ s/\n
\n/\n\n/g;
$discussion =~ s/([^\n])\n([^\n])/$1 $2/g;
$pos = $self->_positionOfNameInEnum($fName, $declaration);
if (!$pos) {
print "---------------------------------------------------------------------------\n";
warn "Tagged parameter '$fName' not found in declaration of enum $name.\n";
warn "Declaration for $name is:\n$declaration\n";
print "---------------------------------------------------------------------------\n";
$pos = "UNKNOWN_POSITION";
}
my $tmpFieldString = "";
$tmpFieldString = $enumID.$sep.$name.$sep.$pos.$sep.$discussion.$sep.$sep.$sep.$fName;
$tmpFieldString = &convertCharsForFileMaker($tmpFieldString);
$tmpFieldString =~ s/$sep/\t/g;
push (@fieldLines, "$tmpFieldString");
}
}
}
$fieldString = join ("\n", @fieldLines);
$fieldString .= "\n";
return $fieldString;
}
# this is simplistic is various ways--should be made more robust.
sub _positionOfNameInBlock {
my $self = shift;
my $name = shift;
my $block = shift;
$block =~ s/\n/ /g;
my $pos = 0;
my $i = 0;
my @chunks = split (/;/, $block);
foreach my $string (@chunks) {
$i++;
$string = quotemeta($string);
if ($string =~ /$name/) {
$pos = $i;
last;
}
}
return $pos;
}
sub _positionOfNameInEnum {
my $self = shift;
my $name = shift;
my $block = shift;
$block =~ s/\n/ /g;
my $pos = 0;
my $i = 0;
my @chunks = split (/,/, $block);
foreach my $string (@chunks) {
$i++;
$string = quotemeta($string);
if ($string =~ /$name/) {
$pos = $i;
last;
}
}
return $pos;
}
sub _positionOfNameInFuncPtrDec {
my $self = shift;
my $name = shift;
my $dec = shift;
$dec =~ s/\n/ /g;
my @decParts = split (/\(/, $dec);
my $paramList = pop @decParts;
my $pos = 0;
my $i = 0;
my @chunks = split (/,/, $paramList);
foreach my $string (@chunks) {
$i++;
$string = quotemeta($string);
if ($string =~ /$name/) {
$pos = $i;
last;
}
}
return $pos;
}
sub _createExportFile {
my $self = shift;
my $outputFile = shift;
my $fileString = shift;
open(OUTFILE, ">$outputFile") || die "Can't write $outputFile.\n";
if ($^O =~ /MacOS/i) {MacPerl::SetFileInfo('R*ch', 'TEXT', "$outputFile");};
print OUTFILE $fileString;
close OUTFILE;
}
sub _createHTMLOutputFile {
my $self = shift;
my $class = ref($self);
my $copyrightOwner = $class->copyrightOwner();
my $outputFile = shift;
my $fileString = shift;
my $heading = shift;
open(OUTFILE, ">$outputFile") || die "Can't write $outputFile.\n";
if ($^O =~ /MacOS/i) {MacPerl::SetFileInfo('MSIE', 'TEXT', "$outputFile");};
print OUTFILE "$heading$heading
\n";
print OUTFILE $fileString;
print OUTFILE "";
print OUTFILE "
© $copyrightOwner " if (length($copyrightOwner));
print OUTFILE "(Last Updated $dateStamp)\n";
print OUTFILE "
";
print OUTFILE "\n";
close OUTFILE;
}
sub objName { # used for sorting
my $obj1 = $a;
my $obj2 = $b;
return ($obj1->name() cmp $obj2->name());
}
##################### Debugging ####################################
sub printObject {
my $self = shift;
print "Header\n";
$self->SUPER::printObject();
print "outputDir: $self->{OUTPUTDIR}\n";
print "constantsDir: $self->{CONSTANTSDIR}\n";
print "datatypesDir: $self->{DATATYPESDIR}\n";
print "functionsDir: $self->{FUNCTIONSDIR}\n";
print "typedefsDir: $self->{TYPEDEFSDIR}\n";
print "constants:\n";
&printArray(@{$self->{CONSTANTS}});
print "functions:\n";
&printArray(@{$self->{FUNCTIONS}});
print "typedefs:\n";
&printArray(@{$self->{TYPEDEFS}});
print "structs:\n";
&printArray(@{$self->{STRUCTS}});
print "\n";
}
1;