#! /usr/bin/perl -w # # Script name: gatherHeaderDoc # Synopsis: Finds all HeaderDoc generated docs in an input # folder and creates a top-level HTML page to them # # Author: Matt Morse (matt@apple.com) # Last Updated: $Date: 2001/03/29 03:02:19 $ # # 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. # # $Revision: 1.3 $ ###################################################################### use Cwd; use File::Find; use File::Copy; my $pathSeparator; my $isMacOS; my $scriptDir; my $framesetFileName; my $masterTOCFileName; BEGIN { if ($^O =~ /MacOS/i) { $pathSeparator = ":"; $isMacOS = 1; } else { $pathSeparator = "/"; $isMacOS = 0; } } use strict; use FindBin qw ($Bin); use lib "$Bin"."$pathSeparator"."Modules"; # Modules specific to gatherHeaderDoc use HeaderDoc::DocReference; use HeaderDoc::Utilities qw(findRelativePath safeName getAPINameAndDisc printArray printHash updateHashFromConfigFiles getHashFromConfigFile); my $debugging = 1; ######################################## Design Overview ################################### # - We scan input directory for frameset files (index.html, by default). # - For each frameset file, we look for a special HTML comment (left by HeaderDoc) # that tell us the name of the header/class and the type (header or cppclass). # - We create a DocReference object to store this info, and also the path to the # frameset file. # - We run through array of DocRef objs and create a master TOC based on the info # - Finally, we visit each TOC file in each frameset and add a "[Top]" link # back to the master TOC. [This is fragile in the current implementation, since # we find TOCs based on searching for a file called "toc.html" in the frameset dir. # ########################## Setup from Configuration File ####################### my $localConfigFileName = "headerDoc2HTML.config"; my $preferencesConfigFileName = "com.apple.headerDoc2HTML.config"; my $homeDir = (getpwuid($<))[7]; my $usersPreferencesPath = $homeDir.$pathSeparator."Library".$pathSeparator."Preferences"; my @configFiles = ($Bin.$pathSeparator.$localConfigFileName, $usersPreferencesPath.$pathSeparator.$preferencesConfigFileName); # default configuration, which will be modified by assignments found in config files. # The default values listed in this hash must be the same as those in the identical # hash in headerDoc2HTML--so that links between the frameset and the masterTOC work. my %config = ( defaultFrameName => "index.html", masterTOCName => "MasterTOC.html" ); %config = &updateHashFromConfigFiles(\%config,\@configFiles); if (defined $config{"defaultFrameName"}) { $framesetFileName = $config{"defaultFrameName"}; } if (defined $config{"masterTOCName"}) { $masterTOCFileName = $config{"masterTOCName"}; } ########################## Input Folder and Files ####################### my @inputFiles; my $inputDir; if (($#ARGV == 0) && (-d $ARGV[0])) { $inputDir = $ARGV[0]; $inputDir =~ s|(.*)/$|$1|; # get rid of trailing slash, if any if ($inputDir !~ /^\//) { # not absolute path -- !!! should check for ~ my $cwd = cwd(); $inputDir = $cwd.$pathSeparator.$inputDir; } &find({wanted => \&getFiles, follow => 1}, $inputDir); } else { die "You must specify a single input directory for processing.\n"; } unless (@inputFiles) { print "No valid input files specified. \n\n";}; sub getFiles { my $filePath = $File::Find::name; my $fileName = $_; if ($fileName =~ /$framesetFileName/) { push(@inputFiles, $filePath); } } ########################## Find HeaderDoc Comments ####################### my @headerFramesetRefs; my @classFramesetRefs; my $oldRecSep = $/; undef $/; # read in files as strings foreach my $file (@inputFiles) { open (INFILE, "<$file") || die "Can't open $file: $!\n"; my $fileString = ; close INFILE; if ($fileString =~ /<--\s+(headerDoc\s*=.*?)-->/) { my $fullComment = $1; my @pairs = split(/;/, $fullComment); my $docRef = HeaderDoc::DocReference->new; $docRef->path($file); foreach my $pair (@pairs) { my ($key, $value) = split(/=/, $pair); $key =~ s/^\s+|\s+$//; $value =~ s/^\s+|\s+$//; SWITCH: { ($key =~ /headerDoc/) && do { $docRef->type($value); last SWITCH; }; ($key =~ /name/) && do { $docRef->name($value); last SWITCH; }; } } my $tmpType = $docRef->type(); if ($tmpType eq "Header") { push (@headerFramesetRefs, $docRef); } elsif ($tmpType eq "CPPClass") { push (@classFramesetRefs, $docRef); } else { my $tmpName = $docRef->name(); my $tmpPath = $docRef->path(); print "Unknown type '$tmpType' for document with name '$tmpName' and path '$tmpPath'\n"; } } } $/ = $oldRecSep; # create master TOC if we have any framesets if (scalar(@headerFramesetRefs) + scalar(@classFramesetRefs)) { &printMasterTOC(); &addTopLinkToFramesetTOCs(); } else { print "gatherHeaderDoc.pl: No HeaderDoc framesets found--returning\n" if ($debugging); return; } exit 0; ################### Print Navigation Page ####################### sub printMasterTOC { my $outputDir = $inputDir; my $masterTOC = $outputDir.$pathSeparator. $masterTOCFileName; my $headersLinkString= ''; my $classesLinkString = ''; my $fileString; my $localDebug = 0; # get the HTML links to each header foreach my $ref (sort objName @headerFramesetRefs) { my $name = $ref->name(); my $path = $ref->path(); my $tmpString = &getLinkToFramesetFrom($masterTOC, $path, $name); $headersLinkString .= $tmpString; } print "\$headersLinkString is '$headersLinkString'\n" if ($localDebug); # get the HTML links to each class foreach my $ref (sort objName @classFramesetRefs) { my $name = $ref->name(); my $path = $ref->path(); my $tmpString = &getLinkToFramesetFrom($masterTOC, $path, $name); $classesLinkString .= $tmpString; } if (($localDebug) && length($classesLinkString)) {print "\$classesLinkString is '$classesLinkString'\n";}; # put together header/footer with linkString--could use template my $htmlHeader = "Header Documentation

