gatherHeaderDoc.pl [plain text]
my $pathSeparator;
my $isMacOS;
my $uninstalledModulesPath;
my $devtoolsModulesPath;
my $has_resolver;
sub resolveLinks($$$);
$HeaderDoc::groupHierLimit = undef;
$HeaderDoc::groupHierSubgroupLimit = undef;
BEGIN {
use FindBin qw ($Bin);
if ($^O =~ /MacOS/i) {
$pathSeparator = ":";
$isMacOS = 1;
($uninstalledModulesPath = $FindBin::Bin) =~ s/([^:]*):$/$1/;
} else {
$pathSeparator = "/";
$isMacOS = 0;
}
$uninstalledModulesPath = "$FindBin::Bin"."$pathSeparator"."Modules";
$devtoolsModulesPath = "$FindBin::Bin"."$pathSeparator".".."."$pathSeparator"."share"."$pathSeparator"."headerdoc"."$pathSeparator"."Modules";
$HeaderDoc::use_styles = 0;
}
use strict;
use File::Basename;
use File::Find;
use File::Copy;
use lib $uninstalledModulesPath;
use lib $devtoolsModulesPath;
use POSIX;
my $generateDocSet = 0;
my $skipTOC = 0;
my $noResolve = 0;
$HeaderDoc::useWhatIs = 0;
$has_resolver = 1;
eval "use HeaderDoc::LinkResolver qw (resolveLinks); 1" || do { $has_resolver = 0; };
if ($has_resolver) {
print STDERR "LinkResolver will be used to resolve cross-references.\n";
}
use HeaderDoc::DocReference;
use HeaderDoc::Utilities qw(findRelativePath safeName printArray printHash updateHashFromConfigFiles getHashFromConfigFile resolveLinks sanitize stripTags getDefaultEncoding);
$HeaderDoc::modulesPath = $INC{'HeaderDoc/Utilities.pm'};
$HeaderDoc::modulesPath =~ s/Utilities.pm$//s;
my $debugging = 1;
my @inputFiles;
my @contentFiles;
my $inputDir;
my $externalXRefFiles = "";
my $linktarget = "";
use Getopt::Std;
my %options = ();
my %letters_linked = ();
my %group_letters_linked = ();
getopts("Nc:dnwt:x:",\%options);
my $masterTOCFileName = "";
if (($#ARGV == 0 || $#ARGV == 1 || $#ARGV == 2) && (-d $ARGV[0])) {
$inputDir = $ARGV[0];
if ($#ARGV) {
$masterTOCFileName = $ARGV[1];
}
} else {
die "You must specify a single input directory for processing.\n";
}
my $localConfigFileName = "headerDoc2HTML.config";
my $preferencesConfigFileName = "com.apple.headerDoc2HTML.config";
my $homeDir;
my $usersPreferencesPath;
my $systemPreferencesPath;
if ($^O =~ /MacOS/i) {
eval {
require "FindFolder.pl";
$homeDir = MacPerl::FindFolder("D"); $usersPreferencesPath = MacPerl::FindFolder("P"); };
if ($@) {
import Mac::Files;
$homeDir = Mac::Files::FindFolder(kOnSystemDisk(), kDesktopFolderType());
$usersPreferencesPath = Mac::Files::FindFolder(kOnSystemDisk(), kPreferencesFolderType());
}
$systemPreferencesPath = $usersPreferencesPath;
} else {
$homeDir = (getpwuid($<))[7];
$usersPreferencesPath = $homeDir.$pathSeparator."Library".$pathSeparator."Preferences";
$systemPreferencesPath = "/Library/Preferences";
}
my $usrPreferencesPath = "/usr/share/headerdoc/conf";
my $devtoolsPreferencesPath = "$FindBin::Bin"."$pathSeparator".".."."$pathSeparator"."share"."$pathSeparator"."headerdoc"."$pathSeparator"."conf";
my $CWD = getcwd();
my @configFiles = ($devtoolsPreferencesPath.$pathSeparator.$preferencesConfigFileName, $systemPreferencesPath.$pathSeparator.$preferencesConfigFileName, $usersPreferencesPath.$pathSeparator.$preferencesConfigFileName, $Bin.$pathSeparator.$localConfigFileName, $CWD.$pathSeparator.$localConfigFileName);
my %config = (
defaultFrameName => "index.html",
masterTOCName => "MasterTOC.html",
groupHierLimit => 0,
groupHierSubgroupLimit => 0
);
if ($options{c}) {
@configFiles = ( $options{c} );
}
%config = &updateHashFromConfigFiles(\%config,\@configFiles);
my $framesetFileName;
my @TOCTemplateList = ();
my @TOCNames = ();
my $framework = "";
my $frameworknestlevel = -1;
my $frameworkShortName = "";
my $frameworkpath = "";
my $headerpath = "";
my $frameworkrelated = "";
my $frameworkUID = "";
my $frameworkCopyrightString = "";
my $landingPageUID = "";
my $landingPageFrameworkUID = "";
my $stripDotH = 0;
my $gather_functions = 0;
my $gather_types = 0;
my $gather_properties = 0;
my $gather_globals_and_constants = 0;
my $gather_man_pages = 0;
my $apiUIDPrefix = "apple_ref";
my $compositePageName = "CompositePage.html";
my $classAsComposite = 0;
my $externalAPIUIDPrefixes = "";
my %usedInTemplate = ();
$HeaderDoc::addTopLink = 1;
if (defined $config{"addTopLink"}) {
$HeaderDoc::addTopLink = $config{"addTopLink"};
}
if (defined $config{"dateFormat"}) {
$HeaderDoc::datefmt = $config{"dateFormat"};
if ($HeaderDoc::datefmt !~ /\S/) {
$HeaderDoc::datefmt = "%B %d, %Y";
}
} else {
$HeaderDoc::datefmt = "%B %d, %Y";
}
use HeaderDoc::APIOwner;
my $tocEncoding = getDefaultEncoding();
if (defined ($config{"tocTemplateEncoding"}) && length($config{"tocTemplateEncoding"})) {
warn("The configuration key tocTemplateEncoding is deprecated.\nUse TOCTemplateEncoding instead.");
$tocEncoding = $config{"tocTemplateEncoding"}
}
if (defined ($config{"TOCTemplateEncoding"}) && length($config{"TOCTemplateEncoding"})) {
$tocEncoding = $config{"TOCTemplateEncoding"}
}
HeaderDoc::APIOwner::fix_date($tocEncoding);
my ($sec,$min,$hour,$mday,$mon,$yr,$wday,$yday,$isdst) = localtime(time());
my $yearStamp = strftime("%Y", $sec, $min, $hour,
$mday, $mon, $yr, $wday, $yday, $isdst);
my $dateStamp = HeaderDoc::HeaderElement::strdate($mon, $mday, $yr + 1900, $tocEncoding);
if (defined $config{"styleImports"}) {
$HeaderDoc::styleImports = $config{"styleImports"};
$HeaderDoc::styleImports =~ s/[\n\r]/ /sgo;
$HeaderDoc::use_styles = 1;
}
if (defined $config{"groupHierLimit"}) {
$HeaderDoc::groupHierLimit = $config{"groupHierLimit"};
}
if (defined $config{"groupHierSubgroupLimit"}) {
$HeaderDoc::groupHierSubgroupLimit = $config{"groupHierSubgroupLimit"};
}
if (defined $config{"tocStyleImports"}) {
$HeaderDoc::tocStyleImports = $config{"tocStyleImports"};
$HeaderDoc::tocStyleImports =~ s/[\n\r]/ /sgo;
$HeaderDoc::use_styles = 1;
}
if (defined $config{"textStyle"}) {
HeaderDoc::APIOwner->setStyle("text", $config{"textStyle"});
}
if (defined $config{"copyrightOwner"}) {
$HeaderDoc::copyrightOwner = $config{"copyrightOwner"};
}
if (defined $config{"commentStyle"}) {
HeaderDoc::APIOwner->setStyle("comment", $config{"commentStyle"});
}
if (defined $config{"preprocessorStyle"}) {
HeaderDoc::APIOwner->setStyle("preprocessor", $config{"preprocessorStyle"});
}
if (defined $config{"funcNameStyle"}) {
HeaderDoc::APIOwner->setStyle("function", $config{"funcNameStyle"});
}
if (defined $config{"stringStyle"}) {
HeaderDoc::APIOwner->setStyle("string", $config{"stringStyle"});
}
if (defined $config{"charStyle"}) {
HeaderDoc::APIOwner->setStyle("char", $config{"charStyle"});
}
if (defined $config{"numberStyle"}) {
HeaderDoc::APIOwner->setStyle("number", $config{"numberStyle"});
}
if (defined $config{"keywordStyle"}) {
HeaderDoc::APIOwner->setStyle("keyword", $config{"keywordStyle"});
}
if (defined $config{"typeStyle"}) {
HeaderDoc::APIOwner->setStyle("type", $config{"typeStyle"});
}
if (defined $config{"paramStyle"}) {
HeaderDoc::APIOwner->setStyle("param", $config{"paramStyle"});
}
if (defined $config{"varStyle"}) {
HeaderDoc::APIOwner->setStyle("var", $config{"varStyle"});
}
if (defined $config{"templateStyle"}) {
HeaderDoc::APIOwner->setStyle("template", $config{"templateStyle"});
}
if (defined $config{"externalXRefFiles"}) {
$externalXRefFiles = $config{"externalXRefFiles"};
}
if (defined $config{"externalAPIUIDPrefixes"}) {
$externalAPIUIDPrefixes = $config{"externalAPIUIDPrefixes"};
}
if (defined $config{"defaultFrameName"}) {
$framesetFileName = $config{"defaultFrameName"};
}
if (defined $config{"apiUIDPrefix"}) {
$apiUIDPrefix = $config{"apiUIDPrefix"};
}
if (defined $config{"compositePageName"}) {
$compositePageName = $config{"compositePageName"};
}
if (defined $config{"classAsComposite"}) {
$classAsComposite = $config{"classAsComposite"};
$classAsComposite =~ s/\s*//;
} else {
$classAsComposite = 0;
}
if (defined $config{"masterTOCName"} && $masterTOCFileName eq "") {
$masterTOCFileName = $config{"masterTOCName"};
}
if (defined $config{"stripDotH"}) {
$stripDotH = $config{"stripDotH"};
}
$GHD::bgcolor = "#ffffff";
my $TOCTemplateFile = "HEADERDOC_DEFAULT_INTERNAL_TEMPLATE";
if (defined $config{"TOCTemplateFile"}) {
$TOCTemplateFile = $config{"TOCTemplateFile"};
}
my $oldRecSep = $/;
undef $/;
my @filelist = split(/\s/, $TOCTemplateFile);
foreach my $file (@filelist) {
my %used = ();
my $TOCTemplate = "";
my $found = 0;
my $foundpath = "";
if ($file eq "HEADERDOC_DEFAULT_INTERNAL_TEMPLATE") {
$found = 1;
$foundpath = "n/a";
$TOCTemplate = default_template();
} else {
print STDERR "Searching for $file\n";
my @templateFiles = ($devtoolsPreferencesPath.$pathSeparator.$file, $usrPreferencesPath.$pathSeparator.$file, $systemPreferencesPath.$pathSeparator.$file, $usersPreferencesPath.$pathSeparator.$file, $Bin.$pathSeparator.$file, $file);
foreach my $filename (@templateFiles) {
if (open(TOCFILE, "<$filename")) {
$TOCTemplate = <TOCFILE>;
close(TOCFILE);
$found = 1;
$foundpath = $filename;
}
}
if (!$found) {
die("Template file $file not found.\n");
} else {
print STDERR "Found at $foundpath\n";
}
}
push(@TOCTemplateList, $TOCTemplate);
push(@TOCNames, basename($file));
if ($TOCTemplate =~ /\$\$\s*typelist/) {
$gather_types = 1;
$used{type} = 1;
}
if ($TOCTemplate =~ /\$\$\s*proplist/) {
$gather_properties = 1;
$used{prop} = 1;
}
if ($TOCTemplate =~ /\$\$\s*datalist/) {
$gather_globals_and_constants = 1;
$used{data} = 1;
}
if ($TOCTemplate =~ /\$\$\s*functionlist/) {
$gather_functions = 1;
$used{function} = 1;
}
if ($TOCTemplate =~ /\$\$\s*manpagelist/) {
$gather_man_pages = 1;
$used{manpage} = 1;
}
if ($TOCTemplate =~ /\$\$\s*headerlist/) {
$used{header} = 1;
}
if ($TOCTemplate =~ /\$\$\s*macrolist/) {
$used{macro} = 1;
}
if ($TOCTemplate =~ /\$\$\s*protocollist/) {
$used{protocol} = 1;
}
if ($TOCTemplate =~ /\$\$\s*categorylist/) {
$used{category} = 1;
}
if ($TOCTemplate =~ /\$\$\s*classlist/) {
$used{class} = 1;
}
if ($TOCTemplate =~ /\$\$\s*comintlist/) {
$used{comint} = 1;
}
$usedInTemplate{$TOCTemplate} = \%used;
}
$/ = $oldRecSep;
my $useBreadcrumbs = 0;
if (defined $config{"useBreadcrumbs"}) {
$useBreadcrumbs = $config{"useBreadcrumbs"};
}
if ($options{w}) {
$HeaderDoc::useWhatIs = 1;
}
if ($options{d}) {
$generateDocSet = 1;
if ($options{n}) {
$skipTOC = 1;
}
}
if ($options{N}) {
$noResolve = 1;
}
if ($options{x}) {
$externalXRefFiles = $options{x};
}
if ($options{t}) {
$linktarget = " target=\"".$options{t}."\"";
}
if ($^O =~ /MacOS/i) {
find(\&getFiles, $inputDir);
$inputDir =~ s/([^:]*):$/$1/; } else {
$inputDir =~ s|(.*)/$|$1|; if ($inputDir !~ /^\//) { # not absolute path -- !!! should check for ~
my $cwd = getcwd();
$inputDir = $cwd.$pathSeparator.$inputDir;
}
&find({wanted => \&getFiles, follow => 1}, $inputDir);
}
unless (@inputFiles) { print STDERR "No valid input files specified. \n\n"; exit(-1)};
sub getFiles {
my $filePath = $File::Find::name;
my $fileName = $_;
my $localDebug = 0;
my $basePath = dirname($filePath);
my $dirName = basename($basePath);
print STDERR "$fileName ($filePath): " if ($localDebug);
if ($fileName =~ /$framesetFileName/) {
print STDERR "HTML frameset\n" if ($localDebug);
push(@inputFiles, $filePath);
push(@contentFiles, $filePath);
} elsif ($dirName =~ /^(man|cat)[\w\d]+$/ && $gather_man_pages) {
print STDERR "Man Page\n" if ($localDebug);
push(@inputFiles, $filePath);
push(@contentFiles, $filePath);
} elsif ($fileName =~ /Constants\.html$/ && $gather_globals_and_constants && !$classAsComposite) {
print STDERR "Constants\n" if ($localDebug);
push(@inputFiles, $filePath);
push(@contentFiles, $filePath);
} elsif ($fileName =~ /Vars\.html$/ && $gather_globals_and_constants && !$classAsComposite) {
print STDERR "Vars\n" if ($localDebug);
push(@inputFiles, $filePath);
push(@contentFiles, $filePath);
} elsif ($fileName =~ /DataTypes\.html$/ && $gather_types && !$classAsComposite) {
print STDERR "DataTypes\n" if ($localDebug);
push(@inputFiles, $filePath);
push(@contentFiles, $filePath);
} elsif ($fileName =~ /Structs\.html$/ && $gather_types && !$classAsComposite) {
print STDERR "Structs\n" if ($localDebug);
push(@inputFiles, $filePath);
push(@contentFiles, $filePath);
} elsif ($fileName =~ /Enums\.html$/ && $gather_types && !$classAsComposite) {
print STDERR "Enums\n" if ($localDebug);
push(@inputFiles, $filePath);
push(@contentFiles, $filePath);
} elsif ($fileName =~ /Methods\.html$/ && $gather_functions && !$classAsComposite) {
print STDERR "Methods\n" if ($localDebug);
push(@inputFiles, $filePath);
push(@contentFiles, $filePath);
} elsif ($fileName =~ /Functions\.html$/ && $gather_functions && !$classAsComposite) {
print STDERR "Functions\n" if ($localDebug);
push(@inputFiles, $filePath);
push(@contentFiles, $filePath);
} elsif ($fileName =~ /doc\.html$/ && !$classAsComposite) {
print STDERR "Framework Documentation\n" if ($localDebug);
push(@inputFiles, $filePath);
push(@contentFiles, $filePath);
} elsif ($fileName !~ /toc\.html$/) {
print STDERR "Other Content\n" if ($localDebug);
if ($classAsComposite && $fileName =~ /\Q$compositePageName\E$/) {
push(@inputFiles, $filePath);
}
push(@contentFiles, $filePath);
} else {
print STDERR "toc.\n" if ($localDebug);
}
}
my @fileRefSets;
my @headerFramesetRefs;
my @propFramesetRefs;
my @dataFramesetRefs;
my @macroFramesetRefs;
my @typeFramesetRefs;
my @comintFramesetRefs;
my @classFramesetRefs;
my @manpageFramesetRefs;
my @categoryFramesetRefs;
my @protocolFramesetRefs;
my @functionRefs;
my $frameworkabstract = "";
my $frameworkdiscussion = "";
$oldRecSep = $/;
undef $/;
my $localDebug = 0;
my %groups = ();
$groups{" "}="";
$| = 1;
print STDERR "Processing...";
foreach my $file (@inputFiles) {
my @perFileDocRefs = ();
if (-f $file) {
open (INFILE, "<$file") || die "Can't open $file: $!\n";
my $fileString = <INFILE>;
close INFILE;
my $fileStringCopy = $fileString;
while ($fileStringCopy =~ s/<\!--\s+(headerDoc\s*=.*?)-->(.*)/$2/s) {
my $fullComment = $1;
my $tail = $2;
my $inDiscussion = 0;
my $inFrameworkDiscussion = 0;
my $inFrameworkAbstract = 0;
my $inAbstract = 0;
my $inDeclaration = 0;
my $inPath = 0;
my $inHeaderPath = 0;
my $inRelated = 0;
my $inFWUID = 0;
my $inFWCopyright = 0;
my @stockpairs = split(/;/, $fullComment);
my @pairs = ();
my $discussion = "";
my $abstract = "";
my $declaration = "";
my $temp = "";
foreach my $stockpair (@stockpairs) {
if (length($temp)) {
$temp .= $stockpair;
if ($temp !~ /\\$/) {
push(@pairs, $temp);
$temp = "";
}
} else {
if ($stockpair =~ /\\$/) {
$temp = $stockpair;
$temp =~ s/\\$/;/s;
} else {
push(@pairs, $stockpair);
$temp = "";
}
}
}
my $docRef = HeaderDoc::DocReference->new();
$docRef->path($file);
print STDERR ".";
foreach my $pair (@pairs) {
my ($key, $value) = split(/=/, $pair, 2);
$key =~ s/^\s+|\s+$//;
$value =~ s/^\s+|\s+$//;
SWITCH: {
($key =~ /indexgroup/) && do
{
my $group = $value;
$group =~ s/^\s*//sg;
$group =~ s/\s*$//sg;
$group =~ s/\\;/;/sg;
$docRef->group($group);
$groups{$group}=1;
};
($key =~ /headerDoc/) &&
do {
$docRef->type($value);
if ($value =~ /discussion/) {
$inDiscussion = 1;
}
if ($value =~ /frameworkdiscussion/) {
if (rightframework($file)) {
$inFrameworkDiscussion = 1;
}
}
if ($value =~ /declaration/) {
$inDeclaration = 1;
}
if ($value =~ /abstract/) {
$inAbstract = 1;
}
if ($value =~ /frameworkabstract/) {
if (rightframework($file)) {
$inFrameworkAbstract = 1;
}
}
if ($value =~ /frameworkpath/) {
if (rightframework($file)) {
$inPath = 1;
}
}
if ($value =~ /headerpath/) {
if (rightframework($file)) {
$inHeaderPath = 1;
}
}
if ($value =~ /frameworkrelated/) {
if (rightframework($file)) {
$inRelated = 1;
}
}
if ($value =~ /frameworkuid/) {
if (rightframework($file)) {
$inFWUID = 1;
}
};
if ($value =~ /frameworkcopyright/) {
if (rightframework($file)) {
$inFWCopyright = 1;
}
};
last SWITCH;
};
($key =~ /shortname/) &&
do {
$docRef->shortname($value);
last SWITCH;
};
($key =~ /uid/) &&
do {
my $newDocRef = $docRef->uid($value, $file);
if ($newDocRef->path() eq $file) {
$docRef = $newDocRef;
}
};
($key =~ /mansrc/) &&
do {
$docRef->mansrc($value);
};
($key =~ /name/) &&
do {
$docRef->name($value);
if ($inFrameworkDiscussion && $value =~ /start/) {
$frameworkdiscussion = $tail;
$frameworkdiscussion =~ s/<!--\s+headerDoc\s*.*//sg;
$docRef->discussion($frameworkdiscussion);
} elsif ($inFrameworkDiscussion && $value =~ /end/) {
$inFrameworkDiscussion = 0;
}
if ($inDiscussion && $value =~ /start/) {
$discussion = $tail;
$discussion =~ s/<!--\s+headerDoc\s*.*//sg;
$docRef->discussion($discussion);
} elsif ($inDiscussion && $value =~ /end/) {
$inDiscussion = 0;
}
if ($inFrameworkAbstract && $value =~ /start/) {
$frameworkabstract = $tail;
$frameworkabstract =~ s/<!--\s+headerDoc\s*.*//sg;
$docRef->abstract($frameworkabstract);
} elsif ($inFrameworkAbstract && $value =~ /end/) {
$inFrameworkAbstract = 0;
}
if ($inAbstract && $value =~ /start/) {
$abstract = $tail;
$abstract =~ s/<!--\s+headerDoc\s*.*//sg;
$docRef->abstract($abstract);
} elsif ($inAbstract && $value =~ /end/) {
$inAbstract = 0;
}
if ($inDeclaration && $value =~ /start/) {
$declaration = $tail;
$declaration =~ s/<!--\s+headerDoc\s*.*//sg;
$docRef->declaration($declaration);
print STDERR "SETTING DEC TO \"$declaration\" FOR $docRef\n" if ($localDebug);
} elsif ($inDeclaration && $value =~ /end/) {
$inDeclaration = 0;
}
if ($inRelated && $value =~ /start/) {
$frameworkrelated = $tail;
$frameworkrelated =~ s/<!--\s+headerDoc\s*.*//sg;
$frameworkrelated =~ s/^\s*//sg;
$frameworkrelated =~ s/\s*$//sg;
} elsif ($inRelated && $value =~ /end/) {
$inRelated = 0;
}
if ($inFWUID && $value =~ /start/) {
$frameworkUID = $tail;
$frameworkUID =~ s/<!--\s+headerDoc\s*.*//sg;
$frameworkUID =~ s/^\s*//sg;
$frameworkUID =~ s/\s*$//sg;
if ($frameworkUID =~ /\S/) {
$landingPageFrameworkUID = "//$apiUIDPrefix/doc/uid/$frameworkUID";
}
} elsif ($inFWUID && $value =~ /end/) {
$inFWUID = 0;
}
if ($inFWCopyright && $value =~ /start/) {
$frameworkCopyrightString = $tail;
$frameworkCopyrightString =~ s/<!--\s+headerDoc\s*.*//sg;
$frameworkCopyrightString =~ s/^\s*//sg;
$frameworkCopyrightString =~ s/\s*$//sg;
} elsif ($inFWCopyright && $value =~ /end/) {
$inFWCopyright = 0;
}
if ($inHeaderPath && $value =~ /start/) {
$headerpath = $tail;
$headerpath =~ s/<!--\s+headerDoc\s*.*//sg;
$headerpath =~ s/^\s*//sg;
$headerpath =~ s/\s*$//sg;
} elsif ($inHeaderPath && $value =~ /end/) {
$inHeaderPath = 0;
}
if ($inPath && $value =~ /start/) {
$frameworkpath = $tail;
$frameworkpath =~ s/<!--\s+headerDoc\s*.*//sg;
$frameworkpath =~ s/^\s*//sg;
$frameworkpath =~ s/\s*$//sg;
} elsif ($inPath && $value =~ /end/) {
$inPath = 0;
}
last SWITCH;
};
}
}
my $tmpType = $docRef->type();
my $isTitle = 0;
if ($tmpType =~ /^title:(.*)$/s) {
$tmpType = $1;
$isTitle = 1; }
if (!$docRef->uid()) {
print STDERR "REF UID BLANK FOR : ".$docRef->name()." in file $file\n";
}
if ($tmpType eq "Header") {
if (!$docRef->pushed()) { push (@headerFramesetRefs, $docRef); }
} elsif ($tmpType eq "instp"){
if (!$docRef->pushed()) { push (@propFramesetRefs, $docRef); }
} elsif ($tmpType eq "clconst"){
if (!$docRef->pushed()) { push (@dataFramesetRefs, $docRef); }
} elsif ($tmpType eq "data"){
if (!$docRef->pushed()) { push (@dataFramesetRefs, $docRef); }
} elsif ($tmpType eq "tag"){
if (!$docRef->pushed()) { push (@typeFramesetRefs, $docRef); }
} elsif ($tmpType eq "tdef"){
if (!$docRef->pushed()) { push (@typeFramesetRefs, $docRef); }
} elsif ($tmpType eq "com"){
if (!$docRef->pushed()) { push (@comintFramesetRefs, $docRef); }
} elsif ($tmpType eq "cl"){
if (!$docRef->pushed()) { push (@classFramesetRefs, $docRef); }
} elsif ($tmpType eq "man"){
if (!$docRef->pushed()) { push (@manpageFramesetRefs, $docRef); }
} elsif ($tmpType eq "intf"){
if (!$docRef->pushed()) { push (@protocolFramesetRefs, $docRef); }
} elsif ($tmpType eq "macro"){
if (!$docRef->pushed()) { push (@macroFramesetRefs, $docRef); }
} elsif ($tmpType eq "functionparam"){
print "Silently ignoring symbol of type $tmpType\n" if ($localDebug);
} elsif ($tmpType eq "enumconstant"){
print "Silently ignoring symbol of type $tmpType\n" if ($localDebug);
} elsif ($tmpType eq "methodparam"){
print "Silently ignoring symbol of type $tmpType\n" if ($localDebug);
} elsif ($tmpType eq "defineparam"){
print "Silently ignoring symbol of type $tmpType\n" if ($localDebug);
} elsif ($tmpType eq "structfield"){
print "Silently ignoring symbol of type $tmpType\n" if ($localDebug);
} elsif ($tmpType eq "typedeffield"){
print "Silently ignoring symbol of type $tmpType\n" if ($localDebug);
} elsif ($tmpType eq "cat"){
if (!$docRef->pushed()) { push (@categoryFramesetRefs, $docRef); }
} elsif ($tmpType eq "func" || $tmpType eq "instm" ||
$tmpType eq "intfm" || $tmpType eq "clm" ||
$tmpType eq "ftmplt") {
if (!$isTitle) {
if (!$docRef->pushed()) { push (@functionRefs, $docRef); }
}
} elsif ($tmpType eq "Framework" || $tmpType eq "framework") {
if (rightframework($file)) {
$framework = $docRef->name();
$frameworkShortName = $docRef->shortname();
$landingPageUID = "//$apiUIDPrefix/doc/framework/$frameworkShortName";
if ($frameworkUID =~ /\S/) {
$landingPageFrameworkUID = "//$apiUIDPrefix/doc/uid/$frameworkUID";
}
}
} elsif ($tmpType eq "frameworkdiscussion" ||
$tmpType eq "frameworkabstract" ||
$tmpType eq "frameworkuid" ||
$tmpType eq "frameworkcopyright" ||
$tmpType eq "frameworkpath" ||
$tmpType eq "headerpath" ||
$tmpType eq "frameworkrelated") {
if ($localDebug) {
print STDERR "Discussion: $frameworkdiscussion\n";
print STDERR "Abstract: $frameworkabstract\n";
print STDERR "UID: $frameworkUID\n";
print STDERR "Copyright: $frameworkCopyrightString\n";
print STDERR "Framework Path: $frameworkpath\n";
print STDERR "Header Path: $frameworkpath\n";
print STDERR "Related: $frameworkrelated\n";
}
} elsif ($tmpType eq "abstract") {
print STDERR "Ignored abstract\n" if ($localDebug);
} elsif ($tmpType eq "discussion") {
print STDERR "Ignored discussion\n" if ($localDebug);
} elsif ($tmpType eq "inheritedContent") {
print STDERR "Inherited content: ".$docRef->name()."\n" if ($localDebug);
} elsif ($tmpType eq "econst") {
print STDERR "Embedded constant: ".$docRef->name()."\n" if ($localDebug);
if (!$docRef->pushed()) { push (@dataFramesetRefs, $docRef); }
} else {
my $tmpName = $docRef->name();
my $tmpPath = $docRef->path();
my $tmpUID = $docRef->uid();
print STDERR "Unknown type '$tmpType' for document with name '$tmpName', path '$tmpPath', UID '$tmpUID'\n";
}
if ($docRef->uid() && !$docRef->pushed()) {
print STDERR "PUSHED ".$docRef->uid()." with name ".$docRef->name()."\n" if ($localDebug);
push(@perFileDocRefs, $docRef);
}
$docRef->pushed(1);
}
}
my $docRef = HeaderDoc::DocReference->new();
$docRef->name($file);
$docRef->path($file);
$docRef->group( \@perFileDocRefs );
push(@fileRefSets, $docRef);
}
$/ = $oldRecSep;
print STDERR "\ndone.\n";
$| = 0;
if (scalar(@manpageFramesetRefs)) {
my %mplatest = ();
my %mpversions = ();
my %reftype = ();
my @newmanpageFramesetRefs = ();
my $currentOS = $ENV{"OS_VERSION"}; my $currentXcode = $ENV{"XCODE_VERSION"};
my $localDebug = 0;
foreach my $page (@manpageFramesetRefs) {
my $ref = $page->uid();
$ref =~ s/^"//;
$ref =~ s/"$//;
print STDERR "REF IS: $ref\n" if ($localDebug);
if ($ref =~ /\/\/apple_ref\/doc\/man\/(.*?)\/(.*)/) {
my $longname = "$2.$1";
$mplatest{$longname} = $currentOS;
$mpversions{$longname} .= ""; } elsif ($ref =~ /\/\/apple_ref\/doc\/legacyOS\/(.*?)\/man\/(.*?)\/(.*)/) {
my $longname = "$3.$2";
my $version = $1;
if ($version =~ /Xcode/i) {
print STDERR "$longname: DEVTOOLS\n" if ($localDebug);
$reftype{$longname}=1;
} else {
print STDERR "$longname: MOSX\n" if ($localDebug);
$reftype{$longname}=0; }
$mpversions{$longname} .= " $version";
if ((!$mplatest{$longname}) || (($mplatest{$longname} ne $currentOS) && ($mplatest{$longname} lt $version))) {
$mplatest{$longname} = $version;
}
}
}
foreach my $page (@manpageFramesetRefs) {
my $ref = $page->uid();
$ref =~ s/^"//;
$ref =~ s/"$//;
if ($ref =~ /\/\/apple_ref\/doc\/legacyOS\/(.*?)\/man\/(.*?)\/(.*)/) {
my $osvers = $1;
my $section = $2;
my $name = $3;
my $longname = "$name.$section";
if (($mplatest{$longname} ne $currentOS) && ($osvers eq $mplatest{$longname})) {
print STDERR "Pushing man page anyway because ".$mplatest{$longname}." ne ".$currentOS." && $osvers eq ".$mplatest{$longname}."\n" if ($localDebug);
print STDERR " UID: $ref OSVERS: $osvers SECTION: $2 NAME: $name LONGNAME: $longname\n" if ($localDebug);
push(@newmanpageFramesetRefs, $page);
}
} else {
my $ref = $page->uid();
$ref =~ s/^"//;
$ref =~ s/"$//;
print STDERR "Pushing base man page ".$page->uid()."\n" if ($localDebug);
if ($ref !~ /\/\/apple_ref\/doc\//) {
$page->hidden(1);
}
push(@newmanpageFramesetRefs, $page);
}
}
@manpageFramesetRefs = @newmanpageFramesetRefs;
foreach my $mpkey (keys(%mpversions)) {
my $outputDir = $inputDir;
print STDERR "MPL: ".$mplatest{$mpkey}."\n" if ($localDebug);
if ($mplatest{$mpkey} eq $currentOS) {
print STDERR "MPL: CURRENTOS\n" if ($localDebug);
if ($reftype{$mpkey}) {
$mpversions{$mpkey} .= " Xcode-".$currentXcode;
} else {
$mpversions{$mpkey} .= " ".$currentOS;
}
}
my $vs = $mpversions{$mpkey};
$vs =~ s/^ //;
my @versions = sort(split(/ /, $vs));
my $versiondir = $outputDir.$pathSeparator."versionlists";
my $versionfile = $versiondir.$pathSeparator.$mpkey.".versions.js";
if ( ! -d $versiondir ) {
mkdir($versiondir) || die("Could not create directory for version files.\n");
}
open(OUTFILE, ">$versionfile") || die("Could not write version files.\n");
print OUTFILE "var jsMPVersionsList = new Array();\n";
foreach my $version (@versions) {
print STDERR "CHECK: $version eq $currentXcode\n" if ($localDebug);
if (($version eq $currentOS) || ($version eq "Xcode-".$currentXcode)) {
print OUTFILE "jsMPVersionsList[\"$version\"] = { isCurrent: 1, isJSMPVersion: 1 };\n";
} else {
print OUTFILE "jsMPVersionsList[\"$version\"] = { isCurrent: 0, isJSMPVersion: 1 };\n";
}
}
print OUTFILE "\n";
close(OUTFILE);
if ($localDebug) {
print STDERR "FILE $mpkey\n";
print STDERR "VERSIONS:\n";
foreach my $version (@versions) {
print STDERR "\t$version\n";
}
print STDERR "\n";
}
}
}
if (scalar(@headerFramesetRefs) + scalar(@comintFramesetRefs) + scalar(@classFramesetRefs) + scalar(@manpageFramesetRefs) + scalar(@protocolFramesetRefs) + scalar(@categoryFramesetRefs) + scalar(@functionRefs)) {
if (!$skipTOC) {
print STDERR "Generating TOCs.\n";
&printMasterTOC();
&addTopLinkToFramesetTOCs();
} else {
print STDERR "Not generating landing pages because -n flag specified.\n";
}
if ($generateDocSet) {
print STDERR "Generating DocSet files suitable for use with docsetutil.\n";
generateDocSetFile($inputDir);
}
if (!$noResolve) {
if ($has_resolver) {
LinkResolver::resolveLinks($inputDir); } else {
resolveLinks($inputDir, $externalXRefFiles, $externalAPIUIDPrefixes);
}
} else {
print STDERR "Not running resolveLinks because -N flag specified.\n";
}
} else {
print STDERR "gatherHeaderDoc.pl: No HeaderDoc framesets found--returning\n" if ($debugging);
}
exit 0;
my $manPageMode = 0;
sub printMasterTOC {
my $outputDir = $inputDir;
my $masterTOC = $outputDir.$pathSeparator.$masterTOCFileName;
my %headersLinkString= ();
my %typeLinkString = ();
my %macroLinkString = ();
my %propLinkString = ();
my %dataLinkString = ();
my %comintsLinkString = ();
my %classesLinkString = ();
my %manpagesLinkString = ();
my %protocolsLinkString = ();
my %categoriesLinkString = ();
my %functionsLinkString = ();
my $seenHeaders = 0;
my $seenType = 0;
my $seenProp = 0;
my $seenData = 0;
my $seenMacros = 0;
my $seenClasses = 0;
my $seenComInts = 0;
my $seenManPages = 0;
my $seenProtocols = 0;
my $seenCategories = 0;
my $seenFunctions = 0;
my $localDebug = 0;
my %tempgroups = %groups;
$tempgroups{"hd_master_letters_linked"} = "";
my $template_number = 0;
foreach my $TOCTemplate (@TOCTemplateList) {
%letters_linked = (); my %used = %{$usedInTemplate{$TOCTemplate}};
my @templatefields = split(/\$\$/, $TOCTemplate);
my $templatefilename = $TOCNames[$template_number];
my $templatename = $templatefilename;
if ($templatename eq "HEADERDOC_DEFAULT_INTERNAL_TEMPLATE") {
print STDERR "Writing output file using default internal template.\n";
} else {
print STDERR "Writing output file for template \"$templatename\"\n";
}
if ($localDebug) {
print STDERR "Contains header list: ".($used{header} ? 1 : 0)."\n";
print STDERR "Contains type list: ".($used{type} ? 1 : 0)."\n";
print STDERR "Contains property list: ".($used{prop} ? 1 : 0)."\n";
print STDERR "Contains data list: ".($used{data} ? 1 : 0)."\n";
print STDERR "Contains function list: ".($used{function} ? 1 : 0)."\n";
print STDERR "Contains man page list: ".($used{manpage} ? 1 : 0)."\n";
print STDERR "Contains macro list: ".($used{macro} ? 1 : 0)."\n";
print STDERR "Contains protocol list: ".($used{protocol} ? 1 : 0)."\n";
print STDERR "Contains category list: ".($used{category} ? 1 : 0)."\n";
print STDERR "Contains class list: ".($used{class} ? 1 : 0)."\n";
print STDERR "Contains COM Interface list: ".($used{comint} ? 1 : 0)."\n";
print STDERR "\n";
}
foreach my $group (groupsort(keys (%tempgroups))) {
print STDERR "processing group $group\n" if ($localDebug);
%letters_linked = (); $headersLinkString{$group} = "";
$typeLinkString{$group} = "";
$propLinkString{$group} = "";
$dataLinkString{$group} = "";
$comintsLinkString{$group} = "";
$classesLinkString{$group} = "";
$manpagesLinkString{$group} = "";
$protocolsLinkString{$group} = "";
$categoriesLinkString{$group} = "";
$functionsLinkString{$group} = "";
if ($used{header}) {
foreach my $ref (sort objName @headerFramesetRefs) {
my $name = $ref->name();
my $path = $ref->path();
if ($ref->group() ne $group) {
next;
}
if ($stripDotH) {
$name =~ s/\.h$//;
}
my $tmpString = &getLinkToFramesetFrom($masterTOC, $path, $name, $group, "header", "");
$headersLinkString{$group} .= $tmpString; $seenHeaders = 1;
}
print STDERR "\$headersLinkString is '".$headersLinkString{$group}."'\n" if ($localDebug);
} else { $seenHeaders = scalar @headerFramesetRefs; }
my $groupns = $group;
$groupns =~ s/\s/_/sg;
{
my %temp_letters_linked = %letters_linked;
my $grouptype = $groupns."_header";
print STDERR "inserting into \"$grouptype\"\n" if ($localDebug);
$group_letters_linked{$grouptype} = \%temp_letters_linked;
%letters_linked = ();
}
if ($used{macro}) {
foreach my $ref (sort objName @macroFramesetRefs) {
my $name = $ref->name();
my $path = $ref->path();
my $uid = $ref->uid();
if ($ref->group() ne $group) { next; }
my $tmpString = &getLinkToFunctionFrom($masterTOC, $path, $name, $uid, $group, "macro");
$macroLinkString{$group} .= $tmpString; $seenMacros = 1;
}
if (($localDebug) && length($macroLinkString{$group})) {print STDERR "\$macroLinkString is '".$macroLinkString{$group}."'\n";};
} else { $seenMacros = scalar @macroFramesetRefs; }
{
my %temp_letters_linked = %letters_linked;
my $grouptype = $groupns."_macro";
print STDERR "inserting into \"$grouptype\" count ".scalar(keys %letters_linked)."\n" if ($localDebug);
$group_letters_linked{$grouptype} = \%temp_letters_linked;
%letters_linked = ();
}
if ($localDebug) {
print STDERR "BLANKLIST: ";
foreach my $name (keys %letters_linked) {
print STDERR "$name "
}
print STDERR "ENDLIST\n";
}
if ($used{data}) {
foreach my $ref (sort objName @dataFramesetRefs) {
my $name = $ref->name();
my $path = $ref->path();
my $uid = $ref->uid();
if ($ref->group() ne $group) {
print STDERR "Not adding \"$name\" because GROUP \"".$ref->group()."\" ne \"$group\".\n" if ($localDebug);
next;
}
print STDERR "Adding \"$name\".\n" if ($localDebug);
my $tmpString = &getLinkToFunctionFrom($masterTOC, $path, $name, $uid, $group, "data");
$dataLinkString{$group} .= $tmpString; $seenData = 1;
}
if (($localDebug) && length($dataLinkString{$group})) {print STDERR "\$dataLinkString is '".$dataLinkString{$group}."'\n";};
} else { $seenData = scalar @dataFramesetRefs; }
if ($localDebug) {
print STDERR "BLANKLIST: ";
foreach my $name (keys %letters_linked) {
print STDERR "$name "
}
print STDERR "ENDLIST\n";
}
if ($used{prop}) {
foreach my $ref (sort objName @propFramesetRefs) {
my $name = $ref->name();
my $path = $ref->path();
my $uid = $ref->uid();
if ($ref->group() ne $group) {
print STDERR "Not adding \"$name\" because GROUP \"".$ref->group()."\" ne \"$group\".\n" if ($localDebug);
next;
}
print STDERR "Adding \"$name\".\n" if ($localDebug);
my $tmpString = &getLinkToFunctionFrom($masterTOC, $path, $name, $uid, $group, "prop");
$propLinkString{$group} .= $tmpString; $seenProp = 1;
}
if (($localDebug) && length($propLinkString{$group})) {print STDERR "\$propLinkString is '".$propLinkString{$group}."'\n";};
} else { $seenProp = scalar @propFramesetRefs; }
{
my %temp_letters_linked = %letters_linked;
my $grouptype = $groupns."_data";
print STDERR "inserting into \"$grouptype\"\n" if ($localDebug);
$group_letters_linked{$grouptype} = \%temp_letters_linked;
if ($localDebug) {
print STDERR "LIST: ";
foreach my $name (keys %letters_linked) {
print STDERR "$name "
}
print STDERR "ENDLIST\n";
}
%letters_linked = ();
}
if ($used{type}) {
foreach my $ref (sort objName @typeFramesetRefs) {
my $name = $ref->name();
my $path = $ref->path();
my $uid = $ref->uid();
if ($ref->group() ne $group) { next; }
my $tmpString = &getLinkToFunctionFrom($masterTOC, $path, $name, $uid, $group, "type");
$typeLinkString{$group} .= $tmpString; $seenType = 1;
}
if (($localDebug) && length($typeLinkString{$group})) {print STDERR "\$typeLinkString is '".$typeLinkString{$group}."'\n";};
} else { $seenType = scalar @typeFramesetRefs; }
{
my %temp_letters_linked = %letters_linked;
my $grouptype = $groupns."_type";
print STDERR "inserting into \"$grouptype\"\n" if ($localDebug);
$group_letters_linked{$grouptype} = \%temp_letters_linked;
%letters_linked = ();
}
if ($used{manpage}) {
foreach my $ref (sort objName @manpageFramesetRefs) {
my $name = $ref->name();
my $path = $ref->path();
if ($ref->group() ne $group && $group ne "hd_master_letters_linked") { next; }
if ($ref->hidden()) { next; }
if (!$ref->mansrc()) {
warn "NO SRC FOR ".$ref->name()." path ".$ref->path()."\n";
}
my $tmpString = &getLinkToFramesetFrom($masterTOC, $path, $name, $group, "man", $ref->mansrc());
$manpagesLinkString{$group} .= $tmpString; $seenManPages = 1; $manPageMode = 1;
}
if (($localDebug) && length($manpagesLinkString{$group})) {print STDERR "\$manpagesLinkString is '".$manpagesLinkString{$group}."'\n";};
} else { $seenManPages = scalar @manpageFramesetRefs; }
{
my %temp_letters_linked = %letters_linked;
my $grouptype = $groupns."_man";
print STDERR "inserting into \"$grouptype\"\n" if ($localDebug);
$group_letters_linked{$grouptype} = \%temp_letters_linked;
%letters_linked = ();
}
if ($used{comint}) {
foreach my $ref (sort objName @comintFramesetRefs) {
my $name = $ref->name();
my $path = $ref->path();
if ($ref->group() ne $group) { next; }
my $tmpString = &getLinkToFramesetFrom($masterTOC, $path, $name, $group, "comint", "");
$comintsLinkString{$group} .= $tmpString; $seenComInts = 1;
}
if (($localDebug) && length($comintsLinkString{$group})) {print STDERR "\$comintsLinkString is '".$comintsLinkString{$group}."'\n";};
} else { $seenComInts = scalar @comintFramesetRefs; }
{
my %temp_letters_linked = %letters_linked;
my $grouptype = $groupns."_comint";
print STDERR "inserting into \"$grouptype\"\n" if ($localDebug);
$group_letters_linked{$grouptype} = \%temp_letters_linked;
%letters_linked = ();
}
if ($used{class}) {
foreach my $ref (sort objName @classFramesetRefs) {
my $name = $ref->name();
my $path = $ref->path();
if ($ref->group() ne $group) { next; }
my $tmpString = &getLinkToFramesetFrom($masterTOC, $path, $name, $group, "class", "");
$classesLinkString{$group} .= $tmpString; $seenClasses = 1;
}
if (($localDebug) && length($classesLinkString{$group})) {print STDERR "\$classesLinkString is '".$classesLinkString{$group}."'\n";};
} else { $seenClasses = scalar @classFramesetRefs; }
{
my %temp_letters_linked = %letters_linked;
my $grouptype = $groupns."_class";
print STDERR "inserting into \"$grouptype\"\n" if ($localDebug);
$group_letters_linked{$grouptype} = \%temp_letters_linked;
%letters_linked = ();
}
if ($used{protocol}) {
foreach my $ref (sort objName @protocolFramesetRefs) {
my $name = $ref->name();
my $path = $ref->path();
if ($ref->group() ne $group) { next; }
my $tmpString = &getLinkToFramesetFrom($masterTOC, $path, $name, $group, "protocol", "");
$protocolsLinkString{$group} .= $tmpString; $seenProtocols = 1;
}
if (($localDebug) && length($protocolsLinkString{$group})) {print STDERR "\$protocolsLinkString is '".$protocolsLinkString{$group}."'\n";};
} else { $seenProtocols = scalar @protocolFramesetRefs; }
{
my %temp_letters_linked = %letters_linked;
my $grouptype = $groupns."_protocol";
print STDERR "inserting into \"$grouptype\"\n" if ($localDebug);
$group_letters_linked{$grouptype} = \%temp_letters_linked;
%letters_linked = ();
}
if ($used{category}) {
foreach my $ref (sort objName @categoryFramesetRefs) {
my $name = $ref->name();
my $path = $ref->path();
if ($ref->group() ne $group) { next; }
my $tmpString = &getLinkToFramesetFrom($masterTOC, $path, $name, $group, "category", "");
$categoriesLinkString{$group} .= $tmpString; $seenCategories = 1;
}
if (($localDebug) && length($categoriesLinkString{$group})) {print STDERR "\$categoriesLinkString is '".$categoriesLinkString{$group}."'\n";};
} else { $seenCategories = scalar @categoryFramesetRefs; }
{
my %temp_letters_linked = %letters_linked;
my $grouptype = $groupns."_category";
print STDERR "inserting into \"$grouptype\"\n" if ($localDebug);
$group_letters_linked{$grouptype} = \%temp_letters_linked;
%letters_linked = ();
}
if ($used{function}) {
foreach my $ref (sort objName @functionRefs) {
my $name = $ref->name();
my $path = $ref->path();
my $uid = $ref->uid();
if ($ref->group() ne $group) { next; }
my $tmpString = &getLinkToFunctionFrom($masterTOC, $path, $name, $uid, $group, "function");
$functionsLinkString{$group} .= $tmpString; $seenFunctions = 1;
}
if (($localDebug) && length($functionsLinkString{$group})) {print STDERR "\$functionsLinkString is '".$functionsLinkString{$group}."'\n";};
} else { $seenFunctions = scalar @functionRefs; }
{
my %temp_letters_linked = %letters_linked;
my $grouptype = $groupns."_function";
print STDERR "inserting into \"$grouptype\"\n" if ($localDebug);
$group_letters_linked{$grouptype} = \%temp_letters_linked;
%letters_linked = ();
}
}
my $localDebug = 0;
if ($localDebug) {
print STDERR "processing # $template_number\n";
print STDERR "NAME WAS $templatefilename\n";
}
$templatename =~ s/^\s*//s;
$templatename =~ s/\s*$//s;
$templatename =~ s/\.html$//s;
$templatename =~ s/\.tmpl$//s;
my $title = "$framework Documentation";
my $include_in_output = 1; my $first = 1; my $out = "";
foreach my $field (@templatefields) {
my $keep = $field;
SWITCH: {
($field =~ /^\s*title/) && do {
if ($include_in_output) {
$out .= $title;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*frameworkdiscussion/) && do {
if ($include_in_output) {
$out .= $frameworkdiscussion;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*frameworkabstract/) && do {
if ($include_in_output) {
$out .= $frameworkabstract;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*tocname/) && do {
my $tn = basename($masterTOC);
if ($include_in_output) {
$out .= "$tn";
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*frameworkrelatedsection/) && do {
if (!length($frameworkrelated)) {
$include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/frameworkrelatedsection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*frameworkrelatedlist/) && do {
$field =~ s/\@\@.*//s;
if ($include_in_output) {
$out .= relatedDocs($frameworkrelated, $field);
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*frameworkorheaderpathorrelatedsection/) && do {
if (!(length($frameworkpath) || length($frameworkrelated) || length($headerpath))) {
$include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/frameworkorheaderpathorrelatedsection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*headerpathsection/) && do {
if (!length($headerpath)) {
$include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/headerpathsection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*headerpath/) && do {
if ($include_in_output) {
$out .= "$headerpath";
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*frameworkpathsection/) && do {
if (!length($frameworkpath)) {
$include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/frameworkpathsection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*frameworkpath/) && do {
if ($include_in_output) {
$out .= "$frameworkpath";
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*frameworkdir/) && do {
if ($include_in_output) {
$out .= "$frameworkShortName";
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*frameworkuid/) && do {
if ($include_in_output) {
$out .= "<a name=\"$landingPageUID\" title=\"$framework\"></a>";
if ($landingPageFrameworkUID ne "") {
$out .= "<a name=\"$landingPageFrameworkUID\" title=\"$framework\"></a>";
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*framework/) && do {
if ($include_in_output) {
$out .= "$framework";
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*headersection/) && do {
if (!$seenHeaders) {
$include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/headersection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*headerlist/) && do {
if ($seenHeaders) {
$field =~ s/\@\@.*//s;
foreach my $group (groupsort(keys(%groups))) {
$out .= genTable($headersLinkString{$group}, $field, $group, "header");
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*manpagesection/) && do {
if (!$seenManPages) {
$include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/manpagesection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*grouplist/) && do {
$keep =~ s/.*?\@\@//s;
if ($include_in_output) {
$out .= groupList();
}
last SWITCH;
};
($field =~ /^\s*manpagelist/) && do {
if ($seenManPages) {
$field =~ s/\@\@.*//s;
if ($field =~ /^\s*manpagelist\s+nogroups\s+/) {
$out .= "<!-- manpage mark=start id=all -->";
$out .= genTable($manpagesLinkString{"hd_master_letters_linked"}, $field, "hd_master_letters_linked", "man", 0);
$out .= "<!-- manpage mark=end id=all -->";
} else {
foreach my $group (groupsort(keys(%groups))) {
if ($group =~ /\S/) {
my $group_id = $group;
$group_id =~ s/\s/_/s;
$group_id = "group_".$group_id;
$out .= "<!-- manpage mark=start id=$group_id -->";
$out .= genTable($manpagesLinkString{$group}, $field, $group, "man", 1);
$out .= "<!-- manpage mark=end id=$group_id -->";
}
}
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*oocontainersection/) && do {
if (!$seenComInts && !$seenClasses && !$seenCategories && !$seenProtocols) {
$include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/oocontainersection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*comintsection/) && do {
if (!$seenComInts) {
$include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/comintsection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*comintlist/) && do {
if ($seenComInts) {
$field =~ s/\@\@.*//s;
foreach my $group (groupsort(keys(%groups))) {
$out .= genTable($comintsLinkString{$group}, $field, $group, "comint");
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*classsection/) && do {
if (!$seenClasses) {
$include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/classsection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*classlist/) && do {
if ($seenClasses) {
$field =~ s/\@\@.*//s;
foreach my $group (groupsort(keys(%groups))) {
$out .= genTable($classesLinkString{$group}, $field, $group, "class");
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*categorysection/) && do {
if (!$seenCategories) { $include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/categorysection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*categorylist/) && do {
if ($seenCategories) {
$field =~ s/\@\@.*//s;
foreach my $group (groupsort(keys(%groups))) {
$out .= genTable($categoriesLinkString{$group}, $field, $group, "category");
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*protocolsection/) && do {
if (!$seenProtocols) { $include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/protocolsection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*protocollist/) && do {
if ($seenProtocols) {
$field =~ s/\@\@.*//s;
foreach my $group (groupsort(keys(%groups))) {
$out .= genTable($protocolsLinkString{$group}, $field, $group, "protocol");
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*macrosection/) && do {
if (!$seenMacros) {
$include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/macrosection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*macrolist/) && do {
if ($seenMacros) {
$field =~ s/\@\@.*//s;
foreach my $group (groupsort(keys(%groups))) {
$out .= genTable($macroLinkString{$group}, $field, $group, "macro");
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*propsection/) && do {
if (!$seenProp) { $include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/propsection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*proplist/) && do {
if ($seenProp) {
$field =~ s/\@\@.*//s;
foreach my $group (groupsort(keys(%groups))) {
$out .= genTable($propLinkString{$group}, $field, $group, "prop");
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*datasection/) && do {
if (!$seenData) { $include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/datasection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*datalist/) && do {
if ($seenData) {
$field =~ s/\@\@.*//s;
foreach my $group (groupsort(keys(%groups))) {
$out .= genTable($dataLinkString{$group}, $field, $group, "data");
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*typesection/) && do {
if (!$seenType) { $include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/typesection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*year/) && do {
$out .= $yearStamp;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*date/) && do {
$out .= $dateStamp;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*copyright/) && do {
if (length($frameworkCopyrightString)) {
my $temp = $frameworkCopyrightString;
$temp =~ s/\$\$year\@\@/\Q$yearStamp\E/g;
$temp =~ s/\$\$date\@\@/\Q$dateStamp\E/g;
$out .= $temp;
} else {
if ($HeaderDoc::copyrightOwner && length($HeaderDoc::copyrightOwner)) {
$out .= "© ".$yearStamp." ".$HeaderDoc::copyrightOwner
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*typelist/) && do {
if ($seenType) {
$field =~ s/\@\@.*//s;
foreach my $group (groupsort(keys(%groups))) {
$out .= genTable($typeLinkString{$group}, $field, $group, "type");
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*functionsection/) && do {
if (!$seenFunctions) { $include_in_output = 0;
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*\/functionsection/) && do {
$include_in_output = 1;
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
($field =~ /^\s*functionlist/) && do {
if ($seenFunctions) {
$field =~ s/\@\@.*//s;
foreach my $group (groupsort(keys(%groups))) {
$out .= genTable($functionsLinkString{$group}, $field, $group, "function");
}
}
$keep =~ s/.*?\@\@//s;
last SWITCH;
};
{
if ($first) { $first = 0; }
else { warn "Unknown field: \$\$$field\n"; $out .= "\$\$"; }
}
}
if ($include_in_output) { $out .= $keep; }
}
print STDERR "gatherHeaderDoc.pl: writing master TOC to $masterTOC\n" if ($localDebug);
if (!$template_number) {
open(OUTFILE, ">$masterTOC") || die "Can't write $masterTOC.\n";
} else {
open(OUTFILE, ">$outputDir$pathSeparator$frameworkShortName-$templatename.html") || die "Can't write $outputDir$pathSeparator$frameworkShortName-$templatename.html.\n";
}
print OUTFILE $out;
close OUTFILE;
++$template_number;
}
}
sub addTopLinkToFramesetTOCs {
my $masterTOC = $inputDir.$pathSeparator. $masterTOCFileName;
my $tocFileName = "toc.html";
my @allFramesetRefs;
push(@allFramesetRefs, @headerFramesetRefs);
push(@allFramesetRefs, @comintFramesetRefs);
push(@allFramesetRefs, @classFramesetRefs);
push(@allFramesetRefs, @protocolFramesetRefs);
push(@allFramesetRefs, @categoryFramesetRefs);
my $localDebug = 0;
foreach my $ref (@allFramesetRefs) {
my $name = $ref->name();
my $type = $ref->type();
my $path = $ref->path();
my $tocFile = $path; my $fsName = quotemeta($framesetFileName);
$tocFile =~ s/$fsName$/toc.html/;
if (-e "$tocFile" ) {
my $oldRecSep = $/;
undef $/; open(INFILE, "<$tocFile") || die "Can't read file $tocFile.\n";
my $fileString = <INFILE>;
close INFILE;
$/ = $oldRecSep;
my $uniqueMarker = "headerDoc=\"topLink\"";
my $newTOC = 0;
if ($fileString =~ /headerDoc TOC style: (\d+)\s*-->/) {
$newTOC = $1;
}
$HeaderDoc::newTOC = $newTOC;
my $relPathToMasterTOC = &findRelativePath($tocFile, $masterTOC);
my $breadcrumb_added = 0;
if ($fileString =~ /<!-- HeaderDoc TOC framework link begin -->.*<!-- HeaderDoc TOC framework link end -->/s) {
my $breadcrumb = "";
$breadcrumb_added = 1;
if ($newTOC) {
$breadcrumb .= HeaderDoc::APIOwner->tocEntry("$relPathToMasterTOC", "$framework", "_top");
} else {
$breadcrumb .= "<nobr> <a href=\"$relPathToMasterTOC\" target=\"_top\">$framework</a></nobr><br>\n";
}
$fileString =~ s/<!-- HeaderDoc TOC framework link begin -->.*<!-- HeaderDoc TOC framework link end -->/<!-- HeaderDoc TOC framework link begin -->$breadcrumb<!-- HeaderDoc TOC framework link end -->/s;
} elsif ($fileString =~ /<!-- HeaderDoc TOC framework link block begin -->.*<!-- HeaderDoc TOC framework link block end -->/s) {
my $breadcrumb = "";
$breadcrumb_added = 1;
if ($newTOC) {
$breadcrumb .= HeaderDoc::APIOwner->tocSeparator("Other Reference", $newTOC);
$breadcrumb .= HeaderDoc::APIOwner->tocEntry("$relPathToMasterTOC", "$framework", "_top");
} else {
$breadcrumb .= "<br><h4>Other Reference</h4><hr class=\"TOCSeparator\">\n";
$breadcrumb .= "<nobr> <a href=\"$relPathToMasterTOC\" target=\"_top\">$framework</a></nobr><br>\n";
}
$fileString =~ s/<!-- HeaderDoc TOC framework link block begin -->.*<!-- HeaderDoc TOC framework link block end -->/<!-- HeaderDoc TOC framework link block begin -->$breadcrumb<!-- HeaderDoc TOC framework link block end -->/s;
}
if ((($HeaderDoc::addTopLink && !$newTOC) || (!$breadcrumb_added)) && (!$useBreadcrumbs)) {
if ($fileString !~ /$uniqueMarker/) { my $relPathToMasterTOC = &findRelativePath($tocFile, $masterTOC);
my $topLink = "\n<font size=\"-2\"><a href=\"$relPathToMasterTOC\" target=\"_top\" $uniqueMarker>[Top]</a></font><br/>\n";
$fileString =~ s/(<body[^>]*>)/$1$topLink/i;
}
}
open (OUTFILE, ">$tocFile") || die "Can't write file $tocFile.\n";
print OUTFILE $fileString;
close (OUTFILE);
} elsif ($debugging) {
print STDERR "--> '$tocFile' doesn't exist!\n";
print STDERR "Cannot add [top] link for frameset doc reference:\n";
print STDERR " name: $name\n";
print STDERR " type: $type\n";
print STDERR " path: $path\n";
}
}
if ($useBreadcrumbs) {
foreach my $file (@contentFiles) {
if (-e "$file" && ! -d "$file" ) {
my $oldRecSep = $/;
undef $/; open(INFILE, "<$file") || die "Can't read file $file.\n";
my $fileString = <INFILE>;
close INFILE;
$/ = $oldRecSep;
my $uniqueMarker = "headerDoc=\"topLink\"";
if (length($framework)) {
my $relPathToMasterTOC = &findRelativePath($file, $masterTOC);
my $breadcrumb = "<a href=\"$relPathToMasterTOC\" $linktarget $uniqueMarker>$framework</a>";
$fileString =~ s/<!-- begin breadcrumb -->.*?<!-- end breadcrumb -->/<!-- begin breadcrumb -->$breadcrumb<!-- end breadcrumb -->/i;
open (OUTFILE, ">$file") || die "Can't write file $file.\n";
print OUTFILE $fileString;
close (OUTFILE);
} else {
warn "No framework (.hdoc) file found and breadcrumb specified. Breadcrumbs will\nnot be inserted.\n";
}
}
}
}
}
sub getLinkToFramesetFrom {
my $masterTOCFile = shift;
my $dest = shift;
my $name = shift;
my $group = shift;
my $typename = shift;
my $mansrc = shift;
my $linkString;
my %manPageTypes = (
"base" => "Mac OS X (client) manual page",
"server" => "Mac OS X Server manual page",
"devtools" => "Developer tools manual page",
"chud" => "CHUD (part of developer tools) manual page",
"internal" => "INTERNAL MANUAL PAGE"
);
my $maninsert = "";
if ($mansrc) {
$maninsert = "<span class=\"manpage_source_$mansrc\">•</span>";
$mansrc = " mansrc=\"$mansrc\" class=\"manpage_source_$mansrc\" title=\"".$manPageTypes{$mansrc}."\" ";
}
my $relPath = &findRelativePath($masterTOCFile, $dest);
my $namestring = getNameStringForLink($name, $group, $typename);
$linkString = "$maninsert<a $namestring href=\"$relPath\" $linktarget $mansrc>$name</a><br/>\n";
return $linkString;
}
sub getNameStringForLink
{
my $name = shift;
my $group = shift;
my $typename = shift;
my $namestring = "";
my $groupns = $group;
$groupns =~ s/\s/_/sg;
my $grouptype = $groupns."_".$typename;
my $firsttwo = uc($name);
$firsttwo =~ s/^(..).*$/$1/s;
if (!$letters_linked{$firsttwo}) {
$namestring = "name=\"group_$grouptype"."_$firsttwo\"";
$letters_linked{$firsttwo} = 1;
} else {
$letters_linked{$firsttwo}++;
}
return $namestring;
}
sub getLinkToFunctionFrom {
my $masterTOCFile = shift;
my $dest = shift;
my $name = shift;
my $uid = shift;
my $group = shift;
my $typename = shift;
my $linkString;
$uid =~ s/^"//;
$uid =~ s/"$//;
my $relPath = &findRelativePath($masterTOCFile, $dest);
my $ns = getNameStringForLink($name, $group, $typename);
my $noClassName = $name;
$noClassName =~ s/.*\:\://s;
my $urlname = sanitize($noClassName);
my $lp = "";
if ($uid && length($uid)) {
$urlname = $uid;
$lp = " logicalPath=\"$uid\"";
}
if ($uid =~ /\/\/apple_ref\/occ\/(clm|instm|intfcm|intfm)\//) {
my $type = $1;
$name =~ s/^(.*)\:\://;
my $class = $1;
my $plusmin = "+";
if ($type eq "instm") {
$plusmin = "-";
}
$name = $plusmin."[ $class $name ]";
}
$linkString = "<a $lp $ns href=\"$relPath#$urlname\" retarget=\"yes\" $linktarget>$name</a><br/>\n";
return $linkString;
}
sub objName { uc($a->name()) cmp uc($b->name());
}
sub default_template
{
my $template = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\n \"http://www.w3.org/TR/1998/REC-html40-19980424/loose.dtd\">\n";
my $stylesheet = "";
$template .= "<html>\n<head>\n <title>\$\$title\@\@</title>\n <meta name=\"generator\" content=\"HeaderDoc\" />\n <meta name=\"formatter\" content=\"gatherHeaderDoc\" />\n <meta name=\"xcode-display\" content=\"render\" />\n$stylesheet</head>\n<body bgcolor=\"$GHD::bgcolor\"><h1>\$\$framework\@\@ Documentation</h1><hr/><br/>\n";
$template .= "<p>\$\$frameworkdiscussion\@\@</p>";
$template .= "\$\$headersection\@\@<h2>Headers</h2>\n<blockquote>\n\$\$headerlist cols=2 order=down atts=border=\"0\" width=\"80%\"\@\@\n</blockquote>\$\$/headersection\@\@\n";
$template .= "\$\$classsection\@\@<h2>Classes</h2>\n<blockquote>\n\$\$classlist cols=2 order=down atts=border=\"0\" width=\"80%\"\@\@\n</blockquote>\$\$/classsection\@\@\n";
$template .= "\$\$categorysection\@\@<h2>Categories</h2>\n<blockquote>\n\$\$categorylist cols=2 order=down atts=border=\"0\" width=\"80%\"\@\@\n</blockquote>\$\$/categorysection\@\@\n";
$template .= "\$\$protocolsection\@\@<h2>Protocols</h2>\n<blockquote>\n\$\$protocollist cols=2 order=down atts=border=\"0\" width=\"80%\"\@\@\n</blockquote>\$\$/protocolsection\@\@\n";
$template .= "\$\$functionsection\@\@<h2>Functions</h2>\n<blockquote>\n\$\$functionlist cols=2 order=down atts=border=\"0\" width=\"80%\"\@\@\n</blockquote>\$\$/functionsection\@\@\n";
$template .= "\$\$typesection\@\@<h2>Data Types</h2>\n<blockquote>\n\$\$typelist cols=2 order=down atts=border=\"0\" width=\"80%\"\@\@\n</blockquote>\$\$/typesection\@\@\n";
$template .= "\$\$datasection\@\@<h2>Globals and Constants</h2>\n<blockquote>\n\$\$datalist cols=2 order=down atts=border=\"0\" width=\"80%\"\@\@\n</blockquote>\$\$/datasection\@\@\n";
$template .= "\$\$propsection\@\@<h2>Globals and Constants</h2>\n<blockquote>\n\$\$proplist cols=2 order=down atts=border=\"0\" width=\"80%\"\@\@\n</blockquote>\$\$/propsection\@\@\n";
$template .= "\$\$copyright\@\@\n";
$template .= "</body>\n</html>\n";
$gather_globals_and_constants = 1;
$gather_types = 1;
$gather_functions = 1;
return $template;
}
sub gethierlinkstring
{
my $group = shift;
my $linkletter = shift;
my $letter = shift;
my $typename = shift;
my $optional_last = "";
if (@_) {
$optional_last = shift;
$optional_last = "-$optional_last";
} elsif ($letter =~ /../) {
$optional_last = $letter;
$optional_last =~ s/(.)./$1Z/s;
$optional_last = "-$optional_last";
}
my $groupns = $group;
$groupns =~ s/\s/_/sg;
my $grouptype = $groupns."_".$typename;
return "<a href=\"#group_$grouptype"."_$linkletter\">$letter$optional_last</a>";
}
sub genTable
{
my $inputstring = shift;
my $settings = shift;
my $groupname = shift;
my $typename = shift;
my $isman = 0;
if (@_) {
$isman = shift;
}
my $ncols = 0;
my $order = "down";
my $attributes = "border=\"0\" width=\"100%\"";
my $tdclass = "";
my $trclass = "";
my $localDebug = 0;
my $addempty = 0;
my $notable = 0;
print STDERR "genTable(IS: [omitted], SET: $settings, GN: $groupname, TN: $typename, IM: $isman)\n" if ($localDebug);
my $mansectiontext = "";
if ($isman) {
my $mansectionname = $groupname;
$mansectionname =~ s/^\s*Section\s+//s;
my $filename="sectiondesc/man$mansectionname".".html";
if (open(SECTIONTEXT, "<$filename")) {
my $lastrs = $/;
$/ = undef;
$mansectiontext = <SECTIONTEXT>;
$/ = $lastrs;
close(SECTIONTEXT);
} else {
warn "No file for man section $mansectionname\n";
}
}
if (!defined($inputstring)) { return ""; }
my @lines = split(/\n/, $inputstring);
my $nlines = scalar(@lines);
my $addHierarchicalLinks = 0;
my $hierstring = "";
if ($HeaderDoc::groupHierLimit && ($nlines > $HeaderDoc::groupHierLimit)) {
$addHierarchicalLinks = 1;
my $splitparts = 0;
my $attempts = 0;
my $subgroupLimit = $HeaderDoc::groupHierSubgroupLimit;
my $minsplit = 5;
while ($splitparts < $minsplit && $attempts < 5) {
my $linkletter = "";
my $prevletter = "";
my $prevtwoletter = "";
$splitparts = 0; $hierstring = "<blockquote class='letterlist'><table width='80%'><tr><td>\n";
print STDERR "GROUPNAME: $groupname\n" if ($localDebug);
my $groupns = $groupname;
$groupns =~ s/\s/_/sg;
my $grouptype = $groupns."_".$typename;
print STDERR "GROUPTYPE: \"$grouptype\"\n" if ($localDebug);
my %twoletterlinkcounts = %{$group_letters_linked{$grouptype}};
print STDERR "GLLCHECK: ".scalar(keys %{$group_letters_linked{$grouptype}})."\n" if ($localDebug);
my %oneletterlinkcounts = ();
foreach my $twoletter (sort keys %twoletterlinkcounts) {
my $firstletter = $twoletter;
$firstletter =~ s/^(.).*$/$1/s;
if (!$oneletterlinkcounts{$firstletter}) {
$oneletterlinkcounts{$firstletter} = $twoletterlinkcounts{$twoletter};
if ($prevletter ne "") {
$hierstring .= gethierlinkstring($groupname, $linkletter, $prevletter, $typename)." <span class='hierpipe'>|</span> \n";
}
$prevletter = $firstletter;
$linkletter = $twoletter;
$splitparts++;
} elsif ($oneletterlinkcounts{$firstletter} + $twoletterlinkcounts{$twoletter} > $subgroupLimit) {
$hierstring .= gethierlinkstring($groupname, $linkletter, $prevletter, $typename, $prevtwoletter)." <span class='hierpipe'>|</span> \n";
$prevletter = $twoletter;
$linkletter = $twoletter;
$splitparts++;
}
$prevtwoletter = $twoletter;
}
if ($prevletter ne "") {
$hierstring .= gethierlinkstring($groupname, $linkletter, $prevletter, $typename);
}
$hierstring .= "</td></tr></table></blockquote>\n";
if ($splitparts < $minsplit) {
print STDERR "Minimum split count $minsplit not reached. Split count was $splitparts. Reducing split count.\n" if ($localDebug);
$subgroupLimit = $subgroupLimit / $minsplit;
}
$attempts++;
}
print STDERR "SPLITPARTS: $splitparts\n" if ($localDebug);
if ($splitparts <= 1) {
print STDERR "Could not split list at all. Dropping singleton.\n" if ($localDebug);
$hierstring = ""; }
}
my $ngroups = scalar(keys(%groups));
my $groupnamestring = "";
if ($groupname =~ /\S/) {
my $groupnospc = $groupname;
$groupnospc =~ s/\s/_/sg;
$groupnamestring = "<p class='groupname'><a name='group_$groupnospc'></a><i>$groupname</i></p>\n";
}
if ($groupname eq "hd_master_letters_linked") { $groupnamestring = ""; }
my $groupheadstring = "<blockquote class='groupindent'>\n";
my $grouptailstring = "</blockquote>\n";
if (!$ngroups) {
$groupheadstring = "";
$grouptailstring = "";
}
$settings =~ s/^\s*(\w+list)\s*//;
my $name = $1;
if ($settings =~ s/^nogroups\s+//) {
$ngroups = 0;
}
if ($settings =~ s/^cols=(\d+)\s+//) {
$ncols = $1;
}
if ($settings =~ s/^order=(\w+)\s+//) {
$order = $1;
if (!$ncols) { $ncols = 1; }
}
if ($settings =~ s/^trclass=(\w+)\s+//) {
$trclass = " class=\"$1\"";
if (!$ncols) { $ncols = 1; }
}
if ($settings =~ s/^tdclass=(\w+)\s+//) {
$tdclass = " class=\"$1\"";
if (!$ncols) { $ncols = 1; }
}
if ($settings =~ s/^notable//) {
$notable = 1; $ncols = 1;
}
if ($settings =~ s/^addempty=(\d+)//) {
$addempty = $1;
}
if ($settings =~ s/^atts=//) {
$attributes = $settings;
$settings = "";
if (!$ncols) { $ncols = 1; }
}
if ($ncols) {
if (!$nlines) { return ""; }
my @columns = ();
my $loopindex = $ncols;
while ($loopindex--) {
my @column = ();
push(@columns, \@column);
}
my $curcolumn = 0; my $curline = 0;
my $lines_per_column = int(($nlines + $ncols - 1) / $ncols);
my $blanks = ($lines_per_column * $ncols) - $nlines;
$nlines += $blanks;
while ($blanks) {
push(@lines, "");
$blanks--;
}
warn "NLINES: $nlines\n" if ($localDebug);
warn "Lines per column: $lines_per_column\n" if ($localDebug);
foreach my $line (@lines) {
warn "columns[$curcolumn] : adding line\n" if ($localDebug);
my $columnref = $columns[$curcolumn];
push(@{$columnref}, $line);
$curline++;
if ($order eq "across") {
$curcolumn = ($curcolumn + 1) % $ncols;
} elsif ($curline >= $lines_per_column) {
$curline = 0; $curcolumn++;
}
}
if ($localDebug) {
$loopindex = 0;
while ($loopindex < $ncols) {
warn "Column ".$loopindex.":\n";
foreach my $line (@{$columns[$loopindex]}) {
warn "$line\n";
}
$loopindex++;
}
}
my $outstring = "";
if (!$notable) { $outstring .= "<table $attributes>"; }
$curline = 0;
$curcolumn = 0;
my $currow = 0;
my $first = 1;
while ($curline < $nlines) {
if (!$curcolumn) {
if ($first) {
$first = 0;
if (!$notable) { $outstring .= "<tr$trclass>"; }
} else {
if (!$notable) { $outstring .= "</tr><tr>\n"; }
$currow++;
}
} else {
if ($addempty) {
if (!$notable) { $outstring .= "<td width=\"$addempty\"$tdclass> </td>\n"; }
}
}
my $line = ${$columns[$curcolumn]}[$currow];
my $val = floor(100/$ncols);
if ($notable) {
$outstring .= "$line<br>\n";
} else {
$outstring .= "<td$tdclass width=\"" . $val . "\%\">$line</td>\n";
}
$curline++;
$curcolumn = ($curcolumn + 1) % $ncols;
}
if (!$notable) { $outstring .= "</tr></table>\n"; }
return $groupnamestring.$mansectiontext.$hierstring.$groupheadstring.$outstring.$grouptailstring;
} else {
return $groupnamestring.$mansectiontext.$hierstring.$groupheadstring.$inputstring.$grouptailstring;
}
}
sub pathparts
{
my $string = shift;
my $count = 0;
while ($string =~ s/\///) { $count++; }
return $count;
}
sub rightframework
{
my $filename = shift;
my $count = pathparts($filename);
if ($frameworknestlevel == -1) {
$frameworknestlevel = $count;
return 1;
}
if ($frameworknestlevel < $count) {
return 0;
}
return 1;
}
sub docListFromString
{
my $string = shift;
my @parts = split(/<!--/, $string);
my @list = ();
my $lastpath = "";
foreach my $part (@parts) {
if ($part =~ s/^\s*a logicalPath="//s) {
# print STDERR "PART $part\n";
my @subparts = split(/\"/, $part, 2);
my $uid = $subparts[0];
my $name = $subparts[1];
$name =~ s/^\s*-->//s;
my $string = "<!-- a logicalPath=\"$uid\" -->$name<!-- /a -->\n";
push(@list, $string);
}
}
return @list;
}
# /*!
# @abstract
# Takes a string containing link requests and returns a single-column
# table containing only the link requests.
# @param inputstring
# The input string.
# @param field
# Passed as the "settings" argument to {@link genTable}.
# */
sub relatedDocs
{
my $inputstring = shift;
my $field = shift;
my $retstring = "";
my $tmpstring = "";
if (length($inputstring)) {
my @lines = docListFromString($inputstring);
foreach my $line (@lines) {
# print STDERR "LINE IS \"$line\"\n";
if (length($line)) {
$tmpstring .= $line . "\n";
}
}
$tmpstring =~ s/\n$//s;
$retstring .= genTable($tmpstring, $field, "", "");
}
return $retstring;
}
# /*!
# @abstract
# Returns a list of links to <code>\@indexgroup</code> groups
# within the TOC.
# */
sub groupList
{
my $string = "";
my $first = 1;
my @list = groupsort(keys(%groups));
foreach my $group (@list) {
if ($group !~ /\S/) { next; }
if ($first) { $first = 0; }
else { $string .= " <span class='sectpipe'>|</span> \n"; }
my $groupnospc = $group;
$groupnospc =~ s/\s/_/sg;
my $groupnobr = $group;
$groupnobr =~ s/\s/ /sg;
$string .= "<a href=\" }
return $string;
}
sub printll
{
my $arrayref = shift;
my $group = shift;
my %arr = %{$arrayref};
print STDERR "FOR GROUP \"$group\"\n";
foreach my $key (sort keys %arr) {
print STDERR "$key\n";
}
print STDERR "\n";
}
sub generateDocSetFile
{
my $outputDir = shift;
my $masterTOCFile = $outputDir.$pathSeparator.$masterTOCFileName;
open(OUTFILE, ">$inputDir/Nodes.xml") || die("Could not write Nodes.xml file.\n");
print OUTFILE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print OUTFILE "<DocSetNodes version=\"1.0\">\n";
print OUTFILE " <TOC>\n";
print OUTFILE " <Node type=\"file\">\n";
print OUTFILE " <Name>$framework</Name>\n";
print OUTFILE " <Path>$masterTOCFileName</Path>\n";
print OUTFILE " </Node>\n";
print OUTFILE " </TOC>\n";
print OUTFILE "</DocSetNodes>\n";
close(OUTFILE);
open(OUTFILE, ">$inputDir/Tokens.xml") || die("Could not write Tokens.xml file.\n");
print OUTFILE "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print OUTFILE "<Tokens version=\"1.0\">\n";
my %refToObj = ();
my %refToRelpath = ();
my %allRelatedRefs = ();
foreach my $header (@fileRefSets) {
my $path = $header->path();
my $relPath = &findRelativePath($masterTOCFile, $path);
my $arrayRef = $header->group();
my @refs = @{$arrayRef};
foreach my $ref (@refs) {
my $uid = $ref->uid();
$uid =~ s/^"//;
$uid =~ s/"$//;
my $keep = 1;
if ($refToObj{$uid}) {
$keep = chooseBest($refToObj{$uid}, $ref, $uid);
}
if ($keep) {
$refToObj{$uid} = $ref;
$refToRelpath{$uid} = $relPath;
}
}
}
foreach my $uid (sort keys %refToObj) {
my $ref = $refToObj{$uid};
my $relPath = $refToRelpath{$uid};
if ($uid =~ /\/\/apple_ref\/doc\//) { next; }
print OUTFILE "<Token>\n";
print OUTFILE " <TokenIdentifier>$uid</TokenIdentifier>\n";
print OUTFILE " <Path>$relPath</Path>\n";
my $abs = XMLTokenAbstract($ref);
print OUTFILE " <Abstract>$abs</Abstract>\n";
my $dec = textToXML($ref->declaration());
if ($dec) {
print OUTFILE " <Declaration>$dec</Declaration>\n";
}
my @relatedrefs = $ref->seealso();
if (scalar(@relatedrefs)) {
print OUTFILE " <RelatedTokens>\n";
foreach my $ref (@relatedrefs) {
print OUTFILE " <TokenIdentifier>$ref</TokenIdentifier>\n";
$allRelatedRefs{$ref} = $ref;
}
print OUTFILE " </RelatedTokens>\n";
}
print OUTFILE "</Token>\n";
}
foreach my $ref (sort keys %allRelatedRefs) {
my $refobj = $refToObj{$ref};
my $title = XMLTokenAbstract($refobj);
print OUTFILE " <RelatedTokens title=\"$title\">\n";
print OUTFILE " <TokenIdentifier>$ref</TokenIdentifier>\n";
print OUTFILE " </RelatedTokens>\n";
}
print OUTFILE "</Tokens>\n";
close(OUTFILE);
}
sub groupsort(@)
{
my @arr = @_;
if ($manPageMode) {
my @resorted = ();
my $seenLegacy = 0;
foreach my $group (sort @arr) {
if ($group eq "Section legacy") {
$seenLegacy = 1;
} else {
push(@resorted, $group);
}
}
if ($seenLegacy) {
push(@resorted, "Section legacy");
}
return @resorted;
} else {
return sort @arr;
}
}
sub textToXML
{
my $textdata = shift;
$textdata =~ s/&/&/sgo;
$textdata =~ s/</</sgo;
$textdata =~ s/>/>/sgo;
return $textdata;
}
sub XMLTokenAbstract
{
my $ref = shift;
my $abs = stripTags($ref->abstract());
$abs =~ s/\s+/ /sg;
$abs =~ s/"/"/sg;
if ($abs) {
return $abs;
} else {
# Punt and use the discussion
my $disc = stripTags($ref->discussion());
# Strip leading newlines.
$disc =~ s/^[\n\r]*//s;
# Limit to one paragraph.
$disc =~ s/\n\n.*$//s;
if ($disc) {
return $disc;
}
}
return "";
}
# /*!
# @abstract
# Chooses the best object for a UID.
# @discussion
# Used by the doc set generation code to choose which HTML file to
# associate with a given apple_ref in the event of a conflict.
#
# This is primarily used when generating manual page content because
# multiple manual pages often describe the same functions. In
# general, apple_ref tags should always be unique. Do not rely
# on this logic remaining as it is today.
# @param firstObj
# The first {@link //apple_ref/perl/cl/HeaderDoc::DocReference DocReference} object to compare.
# @param secondObj
# The second {@link //apple_ref/perl/cl/HeaderDoc::DocReference DocReference} object to compare.
# @param uid
# The uid in question.
# */
sub chooseBest($$$)
{
my $firstObj = shift;
my $secondObj = shift;
my $uid = shift;
my $localDebug = 0;
my @uidparts = split(/\//, $uid);
my $count = scalar(@uidparts);
my $pos = $count;
# There are 2 bogus leading parts due to the leading //.
if ($count == 2 + 7) {
# e.g. intfm, instm, clm, etc. w/ signature and return type
$pos = $count - 2;
# } elsif ($count == 2 + 5) {
# e.g. structs and vars in classes, etc.
# $pos = $count;
}
my $name = $uidparts[$count - 1];
# For example, foo matches blah/foo.html first.
if ($firstObj->path =~ /\/\Q$name\E\./) {
warnRetCause($uid, $firstObj, $secondObj, "$name is ideal (/$name\./).") if ($localDebug);
return $firstObj;
}
if ($secondObj->path =~ /\/\Q$name\E\./) {
warnRetCause($uid, $secondObj, $firstObj, "$name is ideal (/$name\./).") if ($localDebug);
return $secondObj;
}
# For example, foo matches blah/foo or blah/foo/ next.
if ($firstObj->path =~ /\/\Q$name\E(\/|$)/) {
warnRetCause($uid, $firstObj, $secondObj, "$name is a path component (\/$name\/).") if ($localDebug);
return $firstObj;
}
if ($secondObj->path =~ /\/\Q$name\E(\/|$)/) {
warnRetCause($uid, $secondObj, $firstObj, "$name is a path component (\/$name\/).") if ($localDebug);
return $secondObj;
}
# Check on any arbitrary word boundaries next.
if ($firstObj->path =~ /\b\Q$name\E\b/) {
warnRetCause($uid, $firstObj, $secondObj, "$name is between word boundaries.") if ($localDebug);
return $firstObj;
}
if ($secondObj->path =~ /\b\Q$name\E\b/) {
warnRetCause($uid, $secondObj, $firstObj, "$name is between word boundaries.") if ($localDebug);
return $secondObj;
}
# Check on a leading word boundary next.
if ($firstObj->path =~ /\b\Q$name\E/) {
warnRetCause($uid, $firstObj, $secondObj, "$name starts at a word boundary (with trailing garbage).") if ($localDebug);
return $firstObj;
}
if ($secondObj->path =~ /\b\Q$name\E/) {
warnRetCause($uid, $secondObj, $firstObj, "$name starts at a word boundary (with trailing garbage).") if ($localDebug);
return $secondObj;
}
# Check anywhere in the path.
if ($firstObj->path =~ /\Q$name\E/) {
warnRetCause($uid, $firstObj, $secondObj, "$name is in the path.") if ($localDebug);
return $firstObj;
}
if ($secondObj->path =~ /\Q$name\E/) {
warnRetCause($uid, $secondObj, $firstObj, "$name is in the path.") if ($localDebug);
return $secondObj;
}
# Punt
warn("Punting\n") if ($localDebug);
return $firstObj;
}
# /*!
# @abstract
# Helper function to simplify warning code used for debugging
# {@link chooseBest}.
# */
sub warnRetCause($$$)
{
my $uid = shift;
my $obj = shift;
my $overobj = shift;
my $reason = shift;
warn("Chose ".$obj->path()." ($obj) over ".$overobj->path()." ($overobj) for $uid because $reason\n");
}