Header Documentation



\n"; my $headerSection = "

Headers

\n
\n".$headersLinkString."\n
\n"; my $classesSection = ''; if (length($classesLinkString)) { $classesSection = "

Classes

\n
\n".$classesLinkString."\n
\n"; } my $htmlFooter = "\n\n"; $fileString = $htmlHeader.$headerSection.$classesSection.$htmlFooter; # write out page print "gatherHeaderDoc.pl: writing master TOC to $masterTOC\n" if ($localDebug); open(OUTFILE, ">$masterTOC") || die "Can't write $masterTOC.\n"; print OUTFILE $fileString; close OUTFILE; } sub addTopLinkToFramesetTOCs { my $masterTOC = $inputDir.$pathSeparator. $masterTOCFileName; my $tocFileName = "toc.html"; my @allDocRefs; push(@allDocRefs, @headerFramesetRefs); push(@allDocRefs, @classFramesetRefs); my $localDebug = 0; foreach my $ref (@allDocRefs) { my $name = $ref->name(); my $type = $ref->type(); my $path = $ref->path(); my $tocFile = $path; # path to index.html my $fsName = quotemeta($framesetFileName); $tocFile =~ s/$fsName$/toc.html/; # path to toc.html if (-e "$tocFile" ) { my $oldRecSep = $/; undef $/; # read in file as string open(INFILE, "<$tocFile") || die "Can't read file $tocFile.\n"; my $fileString = ; close INFILE; $/ = $oldRecSep; my $uniqueMarker = "headerDoc=\"topLink\""; if ($fileString !~ /$uniqueMarker/) { # we haven't been here before my $relPathToMasterTOC = &findRelativePath($tocFile, $masterTOC); my $topLink = "\n[Top]
\n"; $fileString =~ s/(]*>)/$1$topLink/i; open (OUTFILE, ">$tocFile") || die "Can't write file $tocFile.\n"; print OUTFILE $fileString; close (OUTFILE); } } elsif ($debugging) { print "--> '$tocFile' doesn't exist!\n"; print "Cannot add [top] link for frameset doc reference:\n"; print " name: $name\n"; print " type: $type\n"; print " path: $path\n"; } } } sub getLinkToFramesetFrom { my $masterTOCFile = shift; my $dest = shift; my $name = shift; my $linkString; my $relPath = &findRelativePath($masterTOCFile, $dest); $linkString = "$name
\n"; return $linkString; } sub objName { # for sorting objects by their names uc($a->name()) cmp uc($b->name()); }