package HeaderDoc::HeaderElement;
use HeaderDoc::Utilities qw(findRelativePath safeName getAPINameAndDisc printArray printHash unregisterUID registerUID html2xhtml sanitize parseTokens unregister_force_uid_clear dereferenceUIDObject filterHeaderDocTagContents validTag printFields splitOnPara getDefaultEncoding html_fixup_links xml_fixup_links);
use File::Basename;
use strict;
use vars qw($VERSION @ISA);
use POSIX qw(strftime mktime localtime);
use Carp qw(cluck);
use URI::Escape;
use locale;
use Encode qw(encode decode);
use Devel::Peek;
$HeaderDoc::HeaderElement::VERSION = '$Revision: 1341011599 $';
sub new {
my($param) = shift;
my($class) = ref($param) || $param;
my $self = {};
bless($self, $class);
$self->_initialize();
my (%attributeHash) = @_;
foreach my $key (keys(%attributeHash)) {
$self->{$key} = $attributeHash{$key};
}
return ($self);
}
sub _initialize {
my($self) = shift;
$self->{GROUP} = $HeaderDoc::globalGroup;
$self->{INDEXGROUP} = "";
$self->{AVAILABILITY} = "";
$self->{SINGLEATTRIBUTES} = ();
$self->{LONGATTRIBUTES} = ();
$self->{APIOWNER} = $HeaderDoc::currentClass;
$self->{ORIGCLASS} = "";
$self->{VALUE} = "UNKNOWN";
$self->{RETURNTYPE} = "";
$self->{TAGGEDPARAMETERS} = ();
$self->{PARSEDPARAMETERS} = ();
$self->{CONSTANTS} = ();
$self->{VARIABLES} = ();
$self->{CLASS} = "HeaderDoc::HeaderElement";
}
my %CSS_STYLES = ();
sub clone {
my $self = shift;
my $clone = undef;
if (@_) {
$clone = shift;
} else {
$clone = $self->new("lang" => $self->{LANG}, "sublang" => $self->{SUBLANG});
$clone->{CLASS} = $self->{CLASS};
}
$clone->{ABSTRACT} = $self->{ABSTRACT};
$clone->{DISCUSSION} = $self->{DISCUSSION};
$clone->{DECLARATION} = $self->{DECLARATION};
$clone->{DECLARATIONINHTML} = $self->{DECLARATIONINHTML};
$clone->{PRIVATEDECLARATION} = $self->{PRIVATEDECLARATION};
$clone->{OUTPUTFORMAT} = $self->{OUTPUTFORMAT};
$clone->{FILENAME} = $self->{FILENAME};
$clone->{FULLPATH} = $self->{FULLPATH};
$clone->{NAME} = $self->{NAME};
$clone->{RAWNAME} = $self->{RAWNAME};
$clone->{GROUP} = $self->{GROUP};
$clone->{THROWS} = $self->{THROWS};
$clone->{XMLTHROWS} = $self->{XMLTHROWS};
$clone->{UPDATED} = $self->{UPDATED};
$clone->{LINKAGESTATE} = $self->{LINKAGESTATE};
$clone->{ACCESSCONTROL} = $self->{ACCESSCONTROL};
$clone->{AVAILABILITY} = $self->{AVAILABILITY};
$clone->{LANG} = $self->{LANG};
$clone->{SUBLANG} = $self->{SUBLANG};
$clone->{SINGLEATTRIBUTES} = $self->{SINGLEATTRIBUTES};
$clone->{LONGATTRIBUTES} = $self->{LONGATTRIBUTES};
$clone->{NAMELINE_DISCUSSION} = $self->{NAMELINE_DISCUSSION};
$clone->{ATTRIBUTELISTS} = $self->{ATTRIBUTELISTS};
$clone->{APIOWNER} = $self->{APIOWNER};
$clone->{APIUID} = $self->{APIUID};
$clone->{LINKUID} = undef; $clone->{ORIGCLASS} = $self->{ORIGCLASS};
$clone->{ISTEMPLATE} = $self->{ISTEMPLATE};
$clone->{VALUE} = $self->{VALUE};
$clone->{RETURNTYPE} = $self->{RETURNTYPE};
my $ptref = $self->{PARSETREE};
if ($ptref) {
bless($ptref, "HeaderDoc::ParseTree");
$clone->{PARSETREE} = $ptref; my $pt = ${$ptref};
if ($pt) {
$pt->addAPIOwner($clone);
}
}
$clone->{TAGGEDPARAMETERS} = ();
if ($self->{TAGGEDPARAMETERS}) {
my @params = @{$self->{TAGGEDPARAMETERS}};
foreach my $param (@params) {
my $cloneparam = $param->clone();
push(@{$clone->{TAGGEDPARAMETERS}}, $cloneparam);
$cloneparam->apiOwner($clone);
}
}
$clone->{PARSEDPARAMETERS} = ();
if ($self->{PARSEDPARAMETERS}) {
my @params = @{$self->{PARSEDPARAMETERS}};
foreach my $param (@params) {
my $cloneparam = $param->clone();
push(@{$clone->{PARSEDPARAMETERS}}, $cloneparam);
$cloneparam->apiOwner($clone);
}
}
$clone->{VARIABLES} = ();
if ($self->{VARIABLES}) {
my @local_variables = @{$self->{VARIABLES}};
foreach my $local_variable (@local_variables) {
my $cloned_local_variable = $local_variable->clone();
push(@{$clone->{VARIABLES}}, $cloned_local_variable);
$cloned_local_variable->apiOwner($clone);
}
}
$clone->{CONSTANTS} = ();
if ($self->{CONSTANTS}) {
my @params = @{$self->{CONSTANTS}};
foreach my $param (@params) {
my $cloneparam = $param->clone();
push(@{$clone->{CONSTANTS}}, $cloneparam);
$cloneparam->apiOwner($clone);
}
}
$clone->{LINENUM} = $self->{LINENUM};
$clone->{CASESENSITIVE} = $self->{CASESENSITIVE};
$clone->{KEYWORDHASH} = $self->{KEYWORDHASH};
$clone->{MASTERENUM} = 0; $clone->{APIREFSETUPDONE} = 0;
$clone->{APPLEREFISDOC} = $self->{APPLEREFISDOC};
return $clone;
}
sub typedefContents {
my $self = shift;
if (@_) {
my $newowner = shift;
$self->{TYPEDEFCONTENTS} = $newowner;
}
return $self->{TYPEDEFCONTENTS};
}
sub origClass {
my $self = shift;
if (@_) {
my $newowner = shift;
$self->{ORIGCLASS} = $newowner;
}
return $self->{ORIGCLASS};
}
sub class {
my $self = shift;
return $self->{CLASS};
}
sub constructor_or_destructor {
my $self = shift;
my $localDebug = 0;
if ($self->{CLASS} eq "HeaderDoc::Function") {
my $apio = $self->apiOwner();
if (!$apio) {
print STDERR "MISSING API OWNER\n" if ($localDebug);
return 0;
} else {
my $apioclass = ref($apio) || $apio;
if ($apioclass ne "HeaderDoc::CPPClass") {
print STDERR "Not in CPP Class\n" if ($localDebug);
return 0;
}
}
my $name = $self->rawname();
print STDERR "NAME: $name : " if ($localDebug);
if ($name =~ /^~/o) {
print STDERR "DESTRUCTOR\n" if ($localDebug);
return 1;
}
$name =~ s/^\s*\w+\s*::\s*//so; # remove leading class part, if applicable
$name =~ s/\s*$//so;
my $classname = $apio->name();
if ($name =~ /^\Q$classname\E$/) {
print STDERR "CONSTRUCTOR\n" if ($localDebug);
return 1;
}
print STDERR "FUNCTION\n" if ($localDebug);
return 0;
} elsif ($self->{CLASS} eq "HeaderDoc::Method") {
return 0;
} else {
return 0;
}
}
sub variables {
my $self = shift;
if (@_) {
@{ $self->{VARIABLES} } = @_;
}
($self->{VARIABLES}) ? return @{ $self->{VARIABLES} } : return ();
}
sub constants {
my $self = shift;
if (@_) {
@{ $self->{CONSTANTS} } = @_;
}
($self->{CONSTANTS}) ? return @{ $self->{CONSTANTS} } : return ();
}
sub masterEnum {
my $self = shift;
if (@_) {
my $masterenum = shift;
$self->{MASTERENUM} = $masterenum;
}
return $self->{MASTERENUM};
}
sub addVariable {
my $self = shift;
if (@_) {
foreach my $item (@_) {
if ($self->can("addToVars")) {
$self->addToVars($item);
} else {
my $desc = $item->abstract();
$item->discussion($desc);
$item->abstract("");
push (@{$self->{VARIABLES}}, $item);
}
}
}
}
sub addConstant {
my $self = shift;
if (@_) {
foreach my $item (@_) {
push (@{$self->{CONSTANTS}}, $item);
}
}
return @{ $self->{CONSTANTS} };
}
sub addToFields {
my $self = shift;
if (@_) {
push (@{$self->{FIELDS}}, @_);
}
return @{ $self->{FIELDS} };
}
sub isTemplate {
my $self = shift;
if (@_) {
$self->{ISTEMPLATE} = shift;
}
return $self->{ISTEMPLATE};
}
sub isCallback {
my $self = shift;
if (@_) {
$self->{ISCALLBACK} = shift;
}
if ($self->can("type")) {
if ($self->type() eq "callback") { return 1; }
}
return $self->{ISCALLBACK};
}
sub isAPIOwner {
return 0;
}
sub inheritDoc {
my $self = shift;
if (@_) {
my $inheritDoc = shift;
$self->{INHERITDOC} = $inheritDoc;
}
return $self->{INHERITDOC};
}
sub linenuminblock
{
my $self = shift;
if (@_) {
my $linenum = shift;
$self->{RAWLINENUM} = $linenum;
}
return $self->{RAWLINENUM};
}
sub blockoffset
{
my $self = shift;
if (@_) {
my $linenum = shift;
$self->{BLOCKOFFSET} = $linenum;
}
return $self->{BLOCKOFFSET};
}
sub linenum {
my $self = shift;
if (@_) {
my $linenum = shift;
$self->{LINENUM} = $linenum;
}
return $self->{RAWLINENUM} + $self->{BLOCKOFFSET};
}
sub value {
my $self = shift;
if (@_) {
my $value = shift;
$self->{VALUE} = $value;
}
return $self->{VALUE};
}
sub outputformat {
my $self = shift;
if (@_) {
my $outputformat = shift;
$self->{OUTPUTFORMAT} = $outputformat;
} else {
my $o = $self->{OUTPUTFORMAT};
return $o;
}
}
sub use_stdout {
my $self = shift;
if (@_) {
my $use_stdout = shift;
$self->{USESTDOUT} = $use_stdout;
} else {
my $o = $self->{USESTDOUT};
return $o;
}
}
sub functionContents {
my $self = shift;
if (@_) {
my $string = shift;
$self->{FUNCTIONCONTENTS} = $string;
}
return $self->{FUNCTIONCONTENTS};
}
sub fullpath {
my $self = shift;
if (@_) {
my $fullpath = shift;
$self->{FULLPATH} = $fullpath;
} else {
my $n = $self->{FULLPATH};
return $n;
}
}
sub filename {
my $self = shift;
if (@_) {
my $filename = shift;
$self->{FILENAME} = $filename;
} else {
my $n = $self->{FILENAME};
return $n;
}
}
sub firstconstname {
my $self = shift;
my $localDebug = 0;
my($class) = ref($self) || $self;
print STDERR "$class\n" if ($localDebug);
if (@_) {
my $name = shift;
print STDERR "Set FIRSTCONSTNAME to $name\n" if ($localDebug);
$self->{FIRSTCONSTNAME} = $name;
}
return $self->{FIRSTCONSTNAME};
}
sub name {
my $self = shift;
my $localDebug = 0;
my($class) = ref($self) || $self;
print STDERR "$class\n" if ($localDebug);
if (@_) {
my $name = shift;
my $oldname = $self->{NAME};
my $fullpath = $self->fullpath();
my $linenum = $self->linenum();
my $class = ref($self) || $self;
print STDERR "NAMESET: $self -> $name\n" if ($localDebug);
if (!($class eq "HeaderDoc::Header") && ($oldname && length($oldname))) {
my $nsoname = $oldname;
my $nsname = $name;
if ($class =~ /^HeaderDoc::ObjC/) {
$nsname =~ s/\s//g;
$nsoname =~ s/\s//g;
} elsif ($class =~ /^HeaderDoc::Method/) {
$nsname =~ s/:$//g;
$nsoname =~ s/:$//g;
}
if ($nsname !~ /\Q$nsoname\E/) {
if (!$HeaderDoc::ignore_apiuid_errors) {
warn("$fullpath:$linenum: warning: Name being changed ($oldname -> $name)\n");
}
} elsif (($class eq "HeaderDoc::CPPClass" || $class =~ /^HeaderDoc::ObjC/o) && $name =~ /:/o) {
warn("$fullpath:$linenum: warning: Class name contains colon, which is probably not what you want.\n");
}
}
$name =~ s/\n$//sgo;
$name =~ s/\s$//sgo;
$self->{NAME} = $name;
}
my $n = $self->{NAME};
if ($self->{DISCUSSION_SET}) {
if ((!$HeaderDoc::ignore_apiowner_names) || (!$self->isAPIOwner() && ($HeaderDoc::ignore_apiowner_names != 2)) || $self->isFramework()) {
print STDERR "NAMELINE DISCUSSION for $self CONCATENATED (".$self->{NAMELINE_DISCUSSION}.")\n" if ($localDebug);
print STDERR "ORIGINAL NAME WAS \"$n\"\n" if ($localDebug);
if (length($self->{NAMELINE_DISCUSSION})) {
$n .= " ".$self->{NAMELINE_DISCUSSION};
}
}
}
if ($class eq "HeaderDoc::Function" && $self->conflict()) {
$n .= "(";
$n .= $self->getParamSignature(1);
$n .= ")";
}
if ($n !~ /\S/) {
$n = $self->firstconstname();
}
return $n;
}
sub seeDupCheck {
my $self = shift;
my $name = shift;
my $set = 0;
if (@_) {
$set = shift;
}
my %dupcheck = ();
if ($self->{SEEALSODUPCHECK}) {
%dupcheck = %{$self->{SEEALSODUPCHECK}};
}
my $retval = $dupcheck{$name};
if ($set) {
$dupcheck{$name} = $name;
}
$self->{SEEALSODUPCHECK} = \%dupcheck;
return $retval;
}
sub see {
my $self = shift;
my $liststring = shift;
my $type = "See";
my $apiUIDPrefix = HeaderDoc::APIOwner->apiUIDPrefix();
my $dupDebug = 0;
print STDERR "see called\n" if ($dupDebug);
if ($liststring =~ s/^seealso\s+//iso) {
$type = "See Also";
} else {
$liststring =~ s/^see\s+//iso;
}
my @items = split(/[\n\r]/, $liststring);
foreach my $item (@items) {
if ($item !~ /^\/\/\w+\// && $item =~ /\S/) { ## API anchor (apple_ref or other)
my @list = split(/\s+/, $item, 2);
my $see = $list[0];
my $name = $list[1];
if ($name !~ /\S/) { $name = $see; }
print STDERR "Checking \"$see\" for duplicates.\n" if ($dupDebug);
if (!$self->seeDupCheck($see)) {
my $apiuid = $see;
$self->attributelist($type, $name."\n$apiuid");
$self->seeDupCheck($see, 1);
print STDERR "Not found. Adding.\n" if ($dupDebug);
} else {
print STDERR "Omitting duplicate \"$see\"[1]\n" if ($dupDebug);
}
} elsif ($item =~ /\S/) {
$item =~ s/^\s*//s;
$item =~ s/\s+/ /sg;
my @parts = split(/\s+/, $item, 2);
my $name = $parts[1];
$name =~ s/\s+$//sg;
print STDERR "Checking \"$name\" for duplicates.\n" if ($dupDebug);
if (!$self->seeDupCheck($name)) {
$self->attributelist($type, $name."\n".$parts[0]);
$self->seeDupCheck($name, 1);
print STDERR "Not found. Adding.\n" if ($dupDebug);
} else {
print STDERR "Omitting duplicate \"$name\"[2]\n" if ($dupDebug);
}
}
}
}
sub mediumrarename {
my $self = shift;
return $self->{NAME};
}
sub rawname {
my $self = shift;
my $localDebug = 0;
if (@_) {
my $name = shift;
$self->{RAWNAME} = $name;
print STDERR "RAWNAME: $name\n" if ($localDebug);
}
my $n = $self->{RAWNAME};
if (!($n) || !length($n)) {
$n = $self->{NAME};
}
return $n;
}
sub clearGroup {
my $self = shift;
$self->{GROUP} = undef;
}
sub group {
my $self = shift;
if (@_) {
my $group = shift;
$self->{GROUP} = $group;
if (!$self->isAPIOwner()) {
$self->apiOwner()->addToGroup($group, $self);
}
} else {
my $n = $self->{GROUP};
return $n;
}
}
sub attribute {
my $self = shift;
my $name = shift;
my $attribute = shift;
my $long = shift;
my $programmatic = 0;
if (@_) {
$programmatic = shift;
}
my $localDebug = 0;
cluck("Attribute added:\nNAME => $name\nATTRIBUTE => $attribute\nLONG => $long\nPROGRAMMATIC => $programmatic\n") if ($localDebug);
my %attlist = ();
if ($long) {
if ($self->{LONGATTRIBUTES}) {
%attlist = %{$self->{LONGATTRIBUTES}};
}
} else {
if ($self->{SINGLEATTRIBUTES}) {
%attlist = %{$self->{SINGLEATTRIBUTES}};
}
$attribute =~ s/\n/ /sgo;
$attribute =~ s/^\s*//so;
$attribute =~ s/\s*$//so;
}
if ($programmatic || !$long) {
$attlist{$name}=$attribute;
} else {
$attlist{$name}=filterHeaderDocTagContents($attribute);
}
if ($long) {
$self->{LONGATTRIBUTES} = \%attlist;
} else {
$self->{SINGLEATTRIBUTES} = \%attlist;
}
my $temp = $self->getAttributes(2);
print STDERR "Attributes: $temp\n" if ($localDebug);
}
sub getAttributes
{
my $self = shift;
my $long = shift;
my %attlist = ();
my $localDebug = 0;
my $xml = 0;
my $newTOC = $HeaderDoc::newTOC;
my $class = ref($self) || $self;
my $uid = $self->apiuid();
if (!$self->isAPIOwner()) { $newTOC = 0; }
my $apiowner = $self->apiOwner();
if ($apiowner->outputformat() eq "hdxml") { $xml = 1; }
my $first = 1;
my $maybe = 0;
my $retval = "";
if ($long != 1) {
if ($self->{SINGLEATTRIBUTES}) {
%attlist = %{$self->{SINGLEATTRIBUTES}};
}
foreach my $key (sort strcasecmp keys %attlist) {
my $keyname = $key; if ($key eq "Superclass" && ($HeaderDoc::superclassName =~ /\S/)) {
$keyname = $HeaderDoc::superclassName;
}
print STDERR "KEY NAME CHANGED TO \"$keyname\"\n" if ($localDebug);
my $value = $attlist{$key};
my $newatt = $value;
if (($key eq "Superclass" || $key eq "Extends Class" || $key eq "Extends Protocol" || $key eq "Conforms to" || $key eq "Implements Class")) {
my $classtype = "class";
my $selfclass = ref($self) || $self;
if ($selfclass =~ /HeaderDoc::ObjC/) {
if ($key eq "Conforms to" || $key eq "Extends Protocol") {
$classtype = "protocol";
}
}
my @valparts = split(/\cA/, $value);
$newatt = "";
foreach my $valpart (@valparts) {
if (length($valpart)) {
$valpart =~ s/^\s*//s;
if ($valpart =~ /^(\w+)(\W.*)$/) {
$newatt .= $self->genRef("$classtype", $1, $1).$self->textToXML($2);
} else {
$newatt .= $self->genRef("$classtype", $valpart, $self->htmlToXML($valpart));
}
if (!$xml) {
$newatt .= ", ";
}
}
}
$newatt =~ s/, $//s;
if ($xml) {
$keyname =~ s/ / /sg;
}
} elsif ($key eq "Path To Headers" && !$xml) {
$newatt = "<!-- headerDoc=headerpath;uid=".$uid.";name=start -->\n$value\n<!-- headerDoc=headerpath;uid=".$uid.";name=end -->\n";
} elsif ($key eq "Framework Path" && !$xml) {
$newatt = "<!-- headerDoc=frameworkpath;uid=".$uid.";name=start -->\n$value\n<!-- headerDoc=frameworkpath;uid=".$uid.";name=end -->\n";
} elsif ($key eq "Requested Copyright" && !$xml) {
$newatt = "<!-- headerDoc=frameworkcopyright;uid=".$uid.";name=start -->\n$value\n<!-- headerDoc=frameworkpath;uid=".$uid.";name=end -->\n";
} elsif ($key eq "Requested UID" && !$xml) {
$newatt = "<!-- headerDoc=frameworkuid;uid=".$uid.";name=start -->\n$value\n<!-- headerDoc=frameworkuid;uid=".$uid.";name=end -->\n";
} elsif ($xml) {
$keyname = $self->htmlToXML($keyname);
$newatt = $self->htmlToXML($newatt);
} else {
print STDERR "KEY: $key\n" if ($localDebug);
}
if ($xml) {
$retval .= "<attribute><name>$keyname</name><value>$newatt</value></attribute>\n";
} else {
if ($newTOC) {
if ($first) { $retval .= "<div class=\"spec_sheet_info_box\"><table cellspacing=\"0\" class=\"specbox\">\n"; $first = 0; }
$retval .= "<tr><td scope=\"row\"><b>$keyname:</b></td><td><div style=\"margin-bottom:1px\"><div class=\"content_text\">$newatt</div></div></td></tr>\n";
} else {
$retval .= "<p><b>$keyname</b></p>\n\n<p>$newatt</p>\n";
}
}
}
my $declaredin = $self->declaredIn();
if ($declaredin && (
$self->isAPIOwner())) {
my $blockclass = "\$\$customref_show_block\@\@";
my $rowclass = " class=\"customref_show_row\"";
if ($self->isAPIOwner()) {
$blockclass = "";
$rowclass = "";
}
if (!$xml) {
if ($newTOC) {
if ($first) { $retval .= "<div class=\"".$blockclass."spec_sheet_info_box\"><table cellspacing=\"0\" class=\"specbox\">\n"; $first = 0; $maybe = 1; }
$retval .= "<tr$rowclass><td scope=\"row\"><b>Declared In:</b></td><td><div style=\"margin-bottom:1px\"><div class=\"content_text\">$declaredin</div></div></td></tr>\n";
} else {
$retval .= "<p><b>Declared In</b></p><p>$declaredin</p>\n";
}
}
}
}
if ($long != 0) {
if ($self->{LONGATTRIBUTES}) {
%attlist = %{$self->{LONGATTRIBUTES}};
}
foreach my $key (sort strcasecmp keys %attlist) {
my $value = $attlist{$key};
if ($xml) {
$key = $self->htmlToXML($key);
$value = $self->htmlToXML($value);
$retval .= "<longattribute><name>$key</name><value>$value</value></longattribute>\n";
} else {
$maybe = 0;
if ($newTOC) {
if ($first) { $retval .= "<div class=\"spec_sheet_info_box\"><table cellspacing=\"0\" class=\"specbox\">\n"; $first = 0; }
$retval .= "<tr><td scope=\"row\"><b>$key:</b></td><td><div style=\"margin-bottom:1px\"><div class=\"content_text\">$value</div></div></td></tr>\n";
} else {
$retval .= "<p><b>$key</b></p>\n\n<p>$value</p>\n";
}
}
}
}
if ((!$xml) && ($newTOC && !$first)) {
$retval .= "</table></div>\n";
}
return $retval;
}
sub checkShortLongAttributes
{
my $self = shift;
my $name = shift;
my $localDebug = 0;
my %singleatts = ();
if ($self->{SINGLEATTRIBUTES}) {
%singleatts = %{$self->{SINGLEATTRIBUTES}};
}
my %longatts = ();
if ($self->{LONGATTRIBUTES}) {
%longatts = %{$self->{LONGATTRIBUTES}};
}
my $value = $singleatts{$name};
if ($value && length($value)) {return $value;}
$value = $longatts{$name};
if ($value && length($value)) {return $value;}
return 0;
}
sub checkAttributeLists
{
my $self = shift;
my $name = shift;
my $localDebug = 0;
my %attlists = ();
if ($self->{ATTRIBUTELISTS}) {
%attlists = %{$self->{ATTRIBUTELISTS}};
}
my $retval = "";
my $value = $attlists{$name};
if ($value) { return $value; }
return 0;
}
sub getAttributeLists
{
my $self = shift;
my $composite = shift;
my $localDebug = 0;
my $xml = 0;
my $newTOC = $HeaderDoc::newTOC;
my $uid = $self->apiuid();
my $isFramework = 0;
if ($self->can('isFramework') && $self->isFramework()) {
$isFramework = 1;
}
if (!$self->isAPIOwner()) { $newTOC = 0; }
my $apiowner = $self->apiOwner();
if (!$apiowner) {
cluck("No api owner for $self\n");
}
if ($apiowner->outputformat() eq "hdxml") { $xml = 1; }
my %attlists = ();
if ($self->{ATTRIBUTELISTS}) {
%attlists = %{$self->{ATTRIBUTELISTS}};
}
my $retval = "";
my $first = 1;
foreach my $key (sort strcasecmp (keys %attlists)) {
my $prefix = "";
my $suffix = "";
if ($isFramework && ($key eq "See" || $key eq "See Also")) {
$prefix = "<!-- headerDoc=frameworkrelated;uid=".$uid.";name=start -->\n";
$suffix = "\n<!-- headerDoc=frameworkrelated;uid=".$uid.";name=end -->\n";
}
if ($xml) {
$retval .= "<listattribute><name>$key</name><list>\n";
} else {
$retval .= $prefix;
if ($newTOC) {
if ($first) { $retval .= "<div class=\"spec_sheet_info_box\"><table cellspacing=\"0\" class=\"specbox\">\n"; $first = 0; }
$retval .= "<tr><td scope=\"row\"><b>$key:</b></td><td><div style=\"margin-bottom:1px\"><div class=\"content_text\"><dl>\n";
} else {
$retval .= "<p><b>$key</b></p><div class='list_indent'><dl>\n";
}
}
print STDERR "key $key\n" if ($localDebug);
my @list = @{$attlists{$key}};
foreach my $item (@list) {
if ($item !~ /\S/s) { next; }
print STDERR "item: $item\n" if ($localDebug);
my ($name, $disc, $namedisc) = &getAPINameAndDisc($item, $self->lang());
if ($key eq "Included Defines") {
my $apiref = $self->apiref($composite, "macro", $name);
$name .= "$apiref";
}
if ($xml) {
$name = $self->htmlToXML($name);
$disc = $self->htmlToXML($disc);
}
if (($key eq "See Also" || $key eq "See")) {
$name =~ s/^(\s|<br>|<p>)+//sgio;
$name =~ s/(\s|<br>|<\/p>)+$//sgio;
$disc =~ s/^(\s|<br>|<p>)+//sgio;
$disc =~ s/(\s|<br>|<\/p>)+$//sgio;
$name =~ s/\cD/ /sgo;
if ($xml) {
$disc = "<hd_link logicalPath=\"$disc\" isseealso=\"yes\">$name</hd_link>";
} else {
$name = "<p><hd_link posstarget=\"$disc\">$name</hd_link></p>";
$disc = "";
}
}
if ($xml) {
$retval .= "<item><name>$name</name><value>$disc</value></item>";
} else {
$retval .= "<dt>$name</dt><dd>$disc</dd>";
}
}
if ($xml) {
$retval .= "</list></listattribute>\n";
} else {
if ($newTOC) {
$retval .= "</dl></div></div></td></tr>\n";
} else {
$retval .= "</dl></div>\n";
}
$retval .= $suffix;
}
}
if ($newTOC) {
if (!$first) { $retval .= "</table></div>\n"; }
}
return $retval;
}
sub attributelist {
my $self = shift;
my $name = shift;
my $attribute = shift;
my %attlists = ();
if ($self->{ATTRIBUTELISTS}) {
%attlists = %{$self->{ATTRIBUTELISTS}};
}
my @list = ();
my $listref = $attlists{$name};
if ($listref) {
@list = @{$listref};
}
push(@list, filterHeaderDocTagContents($attribute));
$attlists{$name}=\@list;
$self->{ATTRIBUTELISTS} = \%attlists;
}
sub apiOwner {
my $self = shift;
if (@_) {
my $temp = shift;
$self->{APIOWNER} = $temp;
}
return $self->{APIOWNER};
}
sub apiref {
my $self = shift;
my $filename = $self->filename();
my $linenum = $self->linenum();
my $composite = shift;
my $args = 0;
my $type = "";
my $apiowner = $self->apiOwner();
my $owningclass = ref($apiowner) || $self;
my $paramSignature = "";
if (@_) {
$args = 1;
$type = shift;
if (@_) {
$paramSignature = shift;
}
} else {
my $uid = $self->apiuid();
if ($uid =~ /\/\/.*?\/.*?\/(.*?)\//o) {
$type = $1;
}
}
my $forceuid = "";
if ($self->origClass() ne "") {
$forceuid = $self->generateLinkUID($composite);
}
my $uid = "";
if ($args && !$forceuid) {
$uid = $self->apiuid($type, $paramSignature);
} else {
$uid = $self->apiuid();
}
if ($composite && !$HeaderDoc::ClassAsComposite) {
$uid = $self->compositePageUID();
} elsif (!$composite && $HeaderDoc::ClassAsComposite) {
$uid = $self->compositePageUID();
}
if ($forceuid) { $uid = $forceuid; }
my $ret = "";
if (length($uid)) {
my $name = $self->name();
if ($self->can("rawname")) {
if (!$self->{DISCUSSION} || !$self->{NAMELINE_DISCUSSION}) {
$name = $self->rawname();
}
}
my $extendedname = $name;
if ($owningclass ne "HeaderDoc::Header" && $self->sublang() ne "C") {
$extendedname = $apiowner->rawname() . "::" . $name;
}
$extendedname =~ s/<.*?>//sgo;
$extendedname =~ s/;//sgo;
my $uidstring = "";
my $indexgroup = $self->indexgroup();
if (length($uid)) { $uidstring = " uid=$uid; "; }
if (length($indexgroup)) { $uidstring .= " indexgroup=$indexgroup; "; }
my $fwshortname = "";
if ($self->isFramework()) {
$fwshortname = $self->filename();
$fwshortname =~ s/\.hdoc$//so;
$fwshortname = sanitize($fwshortname, 1);
$fwshortname = "shortname=$fwshortname;";
}
$ret .= "<!-- headerDoc=$type; $uidstring $fwshortname name=$extendedname -->\n";
if (length($uid) && !$self->isFramework()) { $ret .= "<a name=\"$uid\"></a>\n"; }
}
$owningclass = undef;
return $ret;
}
sub indexgroup
{
my $self = shift;
if (@_) {
my $group = shift;
$group =~ s/^\s*//sg;
$group =~ s/\s*$//sg;
$group =~ s/;/\\;/sg;
$group .= " ";
$self->{INDEXGROUP} = $group;
}
my $ret = $self->{INDEXGROUP};
if (!length($ret)) {
my $apio = $self->apiOwner();
if ($apio && ($apio != $self)) {
return $apio->indexgroup();
}
}
return $ret;
}
sub generateLinkUID
{
my $self = shift;
my $composite = shift;
if ($self->{LINKUID}) {
if ($composite) {
return $self->compositePageUID();
}
return $self->{LINKUID};
}
my $classname = sanitize($self->apiOwner()->rawname(), 1);
my $name = sanitize($self->rawname(), 1);
my $apiUIDPrefix = HeaderDoc::APIOwner->apiUIDPrefix();
my $uniquenumber = $HeaderDoc::uniquenumber++;
my $uid = "//$apiUIDPrefix/doc/inheritedContent/$classname/$name/$uniquenumber";
$self->{LINKUID} = $uid;
if ($composite) {
return $self->compositePageUID()
}
return $uid;
}
sub apiuidname
{
my $self = shift;
my $class = ref($self) || $self;
my $localDebug = 0;
my $name = $self->mediumrarename();
if (!($self->can("conflict")) || ($self->can("conflict") && !($self->conflict()))) {
print STDERR "No conflict.\n" if ($localDebug);
$name = $self->rawname();
if ($class eq "HeaderDoc::ObjCCategory") {
if ($name =~ /\s*\w+\s*\(.+\).*/o) {
$name =~ s/\s*(\w+)\s*\(\s*(\w+)\s*\).*/$1($2)/o;
}
}
$name =~ s/^\s*//so;
$name =~ s/\s*$//so;
print STDERR "Sanitized name: $name\n" if ($localDebug);
} else {
print STDERR "Conflict detected.\n" if ($localDebug);
my $apiOwner = $self->apiOwner();
my $apiOwnerClass = ref($apiOwner) || $apiOwner;
if ($apiOwnerClass eq "HeaderDoc::CPPClass") {
$name = $self->rawname();
} else {
$name =~ s/ //sgo;
}
$name =~ s/^\s*//so;
$name =~ s/\s*$//so;
}
$name =~ s/\n//smgo;
if ($name =~ /^operator\s+\w/) {
$name =~ s/^operator\s+/operator_/;
} else {
$name =~ s/^operator\s+/operator/;
}
return $name;
}
sub apiuid {
my $self = shift;
my $type = "AUTO";
my $paramSignature_or_alt_define_name = "";
my $filename = $self->filename();
my $linenum = $self->linenum();
my $localDebug = 0;
print STDERR "IN apiuid\n" if ($localDebug);
if (@_) {
$type = shift;
if (@_) {
$paramSignature_or_alt_define_name = shift;
}
} else {
if ($self->{LINKUID}) {
print STDERR "RETURNING CACHED LINKUID ".$self->{LINKUID}."\n" if ($localDebug);
return $self->{LINKUID};
}
print STDERR "RETURNING CACHED APIUID ".$self->{APIUID}."\n" if ($localDebug);
return $self->{APIUID};
}
if ($self->{REQUESTEDUID} && length($self->{REQUESTEDUID})) {
$self->{APIUID} = $self->{REQUESTEDUID};
print STDERR "RETURNING EXPLICITLY REQUESTED APIUID ".$self->{REQUESTEDUID}."\n" if ($localDebug);
return $self->{REQUESTEDUID};
}
print STDERR "GENERATING NEW APIUID FOR $self (".$self->name.")\n" if ($localDebug);
my $olduid = $self->{APIUID};
if ($self->{LINKUID}) { $olduid = $self->{LINKUID}; }
my $name = $self->apiuidname();
$localDebug = 0;
my $className;
my $lang = $self->sublang();
my $class = ref($self) || $self;
cluck("Call trace\n") if ($localDebug);
my $parentClass = $self->apiOwner();
if ($type eq "econst") {
while (!$parentClass->isAPIOwner()) {
$parentClass = $parentClass->apiOwner();
}
}
my $parentClassType = ref($parentClass) || $parentClass;
if ($parentClassType eq "HeaderDoc::Header") {
if (!($class eq "HeaderDoc::CPPClass" || $class =~ /^HeaderDoc::ObjC/o)) {
if ($lang ne "IDL" && $lang ne "MIG" && $lang ne "javascript") {
$lang = $self->lang();
}
}
}
$lang = $self->apiRefLanguage($lang);
print STDERR "LANG: $lang\n" if ($localDebug);
if ($parentClassType eq "HeaderDoc::Header") {
if (!$HeaderDoc::headerObject) {
die "headerObject undefined!\n";
}
if ($self->parserState() && $self->parserState()->{isStatic}) {
$className = $HeaderDoc::headerObject->filename();
if (!(length($className))) {
die "Header Name empty!\n";
}
} else {
$className = "";
}
} else {
$className = $parentClass->name();
}
$className =~ s/\s//sgo;
$className =~ s/<.*?>//sgo;
$class = ref($self) || $self;
if ($class eq "HeaderDoc::PDefine") {
$className = "";
if ($paramSignature_or_alt_define_name) {
$name = $paramSignature_or_alt_define_name;
$paramSignature_or_alt_define_name = "";
}
}
if ($class eq "HeaderDoc::Header") {
$className = "";
$lang = "doc";
if ($self->isFramework()) {
$type = "framework";
} else {
$type = "header";
}
$name = $self->filename();
if ($self->can('isFramework') && $self->isFramework()) {
$name =~ s/\.hdoc$//s;
}
}
my $apio = $self->apiOwner();
my $sublang = $self->sublang();
if ($type eq "intfm" && ($sublang eq "c" || $sublang eq "C") && $apio =~ /HeaderDoc::CPPClass/) {
$lang = "doc/com";
$type = "intfm";
}
if ($self->appleRefIsDoc()) {
$lang = "doc";
$type = "title:$type";
$name = $self->rawname_extended();
}
print STDERR "genRefSub: \"$lang\" \"$type\" \"$name\" \"$className\" \"$paramSignature_or_alt_define_name\"\n" if ($localDebug);
my $uid = $self->genRefSub($lang, $type, $name, $className, $paramSignature_or_alt_define_name);
if (length($name)) {
unregisterUID($olduid, $name, $self);
$uid = registerUID($uid, $name, $self); }
print STDERR "APIUID SET TO $uid\n" if ($localDebug);
$self->{APIUID} = $uid;
return $uid;
}
sub appleRefIsDoc
{
my $self = shift;
if (@_) {
my $value = shift;
$self->{APPLEREFISDOC} = $value;
}
return $self->{APPLEREFISDOC};
}
sub genRefSub($$$$)
{
my $self = shift;
my $orig_lang = shift;
my $orig_type = shift;
my $orig_name = shift;
my $orig_className = shift;
my $orig_paramSignature = "";
if (@_) {
$orig_paramSignature = shift;
}
my $owner_class = "";
if (@_) {
$owner_class = shift;
}
my $lang = sanitize($orig_lang);
my $type = sanitize($orig_type);
my $name = sanitize($orig_name, 1);
my $className = sanitize($orig_className, 1);
my $paramSignature = sanitize($orig_paramSignature);
if (length($className) && length($name)) { $className .= "/"; }
my $apiUIDPrefix = HeaderDoc::APIOwner->apiUIDPrefix();
my $localDebug = 0;
$lang = $self->apiRefLanguage($lang);
if ($lang eq "perl") {
if ($type ne "cl") {
if ($name =~ s/^(.+)\:\://s) {
$className = "$1/";
}
}
}
my $uid;
if (length($owner_class)) {
$uid = "//$apiUIDPrefix/$lang/$type/$owner_class/$className$name$paramSignature";
} else {
$uid = "//$apiUIDPrefix/$lang/$type/$className$name$paramSignature";
}
return $uid;
}
sub apiRefLanguage
{
my $self = shift;
my $lang = shift;
if ($lang eq "javascript") {
$lang = "js";
}
if ($lang eq "csh") {
$lang = "shell";
}
if ($lang eq "MIG") {
$lang = "mig";
} elsif ($lang eq "IDL") {
$lang = $HeaderDoc::idl_language;
}
if ($lang eq "C") { $lang = "c"; }
if ($lang eq "Csource") { $lang = "c"; }
if ($lang eq "occCat") { $lang = "occ"; }
if ($lang eq "intf") { $lang = "occ"; }
return $lang;
}
sub throws {
my $self = shift;
my $newTOC = $HeaderDoc::newTOC;
if (!$self->isAPIOwner()) { $newTOC = 0; }
if (@_) {
my $new = shift;
$new =~ s/\n/ /smgo; $new =~ s/\s+$//smgo; # Remove trailing spaces
if ($newTOC) {
$self->{THROWS} .= "$new<br>\n";
} else {
$self->{THROWS} .= "$new<br>\n";
}
$self->{XMLTHROWS} .= "<throw>$new</throw>\n";
}
if (length($self->{THROWS})) {
if ($newTOC) {
return $self->{THROWS};
} else {
return ("<p>\n" . $self->{THROWS} . "</p>");
}
} else {
return "";
}
}
sub XMLthrows {
my $self = shift;
my $string = $self->htmlToXML($self->{XMLTHROWS});
my $ret;
if (length($string)) {
$ret = "<throwlist>\n$string</throwlist>\n";
} else {
$ret = "";
}
return $ret;
}
sub abstract {
my $self = shift;
my $localDebug = 0;
my $isbrief = 0;
if (@_) {
my $abs = shift;
print STDERR "Setting abstract for $self to \"$abs\"\n" if ($localDebug);;
if (@_) {
$isbrief = 1;
}
if ($isbrief) {
my ($newabs, $newdisc) = split(/[\n\r][ \t]*[\n\r]/, $abs, 2);
$abs = $newabs;
$newdisc =~ s/^(\n|\r|< *br *\/? *>)*//si;
$self->discussion($newdisc);
}
$self->{ABSTRACT} = $self->linkfix(filterHeaderDocTagContents($abs));
}
my $ret = $self->{ABSTRACT};
return $ret;
}
sub XMLabstract {
my $self = shift;
if (@_) {
$self->{ABSTRACT} = shift;
}
return $self->htmlToXML($self->{ABSTRACT});
}
sub raw_nameline_discussion {
my $self = shift;
return $self->{NAMELINE_DISCUSSION};
}
sub rawname_extended {
my $self = shift;
my $localDebug = 0;
my $n = $self->rawname();
if ($self->{DISCUSSION_SET}) {
if ((!$HeaderDoc::ignore_apiowner_names) || (!$self->isAPIOwner()) || $self->isFramework()) {
print STDERR "NAMELINE DISCUSSION for $self CONCATENATED (".$self->{NAMELINE_DISCUSSION}.")\n" if ($localDebug);
print STDERR "ORIGINAL NAME WAS \"$n\"\n" if ($localDebug);
if (length($self->{NAMELINE_DISCUSSION})) {
$n .= " ".$self->{NAMELINE_DISCUSSION};
}
}
}
return $n;
}
sub nameline_discussion {
my $self = shift;
my $localDebug = 0;
if (@_) {
$self->{NAMELINE_DISCUSSION} = shift;
print STDERR "nameline discussion set to ".$self->{NAMELINE_DISCUSSION}."\n" if ($localDebug);
}
return $self->htmlToXML(filterHeaderDocTagContents($self->{NAMELINE_DISCUSSION}));
}
sub raw_discussion {
my $self = shift;
return $self->{DISCUSSION};
}
sub discussion_set {
my $self = shift;
return $self->{DISCUSSION_SET};
}
sub halfbaked_discussion {
my $self = shift;
return $self->discussion_sub(0, 0);
}
sub discussion {
my $self = shift;
my $discDebug = 0;
if (@_) {
my $olddisc = $self->{DISCUSSION};
$self->{DISCUSSION_SET} = 1;
print STDERR "DISCUSSION SET: $self : $olddisc -> \n" if ($discDebug);
my $discussion = "";
if ($olddisc ne "" && $discussion ne "") {
if (!$self->inDefineBlock()) {
my $fullpath = $self->fullpath();
my $linenum = $self->linenum();
warn("$fullpath:$linenum: warning: Multiple discussions found for ".$self->name()." ($self). Merging.\n");
$discussion = $olddisc."<br /><br />\n";;
}
}
my $newdisc = $self->listfixup(shift);
$discussion .= filterHeaderDocTagContents($newdisc);
print STDERR "$discussion\n" if ($discDebug);
$self->{DISCUSSION} = $self->linkfix($discussion);
if ($self->{DISCUSSION} eq "") {
$self->{DISCUSSION} .= " ";
}
}
return $self->discussion_sub(1, $discDebug);
}
sub discussion_sub
{
my $self = shift;
my $bake = shift;
my $discDebug = shift;
print STDERR "OBJ is \"".$self."\"\n" if ($discDebug);
print STDERR "NAME is \"".$self->{NAME}."\"\n" if ($discDebug);
print STDERR "DISC WAS \"".$self->{DISCUSSION}."\"\n" if ($discDebug);
print STDERR "NAMELINE DISC WAS \"".$self->{NAMELINE_DISCUSSION}."\"\n" if ($discDebug);
if ($self->{DISCUSSION}) {
return $self->{DISCUSSION};
} else {
print STDERR "RETURNING NAMELINE DISC\n" if ($discDebug);
}
if ($bake) {
return "<p>".$self->{NAMELINE_DISCUSSION}."</p>";
}
return $self->{NAMELINE_DISCUSSION};
}
sub splitmerge
{
my $arrayref = shift;
my @arr = @{$arrayref};
my @ret = ();
foreach my $item (@arr) {
if ($item =~ /[\n\r]/) {
my $temp = pop(@ret);
if ($temp) {
if ($temp =~ /[\r\n]$/s) {
push(@ret, $temp);
} else {
$item = $temp.$item;
}
}
push(@ret, $item);
} elsif ($item) {
push(@ret, $item);
}
}
return @ret;
}
sub listfixup
{
my $self = shift;
my $olddiscussion = shift;
my $discussion = "";
my $numListDebug = 0;
my $encoding = $self->encoding();
my $bullet = "";
if ($encoding = /iso-8859-\d+\s*$/i) {
$bullet = "\x95";
} elsif ($encoding = /Windows-\d+/i) {
$bullet = "\x95"; } elsif ($encoding = /MacRoman/i) {
$bullet = "\xA5";
} elsif ($encoding = /UTF-8/i) {
$bullet = "\x{2022}";
}
if ($HeaderDoc::dumb_as_dirt) {
print STDERR "BASIC MODE: LIST FIXUP DISABLED\n" if ($numListDebug);
return $olddiscussion;
}
print STDERR "processing dicussion for ".$self->name().".\n" if ($numListDebug);
my @disclines = split(/([\n\r])/, $olddiscussion);
@disclines = splitmerge(\@disclines);
my $curpos = 0;
my $seekpos = 0;
my $nlines = scalar(@disclines);
my $oldinList = 0;
my $intextblock = 0;
my $inpre = 0;
if ($numListDebug) {
print STDERR "BEGIN DISCUSSION\n";
while ($curpos < $nlines) {
my $line = $disclines[$curpos++];
print STDERR "$line";
}
print STDERR "END DISCUSSION\n";
$curpos = 0;
}
while ($curpos < $nlines) {
my $line = $disclines[$curpos];
if ($line =~ /\@textblock/) {
$intextblock = 1;
print STDERR "intextblock -> 1\n" if ($numListDebug);
}
if ($line =~ /\@\/textblock/) {
$intextblock = 0;
print STDERR "intextblock -> 0\n" if ($numListDebug);
}
if ($line =~ /<pre>/) {
$inpre = 1;
print STDERR "inpre -> 1\n" if ($numListDebug);
}
if ($line =~ /<\/pre>/) {
$inpre = 0;
print STDERR "inpre -> 0\n" if ($numListDebug);
}
if ($intextblock || $inpre) {
$discussion .= $line;
} else {
print STDERR "LINE: \"$line\"\n" if ($numListDebug);
print STDERR "TOP OLDINLIST: $oldinList\n" if ($numListDebug);
if ($line =~ /^\s*((?:-)?\d+)[\)\.\:\s]/o) {
print STDERR "MAYBELIST: $line\n" if ($numListDebug);
my $inList = 1;
my $foundblank = 0;
my $basenum = $1;
$seekpos = $curpos + 1;
my $added = 0;
if (($seekpos >= $nlines) && !$oldinList) {
$discussion .= "$line";
$added = 1;
} else {
while (($seekpos < $nlines) && ($inList == 1)) {
my $scanline = $disclines[$seekpos];
print STDERR "INLIST: $inList, OLDINLIST: $oldinList\n" if ($numListDebug);
if ($scanline =~ /^<\/p><p>\s*$/so || $scanline =~ /^\s*$/s) {
$foundblank = 1;
print STDERR "BLANKLINE\n" if ($numListDebug);
} elsif ($scanline =~ /^\s*((?:-)?\d+)[\)\.\:\s]/o) {
$foundblank = 0;
if ($1 != ($basenum + 1)) {
print STDERR "NONCONTIG\n" if ($numListDebug);
if (!$oldinList) {
print STDERR "ADDED $line\n" if ($numListDebug);
$discussion .= "$line";
$added = 1;
}
$inList = 0;
} else {
print STDERR "CONTIG\n" if ($numListDebug);
$inList = 2;
}
} else {
if ($foundblank && ($scanline =~ /\S+/o)) {
print STDERR "LIST MAY END ON $scanline\n" if ($numListDebug);
print STDERR "BASENUM IS $basenum\n" if ($numListDebug);
$inList = 3;
}
}
$seekpos++;
}
}
if ($oldinList) {
$line =~ s/^\s*((?:-)?\d+)[\)\.\:\s]//so;
$basenum = $1;
$discussion .= "</li><li>$line";
print STDERR "LISTCONTINUES: $line\n" if ($numListDebug);
} elsif ($inList == 3) {
$discussion .= $line;
print STDERR "SINGLETON: $line\n" if ($numListDebug);
} elsif ($inList == 2) {
$line =~ s/^\s*((?:-)?\d+)[\)\.\:\s]//so;
$basenum = $1;
$discussion .= "<ol start=\"$basenum\"><li>$line";
print STDERR "FIRSTENTRY: $line\n" if ($numListDebug);
} elsif (!$added) {
$discussion .= $line;
}
if ($oldinList && !$inList) {
$discussion .= "</li></ol>";
}
$oldinList = $inList;
} elsif ($line =~ /^<\/p><p>\s*$/so || $line =~ /^\s*$/s) {
if ($oldinList == 3 || $oldinList == 1) {
print STDERR "OUTERBLANKLINE\n" if ($numListDebug);
$discussion .= "</li></ol>";
$oldinList = 0;
} else {
print STDERR "OIL: $oldinList\n" if ($numListDebug);
$discussion .= "$line";
}
} else {
print STDERR "TEXTLINE: \"$line\"\n" if ($numListDebug);
$discussion .= $line;
}
}
$curpos++;
}
if ($oldinList) {
$discussion .= "</li></ol>";
}
print STDERR "done processing dicussion for ".$self->name().".\n" if ($numListDebug);
return $discussion;
}
sub XMLdiscussion {
my $self = shift;
if (@_) {
my $discussion = "";
$discussion = shift;
$self->{DISCUSSION} = $discussion;
}
return $self->htmlToXML($self->{DISCUSSION});
}
sub declaration {
my $self = shift;
if (@_) {
$self->{DECLARATION} = shift;
}
return $self->{DECLARATION};
}
sub privateDeclaration {
my $self = shift;
if (@_) {
$self->{PRIVATEDECLARATION} = shift;
}
return $self->{PRIVATEDECLARATION};
}
sub genRefHTML($$$)
{
my $self = shift;
my $keystring = shift;
my $name = shift;
my $linktext = shift;
my $optional_expected_type = "";
my $of = $self->outputformat();
$self->outputformat("html");
my $result;
if (@_) {
$optional_expected_type = shift;
$result = $self->genRef($keystring, $name, $linktext, $optional_expected_type);
} else {
$result = $self->genRef($keystring, $name, $linktext);
}
$self->outputformat($of);
return $result;
}
sub genRefFromDeclaration($$$$)
{
my $self = shift;
my $keystring = shift;
my $name = shift;
my $linktext = shift;
my $optional_expected_type = "";
if (@_) {
$optional_expected_type = shift;
}
my $optional_return_only_ref = 0;
if (@_) {
$optional_return_only_ref = shift;
}
return $self->genRefCore($keystring, $name, $linktext, $optional_expected_type, $optional_return_only_ref, 1);
}
sub genRef($$$$)
{
my $self = shift;
my $keystring = shift;
my $name = shift;
my $linktext = shift;
my $optional_expected_type = "";
if (@_) {
$optional_expected_type = shift;
}
my $optional_return_only_ref = 0;
if (@_) {
$optional_return_only_ref = shift;
}
return $self->genRefCore($keystring, $name, $linktext, $optional_expected_type, $optional_return_only_ref, 0);
}
sub genRefCore($$$$$$)
{
my $self = shift;
my $keystring = shift;
my $name = shift;
my $linktext = shift;
my $expected_type = shift;
my $return_only_ref = shift;
my $fromDeclaration = shift;
my $fullpath = $self->fullpath();
my $linenum = $self->linenum();
my $tail = "";
my $xml = 0;
my $localDebug = 0;
print STDERR "NAME IS $name\n" if ($localDebug);
if ($self->outputformat() eq "hdxml") { $xml = 1; }
my $lang = $self->sublang();
my %parseTokens = %{parseTokens($self->lang(), $self->sublang())};
my $accessregexp = $parseTokens{accessregexp};
if ($name =~ /^[\d\[\]]/o) {
print STDERR "Silently fail[1]\n" if ($localDebug);
if ($return_only_ref) { return ""; }
return $linktext;
}
if (($name =~ /^[=|+-\/&^~!*]/o) || ($name =~ /^\s*\.\.\.\s*$/o)) {
print STDERR "Silently fail[2]\n" if ($localDebug);
if ($return_only_ref) { return ""; }
return $linktext;
}
if (length($accessregexp) && ($name =~ /$accessregexp(:)?/)) {
print STDERR "Silently fail[3]\n" if ($localDebug);
if ($return_only_ref) { return ""; }
return $linktext;
}
if ($name =~ s/\)\s*$//o) {
if ($linktext =~ s/\)\s*$//o) {
$tail = ")";
} else {
warn("$fullpath:$linenum: warning: Parenthesis in ref name, not in link text\n");
warn("name: $name) linktext: $linktext\n");
}
}
my $testing = 0;
if ($testing && ($name =~ /&/o || $name =~ /\(/o || $name =~ /\)/o || $name =~ /.:(~:)./o || $name =~ /;/o || $name eq "::" || $name =~ /^::/o)) {
my $classname = $self->name();
my $class = ref($self) || $self;
my $declaration = $self->declaration();
if (($name eq "(") && $class eq "HeaderDoc::PDefine") {
warn("$fullpath:$linenum: warning: bogus paren in #define\n");
} elsif (($name eq "(") && $class eq "HeaderDoc::Function") {
warn("$fullpath:$linenum: warning: bogus paren in function\n");
} elsif ($class eq "HeaderDoc::Function") {
warn("$fullpath:$linenum: warning: bogus paren in function\n");
} else {
warn("$fullpath:$linenum: warning: $fullpath $classname $class $keystring generates bad crossreference ($name). Dumping trace.\n");
$self->printObject();
}
}
if ($name =~ /^(.+)::(.+?)$/o) {
my $classpart = $1;
my $type = $2;
if ($linktext !~ /::/o) {
warn("$fullpath:$linenum: warning: Bogus link text generated for item containing class separator. Ignoring.\n");
}
my $ret = $self->genRef("class", $classpart, $classpart);
$ret .= "::";
my $ref1 = $self->genRefSub($lang, "instm", $type, $classpart);
my $ref2 = $self->genRefSub($lang, "clm", $type, $classpart);
my $ref3 = $self->genRefSub($lang, "func", $type, "");
my $ref4 = $self->genRefSub($lang, "ftmplt", $type, $classpart);
my $ref5 = $self->genRefSub($lang, "defn", $type, "");
my $ref6 = $self->genRefSub($lang, "macro", $type, "");
my $ref7 = $self->genRefSub($lang, "cl", $type, $classpart);
my $ref8 = $self->genRefSub($lang, "tdef", $type, "");
my $ref9 = $self->genRefSub($lang, "tag", $type, "");
my $ref10 = $self->genRefSub($lang, "econst", $type, "");
my $ref11 = $self->genRefSub($lang, "struct", $type, "");
my $ref12 = $self->genRefSub($lang, "data", $type, $classpart);
my $ref13 = $self->genRefSub($lang, "clconst", $type, $classpart);
my $ref14 = $self->genRefSub($lang, "intfm", $type, $classpart);
my $ref99 = $self->genRefSub("doc/com", "intfm", $name, $classpart);
my $lp = "$ref1 $ref2 $ref3 $ref4 $ref5 $ref6 $ref7 $ref8 $ref9 $ref10 $ref11 $ref12 $ref13 $ref14 $ref99";
if ($return_only_ref) { return $lp; }
if (!$xml) {
$ret .= "<!-- a logicalPath=\"$lp\" machineGenerated=\"true\" -->$type<!-- /a -->";
} else {
$ret .= "<hd_link logicalPath=\"$lp\">$type</hd_link>";
}
print STDERR "Double-colon case\n" if ($localDebug);
return $ret.$tail;
}
my $ret = "";
my $apiUIDPrefix = HeaderDoc::APIOwner->apiUIDPrefix();
my $type = "";
my $className = "";
my $classNameImplicit = 0;
my $apio = $self->apiOwner();
my $apioclass = ref($apio) || $apio;
if ($apioclass ne "HeaderDoc::Header") {
$classNameImplicit = 1;
if ($apio->can("className")) { $className = $apio->className();
} else {
$className = $apio->name();
}
}
my $class_or_enum_check = " $keystring ";
my ($case_sensitive, $keywordhashref) = $self->keywords();
my @keywords = keys %{$keywordhashref};
foreach my $keyword (@keywords) {
if ($case_sensitive) {
$class_or_enum_check =~ s/(^|\s+)\Q$keyword\E(\s+|$)/ /sg;
} else {
$class_or_enum_check =~ s/(^|\s+)\Q$keyword\E(\s+|$)/ /sgi;
}
}
$class_or_enum_check =~ s/\s*//smgo;
if (length($class_or_enum_check)) {
SWITCH: {
($keystring =~ /type/o && $lang eq "pascal") && do { $type = "tdef"; last SWITCH; };
($keystring =~ /type/o && $lang eq "MIG") && do { $type = "tdef"; last SWITCH; };
($keystring =~ /record/o && $lang eq "pascal") && do { $type = "struct"; last SWITCH; };
($keystring =~ /procedure/o && $lang eq "pascal") && do { $type = "*"; last SWITCH; };
($keystring =~ /of/o && $lang eq "pascal") && do { $type = "*"; last SWITCH; };
($keystring =~ /typedef/o) && do { $type = "tdef"; last SWITCH; };
(($keystring =~ /sub/o) && ($lang eq "perl")) && do { $type = "*"; last SWITCH; };
($keystring =~ /function/o) && do { $type = "*"; last SWITCH; };
($keystring =~ /typedef/o) && do { $type = "tdef"; last SWITCH; };
($keystring =~ /struct/o) && do { $type = "tag"; last SWITCH; };
($keystring =~ /union/o) && do { $type = "tag"; last SWITCH; };
($keystring =~ /operator/o) && do { $type = "*"; last SWITCH; };
($keystring =~ /enum/o) && do { $type = "tag"; last SWITCH; };
($keystring =~ /protocol/o) && do { $type = "intf"; $classNameImplicit = 0; $className=$name; $name=""; last SWITCH; };
($keystring =~ /class/o) && do { $type = "cl"; $classNameImplicit = 0; $className=$name; $name=""; last SWITCH; };
($keystring =~ /
print STDERR "Keyword case\n" if ($localDebug);
if ($return_only_ref) { return ""; }
return $linktext.$tail;
};
{
$type = "";
my $name = $self->name();
warn "$fullpath:$linenum: warning: keystring ($keystring) in $name type link markup\n";
if ($return_only_ref) { return ""; }
return $linktext.$tail;
}
}
if ($type eq "*") {
my $lp = "";
if ($className ne "") {
$lp .= " ".$self->genRefSub($lang, "instm", $name, $className);
$lp .= " ".$self->genRefSub($lang, "clm", $name, $className);
}
$lp .= " ".$self->genRefSub($lang, "func", $name, "");
$lp .= " ".$self->genRefSub($lang, "ftmplt", $name, $className);
$lp .= " ".$self->genRefSub($lang, "defn", $name, $className);
$lp .= " ".$self->genRefSub($lang, "macro", $name, $className);
$lp .= " ".$self->genRefSub("doc/com", "intfm", $name, $className);
$lp =~ s/^ //s;
print STDERR "Class or enum check case: Type is \"*\" case\n" if ($localDebug);
if ($return_only_ref) { return $lp; }
if (!$xml) {
return "<!-- a logicalPath=\"$lp\" machineGenerated=\"true\" -->$linktext<!-- /a -->".$tail;
} else {
return "<hd_link logicalPath=\"$lp\">$linktext</hd_link>".$tail;
}
} else {
print STDERR "Class or enum check case: Type is not \"*\" case\n" if ($localDebug);
my $lp = $self->genRefSub($lang, $type, $className, $name);
if ($return_only_ref) { return $lp; }
if (!$xml) {
return "<!-- a logicalPath=\"" . $lp . "\" machineGenerated=\"true\" -->$linktext<!-- /a -->".$tail;
} else {
return "<hd_link logicalPath=\"" . $lp . "\">$linktext</hd_link>".$tail;
}
}
} else {
my $typerefs = $self->genRefSub($lang, "cl", $name, "");
$typerefs .= " ".$self->genRefSub($lang, "cl", $name, $className) if (($className ne "") && !$classNameImplicit);
$typerefs .= " ".$self->genRefSub($lang, "tdef", $name, "");
$typerefs .= " ".$self->genRefSub($lang, "tag", $name, "");
$typerefs .= " ".$self->genRefSub($lang, "struct", $name, "");
$typerefs .= " ".$self->genRefSub($lang, "intf", $name, "");
my $varrefs = $self->genRefSub($lang, "econst", $name, "");
$varrefs .= " ". $self->genRefSub($lang, "data", $name, $className);
if ($classNameImplicit) {
$varrefs .= " ".$self->genRefSub($lang, "data", $name, "");
}
$varrefs .= " ".$self->genRefSub($lang, "clconst", $name, $className);
my $functionrefs = $self->genRefSub($lang, "instm", $name, $className);
$functionrefs .= " ".$self->genRefSub($lang, "clm", $name, $className);
$functionrefs .= " ".$self->genRefSub($lang, "intfcm", $name, $className);
$functionrefs .= " ".$self->genRefSub($lang, "intfm", $name, $className);
$functionrefs .= " ".$self->genRefSub($lang, "func", $name, "");
$functionrefs .= " ".$self->genRefSub($lang, "ftmplt", $name, $className);
$functionrefs .= " ".$self->genRefSub($lang, "defn", $name, "");
$functionrefs .= " ".$self->genRefSub($lang, "macro", $name, "");
my $docrefs = $self->genRefSub("doc/com", "intfm", $name, $className);
my $anysymbol = $self->genRefSub("doc", "anysymbol", $name);
my $masterref = "$typerefs $varrefs $functionrefs $docrefs $anysymbol";
print STDERR "Default case (OET: $expected_type)" if ($localDebug);
if (length($expected_type)) {
SWITCH: {
($expected_type eq "string") && do {
if ($return_only_ref) { return ""; }
return $linktext.$tail;
};
($expected_type eq "char") && do {
if ($return_only_ref) { return ""; }
return $linktext.$tail;
};
($expected_type eq "comment") && do {
if ($return_only_ref) { return ""; }
return $linktext.$tail;
};
($expected_type eq "preprocessor") && do {
last SWITCH;
};
($expected_type eq "number") && do {
if ($return_only_ref) { return ""; }
return $linktext.$tail;
};
($expected_type eq "keyword") && do {
if ($return_only_ref) { return ""; }
return $linktext.$tail;
};
($expected_type eq "function") && do {
$masterref = $functionrefs." ".$anysymbol;
last SWITCH;
};
($expected_type eq "var") && do {
if ($fromDeclaration) { $anysymbol = ""; }
$masterref = $varrefs." ".$anysymbol;
last SWITCH;
};
($expected_type eq "template") && do {
$masterref = $typerefs." ".$anysymbol;
last SWITCH;
};
($expected_type eq "type") && do {
$masterref = $typerefs." ".$anysymbol;
last SWITCH;
};
($expected_type eq "param") && do {
if ($return_only_ref) { return ""; }
return $linktext.$tail;
};
($expected_type eq "ignore") && do {
if ($return_only_ref) { return ""; }
return $linktext.$tail;
};
{
warn("$fullpath:$linenum: warning: Unknown reference class \"$expected_type\" in genRef\n");
}
}
}
print STDERR "Default case: No OET. MR IS $masterref\n" if ($localDebug);
$masterref =~ s/\s+/ /g;
if ($return_only_ref) { return $masterref; }
if ($xml) {
return "<hd_link logicalPath=\"$masterref\">$linktext</hd_link>".$tail;
} else {
return "<!-- a logicalPath=\"$masterref\" machineGenerated=\"true\" -->$linktext<!-- /a -->".$tail;
}
}
}
sub keywords
{
my $self = shift;
my $class = ref($self) || $self;
my $localDebug = 0;
my $parmDebug = 0;
my $lang = $self->lang();
my $sublang = $self->sublang();
my $fullpath = $self->fullpath();
my $linenum = $self->linenum();
my $case_sensitive = 1;
if (!$self->isAPIOwner()) {
my $apio = $self->apiOwner();
return $apio->keywords();
}
if ($self->{KEYWORDHASH}) { return ($self->{CASESENSITIVE}, $self->{KEYWORDHASH}); }
print STDERR "keywords\n" if ($localDebug);
my %RubyKeywords = (
"assert" => 1,
"break" => 1,
"while" => 1,
"if" => 1,
"for" => 1,
"until" => 1,
"break" => 1,
"redo" => 1,
"retry" => 1,
"nil" => 1,
"true" => 1,
"false" => 1,
"class" => 1,
"module" => 1);
my %CKeywords = (
"assert" => 1,
"break" => 1,
"auto" => 1, "const" => 1, "enum" => 1, "extern" => 7, "inline" => 1,
"__inline__" => 1, "__inline" => 1, "__asm" => 2, "__asm__" => 2,
"__attribute__" => 2, "__typeof__" => 6,
"register" => 1, "signed" => 1, "static" => 8, "struct" => 1, "typedef" => 1,
"union" => 1, "unsigned" => 1, "volatile" => 1, "#define" => 1,
"#ifdef" => 1, "#ifndef" => 1, "#if" => 1, "#endif" => 1,
"#undef" => 1, "#elif" => 1, "#error" => 1, "#warning" => 1,
"#pragma" => 1, "#include" => 1, "#import" => 1 , "NULL" => 1,
"true" => 1, "false" => 1);
my %CppKeywords = (%CKeywords,
("class" => 1,
"friend" => 1,
"mutable" => 1,
"namespace" => 1,
"operator" => 1,
"private" => 1,
"protected" => 1,
"public" => 1,
"template" => 1,
"virtual" => 1));
my %ObjCKeywords = (%CKeywords,
("\@class" => 1,
"\@interface" => 1,
"\@protocol" => 1,
"\@property" => 1,
"\@public" => 1,
"\@private" => 1,
"\@protected" => 1,
"\@package" => 1,
"\@synthesize" => 1,
"\@dynamic" => 1,
"\@optional" => 1,
"\@required" => 1,
"nil" => 1,
"YES" => 1,
"NO" => 1 ));
my %phpKeywords = (%CKeywords, ("function" => 1));
my %javascriptKeywords = (
"abstract" => 1,
"break" => 1,
"case" => 1,
"catch" => 1,
"class" => 1,
"const" => 1,
"continue" => 1,
"debugger" => 1,
"default" => 1,
"delete" => 1,
"do" => 1,
"else" => 1,
"enum" => 1,
"export" => 1,
"extends" => 3,
"false" => 1,
"final" => 1,
"finally" => 1,
"for" => 1,
"function" => 1,
"goto" => 1,
"if" => 1,
"implements" => 4,
"import" => 1,
"in" => 1,
"instanceof" => 1,
"interface" => 1,
"native" => 1,
"new" => 1,
"null" => 1,
"package" => 1,
"private" => 1,
"protected" => 1,
"public" => 1,
"return" => 1,
"static" => 8,
"super" => 1,
"switch" => 1,
"synchronized" => 1,
"this" => 1,
"throw" => 1,
"throws" => 1,
"transient" => 1,
"true" => 1,
"try" => 1,
"typeof" => 1,
"var" => 1,
"volatile" => 1,
"while" => 1,
"with" => 1);
my %javaKeywords = (
"abstract" => 1,
"assert" => 1,
"break" => 1,
"case" => 1,
"catch" => 1,
"class" => 1,
"const" => 1,
"continue" => 1,
"default" => 1,
"do" => 1,
"else" => 1,
"enum" => 1,
"extends" => 3,
"false" => 1,
"final" => 1,
"finally" => 1,
"for" => 1,
"goto" => 1,
"if" => 1,
"implements" => 4,
"import" => 1,
"instanceof" => 1,
"interface" => 1,
"native" => 1,
"new" => 1,
"package" => 1,
"private" => 1,
"protected" => 1,
"public" => 1,
"return" => 1,
"static" => 8,
"strictfp" => 1,
"super" => 1,
"switch" => 1,
"synchronized" => 1,
"this" => 1,
"throw" => 1,
"throws" => 1,
"transient" => 1,
"true" => 1,
"try" => 1,
"volatile" => 1,
"while" => 1);
my %tclKeywords = ( "method" => 1, "constructor" => 1, "proc" => 1, "attribute" => 1 ); my %perlKeywords = ( "sub" => 1, "my" => 8, "next" => 1, "last" => 1,
"package" => 1 );
my %shellKeywords = ( "sub" => 1, "alias" => 1,
"set" => 1, "alias" => 1,
"if" => 1, "fi" => 1,
"case" => 9, "esac" => 10
);
my %cshKeywords = ( "set" => 1, "setenv" => 1, "alias" => 1);
my %pythonKeywords = ( "and" => 1, "assert" => 1, "break" => 1,
"class" => 1, "continue" => 1, "def" => 1, "del" => 1,
"elif" => 1, "else" => 1, "except" => 1, "exec" => 1,
"finally" => 1, "for" => 1, "from" => 1, "global" => 1,
"if" => 1, "import" => 1, "in" => 1, "is" => 1,
"lambda" => 1, "not" => 1, "or" => 1, "pass" => 1,
"print" => 1, "raise" => 1, "return" => 1, "try" => 1,
"while" => 1, "yield" => 1
);
my %applescriptKeywords = ( "about" => 1, "above" => 1, "after" => 1,
"against" => 1, "and" => 1, "apart from" => 1, "around" => 1,
"as" => 1, "aside from" => 1, "at" => 1, "back" => 1, "before" => 1,
"beginning" => 1, "behind" => 1, "below" => 1, "beneath" => 1,
"beside" => 1, "between" => 1, "but" => 1, "by" => 1,
"considering" => 1, "contain" => 1, "contains" => 1, "continue" => 1,
"copy" => 1, "div" => 1, "does" => 1, "eighth" => 1, "else" => 1,
"end" => 1, "equal" => 1, "equals" => 1, "error" => 1, "every" => 1,
"exit" => 1, "false" => 1, "fifth" => 1, "first" => 1, "for" => 1,
"fourth" => 1, "from" => 1, "front" => 1, "get" => 1, "given" => 1,
"global" => 1, "if" => 1, "ignoring" => 1, "in" => 1,
"instead of" => 1, "into" => 1, "is" => 1, "it" => 1, "its" => 1,
"last" => 1, "local" => 1, "me" => 1, "middle" => 1, "mod" => 1,
"my" => 1, "ninth" => 1, "not" => 1, "of" => 1, "on" => 1, "onto" => 1,
"or" => 1, "out of" => 1, "over" => 1, "prop" => 1, "property" => 1,
"put" => 1, "ref" => 1, "reference" => 1, "repeat" => 1, "return" => 1,
"returning" => 1, "script" => 1, "second" => 1, "set" => 1,
"seventh" => 1, "since" => 1, "sixth" => 1, "some" => 1, "tell" => 1,
"tenth" => 1, "that" => 1, "the" => 1, "then" => 1, "third" => 1,
"through" => 1, "thru" => 1, "timeout" => 1, "times" => 1, "to" => 1,
"transaction" => 1, "true" => 1, "try" => 1, "until" => 1,
"where" => 1, "while" => 1, "whose" => 1, "with" => 1, "without" => 1
);
my %pascalKeywords = (
"absolute" => 1, "abstract" => 1, "all" => 1, "and" => 1, "and_then" => 1,
"array" => 1, "asm" => 1, "begin" => 1, "bindable" => 1, "case" => 1, "class" => 1,
"const" => 1, "constructor" => 1, "destructor" => 1, "div" => 1, "do" => 1,
"downto" => 1, "else" => 1, "end" => 1, "export" => 1, "file" => 1, "for" => 1,
"function" => 1, "goto" => 1, "if" => 1, "import" => 1, "implementation" => 1,
"inherited" => 1, "in" => 1, "inline" => 1, "interface" => 1, "is" => 1, "label" => 1,
"mod" => 1, "module" => 1, "nil" => 1, "not" => 1, "object" => 1, "of" => 1, "only" => 1,
"operator" => 1, "or" => 1, "or_else" => 1, "otherwise" => 1, "packed" => 1, "pow" => 1,
"procedure" => 1, "program" => 1, "property" => 1, "qualified" => 1, "record" => 1,
"repeat" => 1, "restricted" => 1, "set" => 1, "shl" => 1, "shr" => 1, "then" => 1, "to" => 1,
"type" => 1, "unit" => 1, "until" => 1, "uses" => 1, "value" => 1, "var" => 1, "view" => 1,
"virtual" => 1, "while" => 1, "with" => 1, "xor" => 1);
my %IDLKeywords = (
"abstract" => 1, "any" => 1, "attribute" => 1, "case" => 1,
"component" => 1, "const" => 1, "consumes" => 1, "context" => 1, "custom" => 1, "default" => 1,
"exception" => 1, "emits" => 1, "enum" => 1, "eventtype" => 1, "factory" => 1, "FALSE" => 1,
"finder" => 1, "fixed" => 1,
"getraises" => 5, "getter" => 1, "home" => 1, "import" => 1, "in" => 1, "inout" => 1, "interface" => 1,
"local" => 1, "long" => 1, "module" => 1, "multiple" => 1, "native" => 1, "Object" => 1,
"octet" => 1, "oneway" => 1, "out" => 1, "primarykey" => 1, "private" => 1, "provides" => 1,
"public" => 1, "publishes" => 1, "raises" => 5, "readonly" => 1, "setraises" => 5, "setter" => 1, "sequence" => 1,
"struct" => 1, "supports" => 1, "switch" => 1, "TRUE" => 1, "truncatable" => 1, "typedef" => 1,
"typeid" => 1, "typeprefix" => 1, "unsigned" => 1, "union" => 1, "uses" => 1, "ValueBase" => 1,
"valuetype" => 1,
"#define" => 1,
"#ifdef" => 1, "#ifndef" => 1, "#if" => 1, "#endif" => 1,
"#undef" => 1, "#elif" => 1, "#error" => 1, "#warning" => 1,
"#pragma" => 1, "#include" => 1, "#import" => 1 );
my %MIGKeywords = (
"routine" => 1, "simpleroutine" => 1, "countinout" => 1, "inout" => 1, "in" => 1, "out" => 1,
"subsystem" => 1, "skip" => 1, "#define" => 1,
"#ifdef" => 1, "#ifndef" => 1, "#if" => 1, "#endif" => 1,
"#undef" => 1, "#elif" =>1, "#error" => 1, "#warning" => 1,
"#pragma" => 1, "#include" => 1, "#import" => 1, "import" => 1, "simport" => 1, "type" => 1,
"skip" => 1, "serverprefix" => 1, "serverdemux" => 1, "userprefix" => 1 );
my $objC = 0;
my %keywords = %CKeywords;
if ($lang eq "applescript") {
%keywords = %applescriptKeywords;
}
if ($lang eq "python") {
%keywords = %pythonKeywords;
}
if ($lang eq "ruby") {
%keywords = %RubyKeywords;
}
if ($lang eq "C") {
SWITCH: {
($sublang eq "cpp") && do { %keywords = %CppKeywords; last SWITCH; };
($sublang eq "C") && do { last SWITCH; };
($sublang =~ /^occ/o) && do { %keywords = %ObjCKeywords; $objC = 1; last SWITCH; }; ($sublang eq "intf") && do { %keywords = %ObjCKeywords; $objC = 1; last SWITCH; };
($sublang eq "MIG") && do { %keywords = %MIGKeywords; last SWITCH; };
($sublang eq "IDL") && do { %keywords = %IDLKeywords; last SWITCH; };
warn "$fullpath:$linenum: warning: Unknown language ($lang:$sublang)\n";
}
}
if ($lang eq "Csource") {
SWITCH: {
($sublang eq "Csource") && do { last SWITCH; };
($sublang eq "cpp") && do { %keywords = %CppKeywords; last SWITCH; };
($sublang eq "C") && do { last SWITCH; };
($sublang =~ /^occ/o) && do { %keywords = %ObjCKeywords; $objC = 1; last SWITCH; }; ($sublang eq "intf") && do { %keywords = %ObjCKeywords; $objC = 1; last SWITCH; };
warn "$fullpath:$linenum: warning: Unknown language ($lang:$sublang)\n";
}
}
if ($lang eq "php") {
SWITCH: {
($sublang eq "php") && do { %keywords = %phpKeywords; last SWITCH; };
warn "$fullpath:$linenum: warning: Unknown language ($lang:$sublang)\n";
}
}
if ($lang eq "java") {
SWITCH: {
($sublang eq "java") && do { %keywords = %javaKeywords; last SWITCH; };
($sublang eq "javascript") && do { %keywords = %javascriptKeywords; last SWITCH; };
warn "$fullpath:$linenum: warning: Unknown language ($lang:$sublang)\n";
}
}
if ($lang eq "tcl") {
SWITCH: {
($sublang eq "tcl") && do { %keywords = %tclKeywords; last SWITCH; };
warn "$fullpath:$linenum: warning: Unknown language ($lang:$sublang)\n";
}
}
if ($lang eq "perl") {
SWITCH: {
($sublang eq "perl") && do { %keywords = %perlKeywords; last SWITCH; };
warn "$fullpath:$linenum: warning: Unknown language ($lang:$sublang)\n";
}
}
if ($lang eq "shell") {
SWITCH: {
($sublang eq "csh") && do { %keywords = %cshKeywords; last SWITCH; };
($sublang eq "shell") && do { %keywords = %shellKeywords; last SWITCH; };
warn "$fullpath:$linenum: warning: Unknown language ($lang:$sublang)\n";
}
}
if ($lang eq "pascal") {
%keywords = %pascalKeywords;
$case_sensitive = 0;
}
if ($lang eq "C" && $sublang eq "MIG") {
$case_sensitive = 0;
}
$self->{KEYWORDHASH} = \%keywords;
$self->{CASESENSITIVE} = $case_sensitive;
return ($case_sensitive, \%keywords);
}
sub htmlToXML
{
my $self = shift;
my $htmldata = shift;
my $droppara = shift;
my $debugname = shift;
my $localDebug = 0;
if ($htmldata !~ /[<>&]/o) {
print STDERR "FASTPATH FOR $debugname\n" if ($localDebug);
return $htmldata;
}
my $result = html2xhtml($htmldata, $self->encoding(), $debugname);
print STDERR "FOR:\n$htmldata\nENDFOR\nRETURNING:\n$result\nENDRETURN\n" if ($localDebug);
return $result;
}
sub textToXML
{
my $self = shift;
my $textdata = shift;
$textdata =~ s/&/&/sgo;
$textdata =~ s/</</sgo;
$textdata =~ s/>/>/sgo;
return $textdata;
}
sub declarationInHTML {
my $self = shift;
my $class = ref($self) || $self;
my $localDebug = 0;
my $xml = 0;
if ($self->outputformat() eq "hdxml") { $xml = 1; }
if (@_) {
my $disable_styles = 0;
if ($xml) {
my $xmldec = shift;
if (1 || $HeaderDoc::use_styles && !$disable_styles) {
my $parseTree_ref = $self->parseTree();
my $parseTree = ${$parseTree_ref};
bless($parseTree, "HeaderDoc::ParseTree");
if ($self->can("isBlock") && $self->isBlock()) {
$xmldec = "";
my @tree_refs = @{$self->parseTreeList()};
foreach my $tree_ref (@tree_refs) {
my $tree = ${$tree_ref};
bless($tree, "HeaderDoc::ParseTree");
$xmldec .= $tree->xmlTree($self->preserve_spaces(), $self->hideContents())."\n";
}
} else {
$xmldec = $parseTree->xmlTree($self->preserve_spaces(), $self->hideContents());
}
$self->{DECLARATIONINHTML} = $xmldec;
} else {
$self->{DECLARATIONINHTML} = $self->textToXML($xmldec);
}
return $xmldec;
}
my $declaration = shift;
if (1 || $HeaderDoc::use_styles && !$disable_styles) {
if ($self->can("isBlock") && $self->isBlock()) {
my @defines = $self->parsedParameters();
$declaration = "";
my @tree_refs = @{$self->parseTreeList()};
foreach my $tree_ref (@tree_refs) {
my $tree = ${$tree_ref};
bless($tree, "HeaderDoc::ParseTree");
$declaration .= $tree->htmlTree($self->preserve_spaces(), $self->hideContents())."\n";
}
} else {
my $parseTree_ref = $self->parseTree();
my $parseTree = ${$parseTree_ref};
bless($parseTree, "HeaderDoc::ParseTree");
$declaration = $parseTree->htmlTree($self->preserve_spaces(), $self->hideContents());
}
}
$self->{DECLARATIONINHTML} = $declaration;
}
return $self->{DECLARATIONINHTML};
}
sub parseTree {
my $self = shift;
if (@_) {
my $parsetree = shift;
if ($self->can("isBlock") && $self->isBlock()) {
$self->addParseTree($parsetree);
}
$self->{PARSETREE} = $parsetree;
}
return $self->{PARSETREE};
}
sub parseTreeList
{
my $self = shift;
my $localDebug = 0;
if ($localDebug) {
print STDERR "OBJ ".$self->name().":\n";
foreach my $treeref (@{$self->{PARSETREELIST}}) {
my $tree = ${$treeref};
bless($tree, "HeaderDoc::ParseTree");
print STDERR "PARSE TREE: $tree\n";
$tree->dbprint();
}
}
if ($self->{PARSETREELIST}) {
return $self->{PARSETREELIST};
}
if (!$HeaderDoc::running_test) {
die("No parse trees for object $self.\n".
"Name is ".$self->name().". This usually\n".
"points to a headerdoc comment before a #if whose contents are not a\n".
"complete declaraction. This is a fatal error. Exiting.\n");
}
my @arr = ();
return \@arr;
}
sub addParseTree
{
my $self = shift;
my $tree = shift;
my $localDebug = 0;
push(@{$self->{PARSETREELIST}}, $tree);
if ($localDebug) {
print STDERR "OBJ ".$self->name().":\n";
foreach my $treeref (@{$self->{PARSETREELIST}}) {
my $tree = ${$treeref};
print STDERR "PARSE TREE: $tree\n";
bless($tree, "HeaderDoc::ParseTree");
$tree->dbprint();
}
}
}
sub fixParseTrees
{
my $self = shift;
my $localDebug = 0;
if (!$self->{PARSETREE}) {
return;
}
my @trees = ();
if ($self->{PARSETREELIST}) {
@trees = @{$self->{PARSETREELIST}};
}
my $match = 0;
my $searchtree = ${$self->{PARSETREE}};
print STDERR "Looking for tree $searchtree\n" if ($localDebug);
foreach my $treeref (@trees) {
my $tree = ${$treeref};
print STDERR "Comparing with $tree\n" if ($localDebug);
if ($tree == $searchtree) { $match = 1; }
}
if (!$match) {
print STDERR "Not found. Adding\n" if ($localDebug);
$self->addParseTree($self->{PARSETREE});
} else {
print STDERR "Found. Not adding\n" if ($localDebug);
}
}
sub availabilityAuto
{
my $self = shift;
my $orig = shift;
my $localDebug = 0;
my $fullpath = $self->fullpath();
print STDERR "GENERATING AVAILABILITY FOR $self FP ".$self->fullpath()."\n" if ($localDebug);
my $rangeref = $HeaderDoc::perHeaderRanges{$fullpath};
if ($localDebug) {
print STDERR "FULLPATH: $fullpath\n";
foreach my $x (keys %HeaderDoc::perHeaderRanges) {
print STDERR "PHR{$x} = ".$HeaderDoc::perHeaderRanges{$x}."\n";
}
}
my @ranges = @{$rangeref};
my $linenum = $self->linenum();
my $string = "";
print STDERR "IN AVAILABILITYAUTO (name is ".$self->name()."\n" if ($localDebug);
foreach my $rangeref (@ranges) {
print STDERR "RANGE $rangeref\n" if ($localDebug);
my $range = ${$rangeref};
bless($range, "HeaderDoc::LineRange");
if ($range->inrange($linenum)) {
my $newbit = $range->text();
my @pieces = split(/\;/, $newbit);
foreach my $piece (@pieces) {
my $nvpiece = $piece; $nvpiece =~ s/10\..*$//s;
my $found = -1;
if (($found = index(lc $orig, lc $nvpiece)) == -1) {
if (($found = index(lc $string, lc $nvpiece)) == -1) {
if (length($string)) {
$string .= " ";
}
$string .= $piece.".";
}
}
}
}
}
print STDERR "LEAVING AVAILABILITYAUTO (RETURN IS $string)\n" if ($localDebug);
return $string;
}
sub availability {
my $self = shift;
if (@_) {
$self->{AVAILABILITY} = shift;
}
my $string = $self->{AVAILABILITY};
my $add = $self->availabilityAuto($string);
if (length($string) && length($add)) {
$string .= " ";
}
return $string.$add;
}
sub lang {
my $self = shift;
if (@_) {
$self->{LANG} = shift;
}
return $self->{LANG};
}
sub sublang {
my $self = shift;
if (@_) {
my $sublang = shift;
if ($sublang eq "occCat") { $sublang = "occ"; }
$self->{SUBLANG} = $sublang;
}
return $self->{SUBLANG};
}
sub updated {
my $self = shift;
my $localdebug = 0;
if (@_) {
my $updated = shift;
my $month; my $day; my $year;
$month = $day = $year = $updated;
print STDERR "updated is $updated\n" if ($localdebug);
if (!($updated =~ /\d\d\d\d-\d\d-\d\d/o )) {
if (!($updated =~ /\d\d-\d\d-\d\d\d\d/o )) {
if (!($updated =~ /\d\d-\d\d-\d\d/o )) {
my $fullpath = $self->fullpath();
my $linenum = $self->linenum();
warn "$fullpath:$linenum: warning: Bogus date format: $updated.\n";
warn "$fullpath:$linenum: warning: Valid formats are MM-DD-YYYY, MM-DD-YY, and YYYY-MM-DD\n";
return $self->{UPDATED};
} else {
$month =~ s/(\d\d)-\d\d-\d\d/$1/smog;
$day =~ s/\d\d-(\d\d)-\d\d/$1/smog;
$year =~ s/\d\d-\d\d-(\d\d)/$1/smog;
my $century;
$century = `date +%C`;
$century *= 100;
$year += $century;
print STDERR "YEAR: $year" if ($localdebug);
}
} else {
print STDERR "03-25-2003 case.\n" if ($localdebug);
$month =~ s/(\d\d)-\d\d-\d\d\d\d/$1/smog;
$day =~ s/\d\d-(\d\d)-\d\d\d\d/$1/smog;
$year =~ s/\d\d-\d\d-(\d\d\d\d)/$1/smog;
}
} else {
$year =~ s/(\d\d\d\d)-\d\d-\d\d/$1/smog;
$month =~ s/\d\d\d\d-(\d\d)-\d\d/$1/smog;
$day =~ s/\d\d\d\d-\d\d-(\d\d)/$1/smog;
}
$month =~ s/\n//smog;
$day =~ s/\n//smog;
$year =~ s/\n//smog;
$month =~ s/\s*//smog;
$day =~ s/\s*//smog;
$year =~ s/\s*//smog;
my $invalid = 0;
my $mdays = 28;
if ($month == 2) {
if ($year % 4) {
$mdays = 28;
} elsif ($year % 100) {
$mdays = 29;
} elsif ($year % 400) {
$mdays = 28;
} else {
$mdays = 29;
}
} else {
my $bitcheck = (($month & 1) ^ (($month & 8) >> 3));
if ($bitcheck) {
$mdays = 31;
} else {
$mdays = 30;
}
}
if ($month > 12 || $month < 1) { $invalid = 1; }
if ($day > $mdays || $day < 1) { $invalid = 1; }
if ($year < 1970) { $invalid = 1; }
if ($invalid) {
my $fullpath = $self->fullpath();
my $linenum = $self->linenum();
warn "$fullpath:$linenum: warning: Invalid date (year = $year, month = $month, day = $day).\n";
warn "$fullpath:$linenum: warning: Valid formats are MM-DD-YYYY, MM-DD-YY, and YYYY-MM-DD\n";
return $self->{UPDATED};
} else {
$self->{UPDATED} = HeaderDoc::HeaderElement::strdate($month-1, $day, $year, $self->encoding());
print STDERR "date set to ".$self->{UPDATED}."\n" if ($localdebug);
}
}
return $self->{UPDATED};
}
sub linkageState {
my $self = shift;
if (@_) {
$self->{LINKAGESTATE} = shift;
}
return $self->{LINKAGESTATE};
}
sub accessControl {
my $self = shift;
if (@_) {
$self->{ACCESSCONTROL} = shift;
}
return $self->{ACCESSCONTROL};
}
sub printObject {
my $self = shift;
my $dec = $self->declaration();
print STDERR "------------------------------------\n";
print STDERR "HeaderElement\n";
print STDERR "name: $self->{NAME}\n";
print STDERR "abstract: $self->{ABSTRACT}\n";
print STDERR "declaration: $dec\n";
print STDERR "declaration in HTML: $self->{DECLARATIONINHTML}\n";
print STDERR "discussion: $self->{DISCUSSION}\n";
print STDERR "linkageState: $self->{LINKAGESTATE}\n";
print STDERR "accessControl: $self->{ACCESSCONTROL}\n\n";
print STDERR "Tagged Parameters:\n";
my $taggedParamArrayRef = $self->{TAGGEDPARAMETERS};
if ($taggedParamArrayRef) {
my $arrayLength = @{$taggedParamArrayRef};
if ($arrayLength > 0) {
&printArray(@{$taggedParamArrayRef});
}
print STDERR "\n";
}
my $fieldArrayRef = $self->{CONSTANTS};
if ($fieldArrayRef) {
my $arrayLength = @{$fieldArrayRef};
if ($arrayLength > 0) {
&printArray(@{$fieldArrayRef});
}
print STDERR "\n";
}
}
sub linkfix {
my $self = shift;
my $inpString = shift;
my @parts = split(/\</, $inpString);
my $first = 1;
my $outString = "";
my $localDebug = 0;
print STDERR "Parts:\n" if ($localDebug);
foreach my $part (@parts) {
print STDERR "$part\n" if ($localDebug);
if ($first) {
$outString .= $part;
$first = 0;
} else {
if ($part =~ /^\s*A\s+/sio) {
$part =~ /^(.*?>)/so;
my $linkpart = $1;
my $rest = $part;
$rest =~ s/^\Q$linkpart\E//s;
print STDERR "Found link.\nlinkpart: $linkpart\nrest: $rest\n" if ($localDebug);
if ($linkpart =~ /target\=\".*\"/sio) {
print STDERR "link ok\n" if ($localDebug);
$outString .= "<$part";
} else {
print STDERR "needs fix.\n" if ($localDebug);
$linkpart =~ s/\>$//so;
$outString .= "<$linkpart target=\"_top\">$rest";
}
} else {
$outString .= "<$part";
}
}
}
return $outString;
}
sub strdate($$$$)
{
my $month = shift;
my $day = shift;
my $year = shift;
my $encoding = shift;
my $format = $HeaderDoc::datefmt;
if (!defined $format) {
$format = "%B %d, %Y";
}
my $time_t = mktime(0, 0, 0, $day, $month, $year-1900);
my ($sec,$min,$hour,$mday,$mon,$yr,$wday,$yday,$isdst) = localtime($time_t);
my $time = strftime($format, $sec, $min, $hour,
$mday, $mon, $yr, $wday, $yday, $isdst);
my $current_encoding = getDefaultEncoding();
my $perltimestring = decode($current_encoding, $time);
if ($encoding eq "macintosh") {
return encode("mac_roman", $perltimestring);
} else {
return encode($encoding, $perltimestring);
}
return $time;
if ($format eq "") {
return "$month/$day/$year";
} else {
my $dateString = "";
my $firstsep = "";
if ($format =~ /^.(.)/o) {
$firstsep = $1;
}
my $secondsep = "";
if ($format =~ /^...(.)./o) {
$secondsep = $1;
}
SWITCH: {
($format =~ /^M/io) && do { $dateString .= "$month$firstsep" ; last SWITCH; };
($format =~ /^D/io) && do { $dateString .= "$day$firstsep" ; last SWITCH; };
($format =~ /^Y/io) && do { $dateString .= "$year$firstsep" ; last SWITCH; };
print STDERR "Unknown date format ($format) in config file[1]\n";
print STDERR "Assuming MDY\n";
return "$month/$day/$year";
}
SWITCH: {
($format =~ /^..M/io) && do { $dateString .= "$month$secondsep" ; last SWITCH; };
($format =~ /^..D/io) && do { $dateString .= "$day$secondsep" ; last SWITCH; };
($format =~ /^..Y/io) && do { $dateString .= "$year$secondsep" ; last SWITCH; };
($firstsep eq "") && do { last SWITCH; };
print STDERR "Unknown date format ($format) in config file[2]\n";
print STDERR "Assuming MDY\n";
return "$month/$day/$year";
}
SWITCH: {
($format =~ /^....M/io) && do { $dateString .= "$month" ; last SWITCH; };
($format =~ /^....D/io) && do { $dateString .= "$day" ; last SWITCH; };
($format =~ /^....Y/io) && do { $dateString .= "$year" ; last SWITCH; };
($secondsep eq "") && do { last SWITCH; };
print STDERR "Unknown date format ($format) in config file[3]\n";
print STDERR "Assuming MDY\n";
return "$month/$day/$year";
}
return $dateString;
}
}
sub setStyle
{
my $self = shift;
my $name = shift;
my $style = shift;
$style =~ s/^\s*//sgo;
$style =~ s/\s*$//sgo;
if (length($style)) {
$CSS_STYLES{$name} = $style;
$HeaderDoc::use_styles = 1;
}
}
sub fixup_inheritDoc
{
my $self = shift;
my $html = shift;
my $newhtml = "";
my @pieces = split(/</, $html);
foreach my $piece (@pieces) {
if ($piece =~ s/^hd_ihd\/>//so) {
if ($self->outputformat() eq "hdxml") {
$newhtml .= "<hd_ihd>";
}
$newhtml .= $self->inheritDoc();
if ($self->outputformat() eq "hdxml") {
$newhtml .= "</hd_ihd>";
}
$newhtml .= "$piece";
} else {
$newhtml .= "<$piece";
}
}
$newhtml =~ s/^<//so;
return $newhtml;
}
sub fixup_values
{
my $self = shift;
my $html = shift;
my $newhtml = "";
my @pieces = split(/</, $html);
foreach my $piece (@pieces) {
if ($piece =~ s/^hd_value\/>//so) {
if ($self->outputformat() eq "hdxml") {
$newhtml .= "<hd_value>";
}
$newhtml .= $self->value();
if ($self->outputformat() eq "hdxml") {
$newhtml .= "</hd_value>";
}
$newhtml .= "$piece";
} else {
$newhtml .= "<$piece";
}
}
$newhtml =~ s/^<//so;
return $newhtml;
}
sub getStyle
{
my $self = shift;
my $name = shift;
return $CSS_STYLES{$name};
}
sub styleSheet
{
my $self = shift;
my $TOC = shift;
my $css = "";
my $stdstyles = 1;
if ($TOC) {
if (defined($HeaderDoc::externalTOCStyleSheets)) {
$css .= $self->doExternalStyle($HeaderDoc::externalTOCStyleSheets);
$stdstyles = 0;
} elsif ($HeaderDoc::externalStyleSheets) {
$css .= $self->doExternalStyle($HeaderDoc::externalStyleSheets);
$stdstyles = 0;
}
} elsif ($HeaderDoc::externalStyleSheets) {
$css .= $self->doExternalStyle($HeaderDoc::externalStyleSheets);
$stdstyles = 0;
}
if ($HeaderDoc::suppressDefaultStyles) { $stdstyles = 0; }
$css .= "<style type=\"text/css\">";
$css .= "<!--";
if ($TOC) {
if (defined($HeaderDoc::tocStyleImports)) {
my $tempstyle = $HeaderDoc::tocStyleImports;
$tempstyle =~ s/{\@docroot}/\@\@docroot/sg;
$css .= html_fixup_links($self, "$tempstyle ");
$stdstyles = 0;
} elsif ($HeaderDoc::styleImports) {
my $tempstyle = $HeaderDoc::styleImports;
$tempstyle =~ s/{\@docroot}/\@\@docroot/sg;
$css .= html_fixup_links($self, "$tempstyle ");
$stdstyles = 0;
}
} else {
if ($HeaderDoc::styleImports) {
my $tempstyle = $HeaderDoc::styleImports;
$tempstyle =~ s/{\@docroot}/\@\@docroot/sg;
$css .= html_fixup_links($self, "$tempstyle ");
$stdstyles = 0;
}
}
foreach my $stylename (sort strcasecmp keys %CSS_STYLES) {
my $styletext = $CSS_STYLES{$stylename};
$css .= ".$stylename {$styletext}";
}
if ($stdstyles) {
$css .= "div {font-size: 10pt; text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #000000;}";
$css .= "td {font-size: 10pt; text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #000000;}";
if ($HeaderDoc::newTOC == 5) {
$css .= "span.hd_tocAccessSpace { display: block; font-size: 1px; height: 3px; min-height: 3px; }";
$css .= "span.hd_tocGroupSpace { display: block; font-size: 1px; height: 3px; min-height: 3px; }";
$css .= "span.hd_tocGroup { display: block; font-weight: bold; font-size: 10pt; text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #000000; margin-left: 0px; padding-left: 40px; }";
$css .= "span.hd_tocGroup + span.hd_tocAccess { padding-top: 5px; }";
$css .= "td.toc_contents_text {font-size: 11pt; text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #000000; }";
}
$css .= "li.tocSubEntry {font-size: 11pt; text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #000000;}";
$css .= "p {font-size: 10pt; text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #000000;}";
$css .= "a:link {text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #36c;}";
$css .= "a:visited {text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #36c;}";
$css .= "a:visited:hover {text-decoration: underline; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #36c;}";
$css .= "a:active {text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #36c;}";
$css .= "a:hover {text-decoration: underline; font-family: lucida grande, geneva, helvetica, arial, sans-serif; color: #36c;}";
$css .= "h2.h2tight { margin-top: 0px; padding-top: 0px; }"; if ($HeaderDoc::newTOC != 5) {
$css .= ".hd_toc_box h4 { margin-bottom: 2px; padding-bottom: 0px; }";
$css .= ".hd_toc_box h4 +h4 { margin-top: 2px; padding-top: 0px; }";
}
$css .= "h1 { margin-top: 13px; padding-top: 0px; }"; $css .= "h4 {text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; font-size: tiny; font-weight: bold;}"; $css .= "h5 {text-decoration: none; font-family: lucida grande, geneva, helvetica, arial, sans-serif; font-size: 10.1pt; font-weight: bold;}"; $css .= "pre {text-decoration: none; font-family: Courier, Consolas, monospace; color: #666; font-size: 10pt;}"; $css .= "pre a { font-family: Courier, Consolas, monospace; color: #666;font-size: 10pt;}"; $css .= "pre a:link { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "pre a:visited { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "pre a:visited:hover { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "pre a:active { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "pre a:hover { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "code {text-decoration: none; font-family: Courier, Consolas, monospace; color: #666;font-size: 10pt;}"; $css .= "code a { font-family: Courier, Consolas, monospace; color: #666;font-size: 10pt;}"; $css .= "code a:link { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "code a:visited { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "code a:visited:hover { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "code a:active { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "code a:hover { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "tt {text-decoration: none; font-family: Courier, Consolas, monospace; color: #666;font-size: 10pt;}"; $css .= "tt a { font-family: Courier, Consolas, monospace; color: #666;font-size: 10pt;}"; $css .= "tt a:link { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "tt a:visited { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "tt a:visited:hover { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "tt a:active { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "tt a:hover { font-family: Courier, Consolas, monospace; color: #36c;font-size: 10pt;}"; $css .= "body {text-decoration: none; font-family: Courier, Consolas, monospace; color: #666;font-size: 10pt; padding-left: 0px; padding-top: 0px; margin-left: 0px; margin-top: 0px; border: none; }"; $css .= "#hd_outermost_table { margin-left: 0px; border-spacing: 0px; margin-top: 0px; padding-left: 0px; padding-top: 0px; border: none; }";
$css .= "#hd_outermost_table > tr { border-spacing: 0px; margin-left: 0px; margin-top: 0px; padding-left: 0px; padding-top: 0px; border: none; }";
$css .= "#hd_outermost_table > tr > td { border-spacing: 0px; margin-left: 0px; margin-top: 0px; }";
$css .= "#hd_outermost_table > tbody > tr { border-spacing: 0px; margin-left: 0px; margin-top: 0px; padding-left: 0px; padding-top: 0px; border: none; }";
$css .= "#hd_outermost_table > tbody > tr > td { border-spacing: 0px; margin-left: 0px; margin-top: 0px; padding-top: 3px; }";
$css .= ".afterName { display: none; }";
$css .= ".list_indent { margin-left: 40px; }";
$css .= ".declaration_indent { margin-left: 40px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; min-height: 12px; vertical-align: middle; }";
$css .= ".declaration_indent pre { margin-top: 20px; padding-top: 0px; margin-bottom: 20px; padding-bottom: 0px; }";
$css .= ".gapBeforeFooter { display: none; }";
$css .= "hr { height: 0px; min-height: 0px; border-top: none; border-left: none; border-right: none; border-bottom: 1px solid #909090;}";
$css .= "hr.afterHeader { display: none }";
$css .= ".param_group_indent { margin-left: 25px; }";
$css .= ".param_indent { margin-left: 40px; margin-top: 0px; padding-top: 0px; }";
$css .= ".param_indent dl { margin-top: 4px; padding-top: 0px; }";
$css .= "dl dd > p:first-child { margin-top: 2px; padding-top: 0px; }";
$css .= ".param_indent dl dd > p:first-child { margin-top: 2px; padding-top: 0px; }";
$css .= ".group_indent { margin-left: 40px; }";
$css .= ".group_desc_indent { margin-left: 20px; }";
$css .= ".warning_indent { margin-left: 40px; }";
$css .= ".important_indent { margin-left: 40px; }";
$css .= ".note_indent { margin-left: 40px; }";
$css .= "h3 {";
$css .= " color: #3C4C6C;";
$css .= "}";
$css .= ".tight {";
$css .= " margin-top: 2px; margin-bottom: 0px;";
$css .= " padding-top: 0px; padding-bottom: 0px;";
$css .= "}";
$css .= "h3 a {";
$css .= " color: #3C4C6C;";
$css .= " font-size: 16px;";
$css .= " font-style: normal;";
$css .= " font-variant: normal;";
$css .= " font-weight: bold;";
$css .= " height: 0px;";
$css .= " line-height: normal;";
$css .= "}";
if ($HeaderDoc::newTOC == 5) {
$css .= ".hd_tocAccess { display: block; margin-left: 40px; font-style: italic; font-size: 10px; font-weight: normal; color: #303030; }"; } else {
$css .= ".hd_tocAccess { display: block; margin-left: 25px; font-style: italic; font-size: 10px; font-weight: normal; color: #303030; margin-top: 3px; margin-bottom: 3px;}";
}
$css .= ".tocSubheading { margin-bottom: 4px; }";
}
if ($HeaderDoc::styleSheetExtras) {
my $tempstyle = $HeaderDoc::styleSheetExtras;
$tempstyle =~ s/{\@docroot}/\@\@docroot/sg;
$css .= html_fixup_links($self, "$tempstyle ");
}
$css .= "-->";
$css .= "</style>";
return $css;
}
sub documentationBlock
{
my $self = shift;
my $composite = shift;
my $contentString;
my $name = $self->name();
my $desc = $self->discussion();
my $checkDisc = $self->halfbaked_discussion();
my $throws = "";
my $abstract = $self->abstract();
my $availability = $self->availability();
my $namespace = ""; if ($self->can("namespace")) { $namespace = $self->namespace(); }
my $updated = $self->updated();
my $declaration = "";
my $result = "";
my $localDebug = 0;
my $fullpath = $self->fullpath();
my $linenum = $self->linenum();
my $list_attributes = $self->getAttributeLists($composite);
my $short_attributes = $self->getAttributes(0);
my $long_attributes = $self->getAttributes(1);
my $class = ref($self) || $self;
my $apio = $self->apiOwner();
my $apioclass = ref($apio) || $apio;
my $apiref = "";
my $headlevel = "h3";
my $newTOCinAPIOwner = $HeaderDoc::newTOC;
my $showDiscussionHeading = 1;
my $isAPIO = $self->isAPIOwner();
if ($self->{HIDEDOC}) { return ""; }
if ($self->isInternal() && !$HeaderDoc::document_internal) { return ""; }
if ($isAPIO) {
$headlevel = "h1";
if ($newTOCinAPIOwner) {
$showDiscussionHeading = 0;
}
if (($checkDisc !~ /\S/) && ($abstract !~ /\S/)) {
my $linenum = $self->linenum();
warn "$fullpath:$linenum: No header or class discussion/abstract found. Creating dummy file for default content page.\n";
$abstract .= $HeaderDoc::defaultHeaderComment; }
} else {
$newTOCinAPIOwner = 0;
$declaration = $self->declarationInHTML();
}
if ($self->can("result")) { $result = $self->result(); }
if ($self->can("throws")) { $throws = $self->throws(); }
if ($self->noRegisterUID()) {
cluck("BT\n");
die("Unexpected unregistered object being inserted into content. Object is $self, name is ".$self->name().", header is ".$apio->name()."\n");
}
if ($isAPIO) {
if ($self->htmlHeader() =~ /\S/) {
$contentString .= "<hr class=\"afterHeader\">";
}
} else {
$contentString .= "<hr class=\"betweenAPIEntries\">";
}
my ($constantsref, $fieldsref, $paramsref, $fieldHeading, $func_or_method, $variablesref)=$self->apirefSetup();
my @local_variables = @{$variablesref};
my @constants = @{$constantsref};
my @fields = @{$fieldsref};
my @params = @{$paramsref};
$apiref = $self->apiref($composite);
my $divid = "docbox_".$self->apiuid();
if (!$isAPIO) {
$contentString .= $apiref;
}
if ($HeaderDoc::newTOC != 5) {
$contentString .= "<table border=\"0\" cellpadding=\"2\" cellspacing=\"2\" width=\"300\">";
$contentString .= "<tr>";
$contentString .= "<td valign=\"top\" height=\"12\" colspan=\"5\">";
}
my $urlname = sanitize($name, 1);
$contentString .= "<$headlevel><a name=\"$urlname\">$name</a></$headlevel>\n";
if ($HeaderDoc::newTOC != 5) {
$contentString .= "</td>";
$contentString .= "</tr></table>";
}
if (!$newTOCinAPIOwner) { $contentString .= "<hr class=\"afterName\">"; }
my $attstring = ""; my $c = 0;
if (length($short_attributes)) {
$attstring .= $short_attributes;
$c++;
}
if (length($list_attributes)) {
$attstring .= $list_attributes;
$c++;
}
if ($newTOCinAPIOwner) {
if ($c == 2) {
$attstring =~ s/<\/table><\/div>\s*<div.*?><table.*?>//s;
}
$attstring =~ s/<\/table><\/div>\s*$//s;
}
if (!$newTOCinAPIOwner) { $attstring .= "<dl>"; }
if (length($throws)) {
if ($newTOCinAPIOwner) {
if (!$c) {
$attstring .= "<div class=\"spec_sheet_info_box\"><table cellspacing=\"0\" class=\"specbox\">\n";
}
$attstring .= "<tr><td scope=\"row\"><b>Throws:</b></td><td><div style=\"margin-bottom:1px\"><div class=\"content_text\">$throws</div></div></td></tr>\n";
} else {
$attstring .= "<dt><b>Throws</b></dt>\n<dd>$throws</dd>\n";
}
$c++;
}
my $includeList = "";
if ($class eq "HeaderDoc::Header") {
my $includeref = $HeaderDoc::perHeaderIncludes{$fullpath};
if ($includeref) {
my @includes = @{$includeref};
my $first = 1;
foreach my $include (@includes) {
my $localDebug = 0;
print STDERR "Included file: $include\n" if ($localDebug);
if (!$first) {
if ($newTOCinAPIOwner) {$includeList .= "<br>\n"; }
else {$includeList .= ",\n"; }
}
my $xmlinc = $self->textToXML($include);
my $includeguts = $include;
$includeguts =~ s/[<\"](.*)[>\"]/$1/so;
my $includefile = basename($includeguts);
my $ref = $self->genRefSub("doc", "header", $includefile, "");
$includeList .= "<!-- a logicalPath=\"$ref\" machineGenerated=\"true\" -->$xmlinc<!-- /a -->";
$first = 0;
}
}
}
if (length($includeList)) {
if ($newTOCinAPIOwner) {
if (!$c) {
$attstring .= "<div class=\"spec_sheet_info_box\"><table cellspacing=\"0\" class=\"specbox\">\n";
}
$attstring .= "<tr><td scope=\"row\"><b>Includes:</b></td><td><div style=\"margin-bottom:1px\"><div class=\"content_text\">$includeList</div></div></td></tr>\n";
} else {
$attstring .= "<b>Includes</b> ";
$attstring .= $includeList;
$attstring .= "<br>\n";
}
$c++;
}
if ($newTOCinAPIOwner) {
if ($c) { $attstring .= "</table></div>\n"; }
$contentString .= $attstring;
} else {
if ($attstring =~ /<dl>\s*$/s) {
$attstring =~ s/<dl>\s*$//s;
} else {
$attstring .= "</dl>";
}
}
if ($newTOCinAPIOwner) {
$contentString .= "<h2>".$HeaderDoc::introductionName."</h2>\n";
}
my $uid = $self->apiuid();
if (length($abstract)) {
$showDiscussionHeading = 1;
my $absstart = $self->headerDocMark("abstract", "start");
my $absend = $self->headerDocMark("abstract", "end");
$contentString .= "<p>$absstart<!-- begin abstract -->";
if ($self->can("isFramework") && $self->isFramework()) {
$contentString .= "<!-- headerDoc=frameworkabstract;uid=".$uid.";name=start -->\n";
}
$contentString .= "$abstract";
if ($self->can("isFramework") && $self->isFramework()) {
$contentString .= "<!-- headerDoc=frameworkabstract;uid=".$uid.";name=end -->\n";
}
$contentString .= "<!-- end abstract -->$absend</p>\n";
}
my $accessControl = "";
if ($self->can("accessControl")) {
$accessControl = $self->accessControl();
}
my $optionalOrRequired = "";
if ($self->parserState && ($apioclass =~ /HeaderDoc::ObjCProtocol/)) {
$optionalOrRequired = $self->parserState->{optionalOrRequired};
}
my $includeAccess = 0;
if ($accessControl ne "") { $includeAccess = 1; }
if ($self->can("isProperty") && $self->isProperty()) { $includeAccess = 0; }
if ($self->class eq "HeaderDoc::Method") { $includeAccess = 0; }
if ($self->class eq "HeaderDoc::PDefine") { $includeAccess = 0; }
if ($self->lang eq "perl") { $includeAccess = 0; }
if (!$isAPIO) {
$contentString .= "<div class='declaration_indent'>\n";
my $declstart = $self->headerDocMark("declaration", "start");
my $declend = $self->headerDocMark("declaration", "end");
if ($includeAccess) {
$contentString .= "<pre><tt>$accessControl</tt>\n<br>$declaration</pre>\n";
} elsif (length $optionalOrRequired) {
$contentString .= "<pre><tt>$optionalOrRequired</tt>\n<br>$declaration</pre>\n";
} else {
$contentString .= "<pre>$declstart$declaration$declend</pre>\n";
}
$contentString .= "</div>\n";
}
my @parameters_or_fields = ();
my @callbacks = ();
foreach my $element (@params) {
if ($element->isCallback()) {
push(@callbacks, $element);
} elsif (!$element->{ISDEFINE}) {
push(@parameters_or_fields, $element);
}
}
foreach my $element (@fields) {
if ($element->isCallback()) {
push(@callbacks, $element);
} elsif (!$element->{ISDEFINE}) {
push(@parameters_or_fields, $element);
}
}
my @includedDefines = ();
if ($self->{INCLUDED_DEFINES}) {
@includedDefines = @{$self->{INCLUDED_DEFINES}};
}
my $arrayLength = @includedDefines;
if (($arrayLength > 0)) {
my $paramContentString;
$showDiscussionHeading = 1;
foreach my $element (@includedDefines) {
if ($self->{HIDESINGLETONS}) {
if ($element->{MAINOBJECT}) {
$element = ${$element->{MAINOBJECT}};
bless($element, "HeaderDoc::HeaderElement");
bless($element, $element->class());
}
}
my $fName = $element->name();
my $fDesc = $element->discussion();
my $fType = "";
my $apiref = "";
if ($self->can("type")) { $fType = $element->type(); }
$apiref = $element->apiref($composite);
if (length ($fName) &&
(($fType eq 'field') || ($fType eq 'constant') || ($fType eq 'funcPtr') ||
($fType eq ''))) {
$paramContentString .= "<dt>$apiref<code>$fName</code></dt><dd>$fDesc</dd>\n";
} elsif ($fType eq 'callback') {
my @userDictArray = $element->userDictArray(); my $paramString;
foreach my $hashRef (@userDictArray) {
while (my ($param, $disc) = each %{$hashRef}) {
$paramString .= "<dt><b><code>$param</code></b></dt>\n<dd>$disc</dd>\n";
}
if (length($paramString)) {
$paramString = "<dl>\n".$paramString."\n</dl>\n";
};
}
$contentString .= "<dt><code>$fName</code></dt><dd>$fDesc<br>$paramString</dd>\n";
} else {
my $classname = ref($self) || $self;
$classname =~ s/^HeaderDoc:://o;
if (!$HeaderDoc::ignore_apiuid_errors) {
print STDERR "$fullpath:$linenum: warning: $classname ($name) field with name $fName has unknown type: $fType\n";
}
}
}
if (length ($paramContentString)){
$contentString .= "<h5 class=\"tight\"><font face=\"Lucida Grande,Helvetica,Arial\">Included Defines</font></h5>\n";
$contentString .= "<div class='param_indent'>\n";
$contentString .= "<dl>\n";
$contentString .= $paramContentString;
$contentString .= "</dl>\n";
$contentString .= "</div>\n";
}
}
$arrayLength = @parameters_or_fields;
if (($arrayLength > 0) && (length($fieldHeading))) {
my $paramContentString;
$showDiscussionHeading = 1;
foreach my $element (@parameters_or_fields) {
my $fName = $element->name();
my $fDesc = $element->discussion();
my $fType = "";
my $apiref = "";
if ($self->can("type")) { $fType = $element->type(); }
$apiref = $element->apiref($composite);
if (length ($fName) &&
(($fType eq 'field') || ($fType eq 'constant') || ($fType eq 'funcPtr') ||
($fType eq ''))) {
$paramContentString .= "<dt>$apiref<code>$fName</code></dt><dd>$fDesc</dd>\n";
} elsif ($fType eq 'callback') {
my @userDictArray = $element->userDictArray(); my $paramString;
foreach my $hashRef (@userDictArray) {
while (my ($param, $disc) = each %{$hashRef}) {
$paramString .= "<dt><b><code>$param</code></b></dt>\n<dd>$disc</dd>\n";
}
if (length($paramString)) {
$paramString = "<dl>\n".$paramString."\n</dl>\n";
};
}
$contentString .= "<dt><code>$fName</code></dt><dd>$fDesc<br>$paramString</dd>\n";
} else {
my $classname = ref($self) || $self;
$classname =~ s/^HeaderDoc:://o;
if (!$HeaderDoc::ignore_apiuid_errors) {
print STDERR "$fullpath:$linenum: warning: $classname ($name) field with name $fName has unknown type: $fType\n";
}
}
}
if (length ($paramContentString)){
$contentString .= "<h5 class=\"tight\"><font face=\"Lucida Grande,Helvetica,Arial\">$fieldHeading</font></h5>\n";
$contentString .= "<div class='param_indent'>\n";
$contentString .= "<dl>\n";
$contentString .= $paramContentString;
$contentString .= "</dl>\n";
$contentString .= "</div>\n";
}
}
if (@constants) {
$showDiscussionHeading = 1;
$contentString .= "<h5 class=\"tight\"><font face=\"Lucida Grande,Helvetica,Arial\">Constants</font></h5>\n";
$contentString .= "<div class='param_indent'>\n";
$contentString .= "<dl>\n";
foreach my $element (@constants) {
my $cName = $element->name();
my $cDesc = $element->discussion();
my $uid = $element->apiuid();
if (!$apio->appleRefUsed($uid) && !$HeaderDoc::ignore_apiuid_errors) {
$apio->appleRefUsed($uid, 1);
$contentString .= "<dt><a name=\"$uid\"><code>$cName</code></a></dt><dd>$cDesc</dd>\n";
} else {
$contentString .= "<dt><code>$cName</code></dt><dd>$cDesc</dd>\n";
}
}
$contentString .= "</dl>\n</div>\n";
}
if (scalar(@callbacks)) {
$showDiscussionHeading = 1;
$contentString .= "<h5 class=\"tight\"><font face=\"Lucida Grande,Helvetica,Arial\">Callbacks</font></h5>\n";
$contentString .= "<div class='param_indent'>\n";
$contentString .= "<dl>";
foreach my $element (@callbacks) {
my $fName = $element->name();
my $fDesc = $element->discussion();
my $fType = $element->type();
if (($fType eq 'field') || ($fType eq 'constant') || ($fType eq 'funcPtr')){
$contentString .= "<dt><code>$fName</code></dt><dd>$fDesc</dd>\n";
} elsif ($fType eq 'callback') {
my @userDictArray = $element->userDictArray(); my $paramString;
foreach my $hashRef (@userDictArray) {
while (my ($param, $disc) = each %{$hashRef}) {
$paramString .= "<dt><b><code>$param</code></b></dt>\n<dd>$disc</dd>\n";
}
if (length($paramString)) {$paramString = "<dl>\n".$paramString."\n</dl>\n";};
}
$contentString .= "<dt><code>$fName</code></dt><dd>$fDesc<br>$paramString</dd>\n";
} else {
my $fullpath = $HeaderDoc::headerObject->name();
if (!$HeaderDoc::ignore_apiuid_errors) {
print STDERR "$fullpath:$linenum: warning: struct/typdef/union ($name) field with name $fName has unknown type: $fType\n";
}
}
}
$contentString .= "</dl>\n</div>\n";
}
if (length($result)) {
$showDiscussionHeading = 1;
$contentString .= "<h5 class=\"tight\"><font face=\"Lucida Grande,Helvetica,Arial\">Return Value</font></h5><p><!-- begin return value -->";
$contentString .= "$result\n";
$contentString .= "<!-- end return value --></p>";
}
my $stripdesc = $checkDisc;
$stripdesc =~ s/<br>/\n/sg;
my $BD = "";
if ($self->can("blockDiscussion")) {
$BD = $self->blockDiscussion();
$BD =~ s/<br>/\n/sg;
}
if ($stripdesc =~ /\S/ || $BD =~ /\S/) {
if ($showDiscussionHeading) {
$contentString .= "<h5 class=\"tight\"><font face=\"Lucida Grande,Helvetica,Arial\">Discussion</font></h5>\n";
}
my $discstart = $self->headerDocMark("discussion", "start");
my $discend = $self->headerDocMark("discussion", "end");
$contentString .= "<!-- begin discussion -->";
if ($self->can("isFramework") && $self->isFramework()) {
$contentString .= "<!-- headerDoc=frameworkdiscussion;uid=".$uid.";name=start -->\n";
} else {
$contentString .= $discstart;
}
$contentString .= $desc;
if ($self->can("isFramework") && $self->isFramework()) {
$contentString .= "<!-- headerDoc=frameworkdiscussion;uid=".$uid.";name=end -->\n";
} else {
$contentString .= $discend;
}
$contentString .= "<!-- end discussion -->\n";
}
if (!$HeaderDoc::suppress_local_variables) {
if (@local_variables) {
$showDiscussionHeading = 1;
$contentString .= "<h5 class=\"tight\"><font face=\"Lucida Grande,Helvetica,Arial\">Local Variables</font></h5>\n";
my @groups = ();
my %groupshash = ();
foreach my $element (@local_variables) {
my $group = $element->group();
$group =~ s/[\r\n]/ /sg;
$group =~ s/^\s*//s;
$group =~ s/\s*$//s;
if (!$group) { $group = " "; }
if (!$groupshash{$group}) {
push(@groups, $group);
my @arr = ();
$groupshash{$group} = \@arr;
}
my @arr = @{$groupshash{$group}};
push(@arr, \$element);
$groupshash{$group} = \@arr;
}
foreach my $group (@groups) {
if ($group =~ /\S/) {
$contentString .= "<div class='param_group_indent'>$group</div>\n";
}
$contentString .= "<div class='param_indent'>\n";
$contentString .= "<dl>\n";
my @arr = @{$groupshash{$group}};
foreach my $elementref (@arr) {
my $element = ${$elementref};
my $cName = $element->name();
my $cDesc = $element->discussion();
my $uid = $element->apiuid();
if (!$apio->appleRefUsed($uid) && !$HeaderDoc::ignore_apiuid_errors) {
$apio->appleRefUsed($uid, 1);
$contentString .= "<dt><a name=\"$uid\"><code>$cName</code></a></dt><dd>$cDesc</dd>\n";
} else {
$contentString .= "<dt><code>$cName</code></dt><dd>$cDesc</dd>\n";
}
}
$contentString .= "</dl>\n</div>\n";
}
}
}
if (!$newTOCinAPIOwner) {
$contentString .= $attstring;
}
if (length($long_attributes)) {
$contentString .= $long_attributes;
}
my $late_attributes = "";
if (length($namespace)) {
$late_attributes .= "<dt><b>Namespace</b></dt><dd>$namespace</dd>\n";
}
if (length($availability)) {
$late_attributes .= "<dt><b>Availability</b></dt><dd>$availability</dd>\n";
}
if (length($updated)) {
$late_attributes .= "<dt><b>Updated:</b></dt><dd>$updated</dd>\n";
}
if (length($late_attributes)) {
$contentString .= "<dl>".$late_attributes."</dl>\n";
}
my $value_fixed_contentString = $self->fixup_values($contentString);
return $value_fixed_contentString;
}
sub taggedParameters {
my $self = shift;
if (@_) {
@{ $self->{TAGGEDPARAMETERS} } = @_;
}
($self->{TAGGEDPARAMETERS}) ? return @{ $self->{TAGGEDPARAMETERS} } : return ();
}
sub compositePageUID {
my $self = shift;
my $uid = "";
if ($self->can("compositePageAPIUID")) {
$uid = $self->compositePageAPIUID();
} else {
my $apiUIDPrefix = HeaderDoc::APIOwner->apiUIDPrefix();
$uid = $self->apiuid();
$uid =~ s/\/\/\Q$apiUIDPrefix\E\//\/\/$apiUIDPrefix\/doc\/compositePage\//s;
}
return $uid;
}
sub addTaggedParameter {
my $self = shift;
if (@_) {
push (@{$self->{TAGGEDPARAMETERS}}, @_);
my @arr = @{$self->{TAGGEDPARAMETERS}};
return \$arr[scalar(@arr) - 1];
}
return undef; }
sub taggedParsedCompare {
my $self = shift;
my @tagged = $self->taggedParameters();
my @parsed = $self->parsedParameters();
my $funcname = $self->name();
my $fullpath = $self->fullpath();
my $linenum = $self->linenum();
my $tpcDebug = 0;
my $struct = 0;
my $strict = $HeaderDoc::force_parameter_tagging;
my %taggednames = ();
my %parsednames = ();
if ($self->{TPCDONE}) { return; }
if (!$HeaderDoc::ignore_apiuid_errors) {
$self->{TPCDONE} = 1;
}
my @fields = ();
if ($self->can("fields")) {
$struct = 1;
@fields = $self->fields();
}
my @constants = $self->constants();
my $apiOwner = $self->isAPIOwner();
if (!$self->suppressChildren()) {
foreach my $myfield (@fields) {
my $nscomp = $myfield->name();
$nscomp =~ s/\s*//sgo;
$nscomp =~ s/^\**//sso;
if (!length($nscomp)) {
$nscomp = $myfield->type();
$nscomp =~ s/\s*//sgo;
}
$taggednames{$nscomp}=$myfield;
print STDERR "Mapped Field $nscomp -> $myfield\n" if ($tpcDebug);
}
if (!$apiOwner) {
foreach my $myconstant (@constants) {
my $nscomp = $myconstant->name();
print STDERR "CONST: $nscomp\n" if ($tpcDebug);
$nscomp =~ s/\s*//sgo;
$nscomp =~ s/^\**//sso;
if (!length($nscomp)) {
$nscomp = $myconstant->type();
$nscomp =~ s/\s*//sgo;
}
$taggednames{$nscomp}=$myconstant;
print STDERR "COUNT: ".(keys %taggednames)."\n" if ($tpcDebug);
print STDERR "Mapped Constant $nscomp -> $myconstant\n" if ($tpcDebug);
}
}
}
foreach my $mytaggedparm (@tagged) {
my $nscomp = $mytaggedparm->name();
$nscomp =~ s/\s*//sgo;
$nscomp =~ s/^\**//sso;
if (!length($nscomp)) {
$nscomp = $mytaggedparm->type();
$nscomp =~ s/\s*//sgo;
}
$taggednames{$nscomp}=$mytaggedparm;
print STDERR "Mapped Tagged Parm $nscomp -> $mytaggedparm\n" if ($tpcDebug);
}
if ($HeaderDoc::ignore_apiuid_errors) {
if ($tpcDebug) { print STDERR "ignore_apiuid_errors set. Skipping tagged/parsed comparison.\n"; }
}
if ($self->lang() eq "perl" || $self->lang() eq "shell") {
if ($tpcDebug) { print STDERR "Can't parse Perl or shell script parameter names.\nSkipping tagged/parsed comparison.\n"; }
return;
}
if ($tpcDebug) {
print STDERR "Tagged Parms:\n" if ($tpcDebug);
foreach my $obj (@tagged) {
bless($obj, "HeaderDoc::HeaderElement");
bless($obj, $obj->class());
print STDERR "TYPE: \"" .$obj->type . "\"\nNAME: \"" . $obj->name() ."\"\n";
}
}
print STDERR "Parsed Parms:\n" if ($tpcDebug);
foreach my $obj (@parsed) {
bless($obj, "HeaderDoc::HeaderElement");
bless($obj, $obj->class());
my $type = "";
if ($obj->can("type")) { $type = $obj->type(); }
print STDERR "TYPE:" .$type . "\nNAME:\"" . $obj->name()."\"\n" if ($tpcDebug);
my $nscomp = $obj->name();
$nscomp =~ s/\s*//sgo;
$nscomp =~ s/^\**//sso;
if (!length($nscomp)) {
$nscomp = $type;
$nscomp =~ s/\s*//sgo;
}
$parsednames{$nscomp}=$obj;
}
print STDERR "Checking Parameters and Stuff.\n" if ($tpcDebug);
foreach my $taggedname (keys %taggednames) {
my $searchname = $taggedname;
my $tp = $taggednames{$taggedname};
if ($tp->type eq "funcPtr") {
$searchname = $tp->name();
$searchname =~ s/\s*//sgo;
}
my $searchnameb = $searchname;
$searchnameb =~ s/.*\.//s; # to allow tagging of subfields with the same name in a meaningful way.
print STDERR "TN: $taggedname\n" if ($tpcDebug);
print STDERR "SN: $searchname\n" if ($tpcDebug);
if (!$parsednames{$searchname} && !$parsednames{$searchnameb}) {
my $apio = $tp->apiOwner();
print STDERR "APIO: $apio SN: \"$searchname\"\n" if ($tpcDebug);
my $tpname = $tp->type . " " . $tp->name();
$tpname =~ s/^\s*//s;
my $oldfud = $self->{PPFIXUPDONE};
if (!$self->fixupParsedParameters($tp->name)) {
if (!$oldfud) {
my @newparsed = $self->parsedParameters();
%parsednames = ();
foreach my $obj (@newparsed) {
bless($obj, "HeaderDoc::HeaderElement");
bless($obj, $obj->class());
print STDERR "TYPE:" .$obj->type . "\nNAME:" . $obj->name()."\n" if ($tpcDebug);
my $nscomp = $obj->name();
$nscomp =~ s/\s*//sgo;
$nscomp =~ s/^\**//sso;
if (!length($nscomp)) {
$nscomp = $obj->type();
$nscomp =~ s/\s*//sgo;
}
$parsednames{$nscomp}=$obj;
}
}
if (!$HeaderDoc::ignore_apiuid_errors) {
warn("$fullpath:$linenum: warning: Parameter $tpname does not appear in $funcname declaration ($self).\n");
print STDERR "---------------\n";
print STDERR "Candidates are:\n";
foreach my $ppiter (@parsed) {
my $ppname = $ppiter->name();
if (!length($ppname)) {
$ppname = $ppiter->type();
}
print STDERR " \"".$ppname."\"\n";
}
print STDERR "---------------\n";
}
}
}
}
if ($strict) { print STDERR "STRICT CHECK\n" if ($tpcDebug);
foreach my $parsedname (keys %parsednames) {
print STDERR "PN: $parsedname\n" if ($tpcDebug);
if (!$taggednames{$parsedname}) {
my $pp = $parsednames{$parsedname};
my $ppname = $pp->type . " " . $pp->name();
if (!$HeaderDoc::ignore_apiuid_errors) {
warn("$fullpath:$linenum: warning: Parameter $ppname in $funcname declaration is not tagged.\n");
} elsif ($tpcDebug) {
warn("Warning skipped\n");
}
}
}
}
}
sub fixupParsedParameters
{
my $self = shift;
my $name = shift;
if ($self->{PPFIXUPDONE}) { return 0; }
$self->{PPFIXUPDONE} = 1;
my $retval = 0;
my $simpleTDcontents = $self->typedefContents();
if (length($simpleTDcontents)) {
my $addDebug = 0;
$simpleTDcontents =~ s/\s+/ /sgo;
$simpleTDcontents =~ s/^\s*//so;
$simpleTDcontents =~ s/\s*$//so;
my $origref = $HeaderDoc::namerefs{$simpleTDcontents};
if ($origref && ($origref != $self)) {
print STDERR "Associating additional fields.\n" if ($addDebug);
bless($origref, "HeaderDoc::HeaderElement");
bless($origref, $origref->class());
foreach my $origpp ($origref->parsedParameters()) {
print STDERR "adding \"".$origpp->type()."\" \"".$origpp->name()."\" to $name\n" if ($addDebug);
my $newpp = $origpp->clone();
$newpp->hidden(1);
$self->addParsedParameter($newpp);
if ($newpp->name() eq $name) {
$retval = 1;
}
}
}
}
return $retval;
}
sub parsedParameters {
my $self = shift;
if (@_) {
@{ $self->{PARSEDPARAMETERS} } = @_;
}
($self->{PARSEDPARAMETERS}) ? return @{ $self->{PARSEDPARAMETERS} } : return ();
}
sub addParsedParameter {
my $self = shift;
if (@_) {
push (@{$self->{PARSEDPARAMETERS}}, @_);
}
return @{ $self->{PARSEDPARAMETERS} };
}
sub dropParsedParameter {
my $self = shift;
my $last = pop(@{$self->{PARSEDPARAMETERS}});
return $last;
}
sub parsedParamCompare {
my $self = shift;
my $compareObj = shift;
my @comparelist = $compareObj->parsedParameters();
my $name = $self->name();
my $localDebug = 0;
my @params = $self->parsedParameters();
if (scalar(@params) != scalar(@comparelist)) {
print STDERR "parsedParamCompare: function $name arg count differs (".
scalar(@params)." != ". scalar(@comparelist) . ")\n" if ($localDebug);
return 0;
}
my $pos = 0;
my $nparams = scalar(@params);
while ($pos < $nparams) {
my $compareparam = $comparelist[$pos];
my $param = $params[$pos];
if ($compareparam->type() ne $param->type()) {
print STDERR "parsedParamCompare: function $name no match for argument " .
$param->name() . ".\n" if ($localDebug);
return 0;
}
$pos++;
}
print STDERR "parsedParamCompare: function $name matched.\n" if ($localDebug);
return 1;
}
sub returntype {
my $self = shift;
my $localDebug = 0;
if (@_) {
$self->{RETURNTYPE} = shift;
print STDERR "$self: SET RETURN TYPE TO ".$self->{RETURNTYPE}."\n" if ($localDebug);
}
print STDERR "$self: RETURNING RETURN TYPE ".$self->{RETURNTYPE}."\n" if ($localDebug);
return $self->{RETURNTYPE};
}
sub taggedParamMatching
{
my $self = shift;
my $name = shift;
my $localDebug = 0;
return $self->paramMatching($name, \@{$self->{TAGGEDPARAMETERS}});
}
sub parsedParamMatching
{
my $self = shift;
my $name = shift;
my $localDebug = 0;
return $self->paramMatching($name, \@{$self->{PARSEDPARAMETERS}});
}
sub paramMatching
{
my $self = shift;
my $name = shift;
my $arrayref = shift;
my @array = @{$arrayref};
my $localDebug = 0;
print STDERR "SA: ".scalar(@array)."\n" if ($localDebug);
foreach my $param (@array) {
my $reducedname = $name;
my $reducedpname = $param->name;
$reducedname =~ s/\W//sgo;
$reducedpname =~ s/\W//sgo;
print STDERR "comparing \"$reducedname\" to \"$reducedpname\"\n" if ($localDebug);
if ($reducedname eq $reducedpname) {
print STDERR "PARAM WAS $param\n" if ($localDebug);
return $param;
}
}
print STDERR "NO SUCH PARAM\n" if ($localDebug);
return 0;
}
sub XMLdocumentationBlock {
my $self = shift;
my $class = ref($self) || $self;
my $compositePageString = "";
my $fullpath = $self->fullpath();
my $linenum = $self->linenum();
my $name = $self->textToXML($self->name(), 1, "$fullpath:$linenum:Name");
my $availability = $self->htmlToXML($self->availability(), 1, "$fullpath:$linenum:Availability");
my $updated = $self->htmlToXML($self->updated(), 1, "$fullpath:$linenum:Updated");
my $abstract = $self->htmlToXML($self->abstract(), 1, "$fullpath:$linenum:Abstract");
my $discussion = $self->htmlToXML($self->discussion(), 0, "$fullpath:$linenum:Discussion");
my $group = $self->htmlToXML($self->group(), 0, "$fullpath:$linenum:Group");
my $apio = $self->apiOwner();
my $apioclass = ref($apio) || $apio;
my $contentString;
my $localDebug = 0;
my $type = "";
my $isAPIOwner = $self->isAPIOwner();
my $lang = $self->lang();
my $sublang = $self->sublang();
my $langstring = "";
my $fieldType = "";
my $fieldHeading = "";
my $uid = "";
my $fielduidtag = "";
my $extra = "";
my $accessControl = "";
if ($self->can("accessControl")) {
$accessControl = $self->accessControl();
}
if ($accessControl =~ /\S/) {
$accessControl = " accessControl=\"$accessControl\"";
} else {
$accessControl = "";
}
my $optionalOrRequired = "";
if ($self->parserState && ($apioclass =~ /HeaderDoc::ObjCProtocol/)) {
$optionalOrRequired = $self->parserState->{optionalOrRequired};
if (length $optionalOrRequired) {
$optionalOrRequired = " optionalOrRequired=\"$optionalOrRequired\"";
}
}
$langstring = $self->apiRefLanguage($sublang);
my $defineinfo = "";
my @includedDefines = ();
if ($self->{INCLUDED_DEFINES}) {
@includedDefines = @{$self->{INCLUDED_DEFINES}};
}
my @includedDefineUIDs = ();
SWITCH: {
($class eq "HeaderDoc::Constant") && do {
$fieldType = "field"; $fieldHeading = "fieldlist"; $type = "constant";
if ($apioclass eq "HeaderDoc::Header") {
$uid = $self->apiuid("data");
} else {
$uid = $self->apiuid("clconst");
}
$isAPIOwner = 0;
last SWITCH;
};
($class eq "HeaderDoc::CPPClass") && do {
$fieldType = "field";
$fieldHeading = "template_fields";
$type = "cl";
if ($self->fields()) {
$type = "tmplt";
}
$uid = $self->apiuid("$type");
$type = "class";
if ($self->isCOMInterface()) {
$type = "com_interface";
}
$isAPIOwner = 1;
last SWITCH;
};
($class eq "HeaderDoc::Header") && do {
$fieldType = "field";
$fieldHeading = "fields";
my $filename = $self->filename();
my $fullpath = $self->fullpath();
$type = "header";
$uid = $self->apiuid("$type");
$type = "header";
$extra = " filename=\"$filename\" headerpath=\"$fullpath\"";
if ($self->isFramework()) { $type = "framework"; }
$isAPIOwner = 1;
last SWITCH;
};
($class eq "HeaderDoc::Enum") && do {
$fieldType = "constant";
$fieldHeading = "constantlist";
$type = "enum";
$uid = $self->apiuid("tag");
$fielduidtag = "econst";
$isAPIOwner = 0;
last SWITCH;
};
($class eq "HeaderDoc::Function") && do {
$fieldType = "parameter";
$fieldHeading = "parameterlist";
if ($apioclass eq "HeaderDoc::Header") {
$type = "func";
} else {
$type = $self->getMethodType();
}
if ($apioclass eq "HeaderDoc::CPPClass") {
my $paramSignature = $self->getParamSignature();
if (length($paramSignature)) {
$paramSignature = "/$paramSignature"; }
if ($self->sublang() eq "C") { $paramSignature = ""; }
if ($self->isTemplate()) {
my $apiref = $self->apiref(0, "ftmplt", "$paramSignature");
} else {
my $declarationRaw = $self->declaration();
my $methodType = $self->getMethodType();
my $apiref = $self->apiref(0, $methodType, "$paramSignature");
}
$uid = $self->apiuid();
} else {
$uid = $self->apiuid($type);
}
$type = "function";
$isAPIOwner = 0;
last SWITCH;
};
($class eq "HeaderDoc::Method") && do {
$fieldType = "parameter";
$fieldHeading = "parameterlist";
$type = "method";
my $declarationRaw = $self->declaration();
my $methodType = $self->getMethodType();
$uid = $self->apiuid($methodType);
$extra = " type=\"$methodType\"";
$isAPIOwner = 0;
last SWITCH;
};
($class eq "HeaderDoc::ObjCCategory") && do {
$fieldType = "field";
$fieldHeading = "template_fields";
$type = "category";
$uid = $self->apiuid("cat");
$isAPIOwner = 1;
last SWITCH;
};
($class eq "HeaderDoc::ObjCClass") && do {
$fieldType = "field";
$fieldHeading = "template_fields";
$type = "class";
$uid = $self->apiuid("cl");
$isAPIOwner = 1;
last SWITCH;
};
($class eq "HeaderDoc::ObjCContainer") && do {
$fieldType = "field";
$fieldHeading = "template_fields";
$type = "class";
$uid = $self->apiuid("cl");
$isAPIOwner = 1;
last SWITCH;
};
($class eq "HeaderDoc::ObjCProtocol") && do {
$fieldType = "field";
$fieldHeading = "template_fields";
$type = "protocol";
$uid = $self->apiuid("intf");
$isAPIOwner = 1;
last SWITCH;
};
($class eq "HeaderDoc::PDefine") && do {
$fieldType = "parameter";
$fieldHeading = "parameterlist";
$type = "pdefine";
$uid = $self->apiuid("macro");
my $definetype = "";
if ($self->isBlock()) {
$definetype = "block";
if (scalar(@includedDefines)) {
foreach my $refobj (@includedDefines) {
my $defineref = $refobj->{MAINOBJECT};
if (!$defineref) {
@includedDefines = ();
@includedDefineUIDs = @{$self->autoRelate()};
}
}
} else {
@includedDefines = ();
@includedDefineUIDs = @{$self->autoRelate()};
}
} elsif ($self->isFunctionLikeMacro()) {
$definetype = "function";
} else {
$definetype = "value";
}
$defineinfo = "definetype=\"$definetype\" ";
if ($self->parseOnly()) {
$defineinfo .= "parseOnly=\"true\" ";
}
$isAPIOwner = 0;
last SWITCH;
};
($class eq "HeaderDoc::Struct") && do {
$fieldType = "field";
$fieldHeading = "fieldlist";
if ($self->isUnion()) {
$type = "union";
} else {
$type = "struct";
}
$uid = $self->apiuid("tag");
$isAPIOwner = 0;
last SWITCH;
};
($class eq "HeaderDoc::Typedef") && do {
if ($self->isEnumList()) {
$fieldType = "constant";
$fieldHeading = "constantlist";
} elsif ($self->isFunctionPointer()) {
$fieldType = "parameter";
$fieldHeading = "parameterlist";
} else {
$fieldType = "field";
$fieldHeading = "fieldlist";
}
$type = "typedef";
$uid = $self->apiuid("tdef");
if ($self->isFunctionPointer()) {
$extra = " type=\"funcPtr\"";
} else {
$extra = " type=\"simple\"";
}
$isAPIOwner = 0;
last SWITCH;
};
($class eq "HeaderDoc::Var" || $class eq "HeaderDoc::MinorAPIElement") && do {
$fieldType = "field";
$fieldHeading = "fieldlist";
if ($self->can('isFunctionPointer')) {
if ($self->isFunctionPointer()) {
$fieldType = "parameter";
$fieldHeading = "parameterlist";
}
}
$type = "variable";
my $isProperty = $self->can('isProperty') ? $self->isProperty() : 0;
my $typename = "data";
if ($isProperty) {
$type = "property";
$typename = "instp";
}
$uid = $self->apiuid($typename);
$isAPIOwner = 0;
last SWITCH;
};
{
warn "UNKNOWN CLASS $self in XMLdocumentationBlock\n";
warn "OBJECT: TYPE: $self NAME: ".$self->name()."\n";
warn "APIO: TYPE: $apio NAME: ".$apio->name()."\n";
};
}
my $indexgroup = $self->indexgroup();
my $throws = $self->XMLthrows();
$compositePageString .= "<$type id=\"$uid\" $defineinfo"."lang=\"$langstring\"$extra$accessControl$optionalOrRequired>";
if (length($name)) {
$compositePageString .= "<name>$name</name>\n";
}
if ($indexgroup =~ /\S/) { $compositePageString .= "<indexgroup>".textToXML($indexgroup)."</indexgroup>"; }
if (length($abstract)) {
$compositePageString .= "<abstract>$abstract</abstract>\n";
}
if (length($availability)) {
$compositePageString .= "<availability>$availability</availability>\n";
}
if (length($updated)) {
$compositePageString .= "<updated>$updated</updated>\n";
}
if (length($group)) {
$compositePageString .= "<group>$group</group>\n";
}
my $value = "";
if ($self->can('value')) {
$value = $self->value();
if (length($value) && ($value ne "UNKNOWN")) {
$value = $self->textToXML($value);
$compositePageString .= "<value>$value</value>\n";
}
}
if (length($throws)) {
$compositePageString .= "$throws\n";
}
my @params = ();
my @origfields = ();
if ($self->can("fields")) { @origfields = $self->fields(); }
if ($self->can("taggedParameters")){
print STDERR "setting params\n" if ($localDebug);
@params = $self->taggedParameters();
if ($self->can("parsedParameters")) {
$self->taggedParsedCompare();
}
} elsif ($self->can("fields")) {
if ($self->can("parsedParameters")) {
$self->taggedParsedCompare();
}
} else {
print STDERR "type $class has no taggedParameters function\n" if ($localDebug);
}
my @parsedparams = ();
if ($self->can("parsedParameters")) {
@parsedparams = $self->parsedParameters();
}
my @parameters_or_fields = ();
my @callbacks = ();
foreach my $element (@params) {
if ($element->isCallback()) {
push(@callbacks, $element);
} elsif (!$element->{ISDEFINE}) {
push(@parameters_or_fields, $element);
}
}
foreach my $element (@origfields) {
bless($element, "HeaderDoc::HeaderElement");
bless($element, $element->class()); if ($element->can("hidden")) {
if (!$element->hidden()) {
if ($element->isCallback()) {
push(@callbacks, $element);
} elsif (!$element->{ISDEFINE}) {
push(@parameters_or_fields, $element);
}
}
}
}
my @orig_local_variables = $self->variables();
my @origconstants = $self->constants();
my @local_variables = ();
my @constants = ();
foreach my $copylocal (@orig_local_variables) {
bless($copylocal, "HeaderDoc::HeaderElement");
bless($copylocal, $copylocal->class()); if ($copylocal->can("hidden")) {
if (!$copylocal->hidden()) {
push(@local_variables, $copylocal);
}
}
}
foreach my $copyconstant (@origconstants) {
bless($copyconstant, "HeaderDoc::HeaderElement");
bless($copyconstant, $copyconstant->class()); if ($copyconstant->can("hidden")) {
if (!$copyconstant->hidden()) {
push(@constants, $copyconstant);
}
}
}
my $parseTree_ref = $self->parseTree();
my $parseTree = undef;
if ($class ne "HeaderDoc::MinorAPIElement") {
if (!$parseTree_ref) {
if (!$parseTree_ref && !$self->isAPIOwner()) {
warn "Missing parse tree for ".$self->name()."\n";
}
} else {
$parseTree = ${$parseTree_ref};
}
}
my $declaration = "";
if ($parseTree) {
$declaration = $self->declarationInHTML();
}
if (@constants) {
$compositePageString .= "<constantlist>\n";
foreach my $field (@constants) {
my $name = $self->textToXML($field->name());
my $desc = $self->htmlToXML($field->discussion());
my $fType = "";
if ($field->can("type")) { $fType = $field->type(); }
my $fielduidstring = "";
if (length($fielduidtag)) {
my $fielduid = $field->apiuid($fielduidtag);
$fielduidstring = " id=\"$fielduid\"";
if (!$apio->appleRefUsed($uid) && !$HeaderDoc::ignore_apiuid_errors) {
$apio->appleRefUsed($uid, 1);
} else {
$fielduidstring = "";
}
}
if ($fType eq "callback") {
my @userDictArray = $field->userDictArray(); my $paramString;
foreach my $hashRef (@userDictArray) {
while (my ($param, $disc) = each %{$hashRef}) {
$param = $self->textToXML($param);
$disc = $self->htmlToXML($disc);
$paramString .= "<parameter><name>$param</name><desc>$disc</desc></parameter>\n";
}
$compositePageString .= "<constant$fielduidstring><name>$name</name><desc>$desc</desc><callback_parameters>$paramString</callback_parameters></constant>\n";
}
} else {
$compositePageString .= "<constant$fielduidstring><name>$name</name><desc>$desc</desc></constant>\n";
}
}
$compositePageString .= "</constantlist>\n";
}
if (@local_variables) {
$compositePageString .= "<localvariablelist>\n";
foreach my $field (@local_variables) {
my $name = $self->textToXML($field->name());
my $desc = $self->htmlToXML($field->discussion());
my $fType = "";
if ($field->can("type")) { $fType = $field->type(); }
my $groupstring = "";
my $groupraw = $field->group();
if (length($groupraw)) {
$groupraw =~ s/"/\"/sg;
$groupstring = "<group>".textToXML($groupraw)."</group>";
}
my $fielduidstring = "";
if (length($fielduidtag)) {
my $fielduid = $field->apiuid($fielduidtag);
$fielduidstring = " id=\"$fielduid\"";
if (!$apio->appleRefUsed($uid) && !$HeaderDoc::ignore_apiuid_errors) {
# print STDERR "MARKING APIREF $uid used\n";
$apio->appleRefUsed($uid, 1);
} else {
# already used or a "junk" run to obtain
# uids for another purpose. Drop the
# uid in case it is already used
$fielduidstring = "";
}
}
if ($fType eq "callback") {
my @userDictArray = $field->userDictArray(); # contains elements that are hashes of param name to param doc
my $paramString;
foreach my $hashRef (@userDictArray) {
while (my ($param, $disc) = each %{$hashRef}) {
$param = $self->textToXML($param);
$disc = $self->htmlToXML($disc);
$paramString .= "<parameter><name>$param</name><desc>$disc</desc></parameter>\n";
}
$compositePageString .= "<localvariable$fielduidstring><name>$name</name><desc>$desc</desc><callback_parameters>$paramString</callback_parameters>$groupstring</localvariable>\n";
}
} else {
$compositePageString .= "<localvariable$fielduidstring><name>$name</name><desc>$desc</desc></localvariable>\n";
}
}
$compositePageString .= "</localvariablelist>\n";
}
if (@parameters_or_fields) {
$compositePageString .= "<$fieldHeading>\n";
foreach my $field (@parameters_or_fields) {
my $name = $self->textToXML($field->name());
my $desc = $self->htmlToXML($field->discussion());
my $fType = "";
if ($field->can("type")) { $fType = $field->type(); }
if ($fType eq "callback") {
my @userDictArray = $field->userDictArray(); # contains elements that are hashes of param name to param doc
my $paramString;
foreach my $hashRef (@userDictArray) {
while (my ($param, $disc) = each %{$hashRef}) {
$param = $self->textToXML($param);
$disc = $self->htmlToXML($disc);
$paramString .= "<parameter><name>$param</name><desc>$disc</desc></parameter>\n";
}
$compositePageString .= "<$fieldType><name>$name</name><desc>$desc</desc><callback_parameters>$paramString</callback_parameters></$fieldType>\n";
}
} else {
$compositePageString .= "<$fieldType><name>$name</name><desc>$desc</desc></$fieldType>\n";
}
}
$compositePageString .= "</$fieldHeading>\n";
}
if (@callbacks) {
$compositePageString .= "<callbacks>\n";
foreach my $field (@callbacks) {
my $name = $self->textToXML($field->name());
my $desc = $self->htmlToXML($field->discussion());
my $fType = "";
if ($field->can("type")) { $fType = $field->type(); }
if ($fType eq "callback") {
my @userDictArray = $field->userDictArray(); # contains elements that are hashes of param name to param doc
my $paramString;
foreach my $hashRef (@userDictArray) {
while (my ($param, $disc) = each %{$hashRef}) {
$param = $self->textToXML($param);
$disc = $self->htmlToXML($disc);
$paramString .= "<parameter><name>$param</name><desc>$disc</desc></parameter>\n";
}
$compositePageString .= "<$fieldType><name>$name</name><desc>$desc</desc><callback_parameters>$paramString</callback_parameters></$fieldType>\n";
}
} else {
$compositePageString .= "<$fieldType><name>$name</name><desc>$desc</desc></$fieldType>\n";
}
}
$compositePageString .= "</callbacks>\n";
}
if (scalar(@parsedparams) && (!$self->isBlock())) {
# PDefine blocks use parsed parameters to store all of the defines
# in a define block, so this would be bad.
my $paramContentString;
foreach my $element (@parsedparams) {
my $pName = $self->textToXML($element->name());
# if (!$element->can("type")) {
# cluck("ELEMENT TRACE: ".$element." (".$element->name().") in $self (".$self->name().") in ".$self->apiOwner()." (".$self->apiOwner()->name().")\n");
# my $headerObj = $HeaderDoc::headerObject;
# $headerObj->headerDump();
# next;
# }
my $pType = $self->textToXML($element->type());
$pType =~ s/\s*$//so;
if ($pName =~ s/^\s*(\*+)\s*//so) {
$pType .= " $1";
}
$pType = $self->textToXML($pType);
$pName = $self->textToXML($pName);
if (length ($pName) || length($pType)) {
$paramContentString .= "<parsedparameter><type>$pType</type><name>$pName</name></parsedparameter>\n";
}
}
if (length ($paramContentString)){
$compositePageString .= "<parsedparameterlist>\n";
$compositePageString .= $paramContentString;
$compositePageString .= "</parsedparameterlist>\n";
}
}
my $returntype = $self->textToXML($self->returntype());
my $result = "";
if ($self->can('result')) { $result = html2xhtml($self->result(), $self->encoding()); }
my $attlists = "";
if ($self->can('getAttributeLists')) { $attlists = $self->getAttributeLists(0); }
my $atts = "";
if ($self->can('getAttributes')) { $atts = $self->getAttributes(); }
if (length($atts)) {
$compositePageString .= "<attributes>$atts</attributes>\n";
}
if (length($attlists)) {
$compositePageString .= "<attributelists>$attlists</attributelists>\n";
}
my $idstring = "";
if (scalar(@includedDefines)) {
foreach my $refobj (@includedDefines) {
# $refobj->dbprint();
my $defineref = $refobj->{MAINOBJECT};
if (!$defineref) { next; }
my $define = ${$defineref};
$idstring .= "<includeddefine>".$define->apiuid()."</includeddefine>\n";
# $refobj->dbprint();
# $define->dbprint();
# die("Define: $define\n");
}
}
if (scalar(@includedDefineUIDs)) {
foreach my $idUID (@includedDefineUIDs) {
$idstring .= "<includeddefine>".$idUID."</includeddefine>\n";
}
}
if (length($idstring)) {
$compositePageString .= "<includeddefines>\n$idstring\n</includeddefines>\n";
}
if ($class eq "HeaderDoc::Header") {
my $includeref = $HeaderDoc::perHeaderIncludes{$fullpath};
if ($includeref) {
my @includes = @{$includeref};
$compositePageString .= "<includes>\n";
foreach my $include (@includes) {
print STDERR "Included file: $include\n" if ($localDebug);
my $xmlinc = $self->textToXML($include);
# $compositePageString .= "<include>$xmlinc</include>\n";
my $includeguts = $include;
$includeguts =~ s/[<\"](.*)[>\"]/$1/so;
my $includefile = basename($includeguts);
my $ref = $self->genRefSub("doc", "header", $includefile, "");
$compositePageString .= "<include><hd_link logicalPath=\"$ref\">$xmlinc</hd_link></include>\n";
}
$compositePageString .= "</includes>\n";
}
}
if (length($returntype)) {
$compositePageString .= "<returntype>$returntype</returntype>\n";
}
if (length($result)) {
$compositePageString .= "<result>$result</result>\n";
}
if (length($declaration)) {
$compositePageString .= "<declaration>$declaration</declaration>\n";
}
if (length($discussion)) {
$compositePageString .= "<desc>$discussion</desc>\n";
}
my @autoRelated = @{$self->autoRelate()};
if (scalar(@autoRelated)) {
$compositePageString .= "<autorelated>\n";
foreach my $autoRelatedItem (@autoRelated) {
$compositePageString .= "<relateduid>$autoRelatedItem</relateduid>\n";
}
$compositePageString .= "</autorelated>\n";
}
# Quick debugging of discussion and abstract
# print STDERR "OBJ $self\n";
# print STDERR " NAME: ".$self->name()."\n";
# print STDERR " DESC: ".$discussion."\n";
# print STDERR " ABS: ".$abstract."\n";
if ($isAPIOwner) {
$compositePageString .= $self->groupDoc();
$contentString = $self->_getFunctionXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$compositePageString .= "<functions>$contentString</functions>\n";
}
$contentString= $self->_getMethodXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$compositePageString .= "<methods>$contentString</methods>\n";
}
$contentString= $self->_getPropXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$compositePageString .= "<properties>$contentString</properties>\n";
}
$contentString= $self->_getVarXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$compositePageString .= "<globals>$contentString</globals>\n";
}
$contentString= $self->_getConstantXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$compositePageString .= "<constants>$contentString</constants>\n";
}
$contentString= $self->_getTypedefXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$compositePageString .= "<typedefs>$contentString</typedefs>";
}
$contentString= $self->_getStructXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$compositePageString .= "<structs_and_unions>$contentString</structs_and_unions>";
}
$contentString= $self->_getEnumXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$compositePageString .= "<enums>$contentString</enums>";
}
$contentString= $self->_getPDefineXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$compositePageString .= "<defines>$contentString</defines>";
}
# @@@ Class generation code. Important debug checkpoint.
my $classContent = "";
$contentString= $self->_getClassXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$classContent .= $contentString;
}
$contentString= $self->_getCategoryXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$classContent .= $contentString;
}
$contentString= $self->_getProtocolXMLDetailString();
if (length($contentString)) {
$contentString = $self->stripAppleRefs($contentString);
$classContent .= $contentString;
}
if (length($classContent)) {
$compositePageString .= "<classes>$classContent</classes>\n";
}
}
if ($isAPIOwner) {
my $copyrightOwner = $self->copyrightOwner;
if ($class eq "HeaderDoc::Header") {
my $headercopyright = $self->htmlToXML($self->headerCopyrightOwner());
if ($headercopyright ne "") {
$copyrightOwner = $headercopyright;
}
}
$compositePageString .= "<copyrightinfo>&
my $dateStamp = HeaderDoc::APIOwner::fix_date($self->encoding());
$compositePageString .= "<timestamp>$dateStamp</timestamp>\n" if (length($dateStamp));
}
$compositePageString .= "</$type>"; return $compositePageString;
}
sub isFunctionPointer {
my $self = shift;
if (@_) {
$self->{ISFUNCPTR} = shift;
}
return $self->{ISFUNCPTR};
}
sub addToIncludedDefines {
my $self = shift;
my $obj = shift;
if (!$self->{INCLUDED_DEFINES}) {
my @x = ();
$self->{INCLUDED_DEFINES} = \@x;
}
push(@{$self->{INCLUDED_DEFINES}}, $obj);
my @arr = @{$self->{INCLUDED_DEFINES}};
return \$arr[scalar(@arr) - 1];
}
sub apirefSetup
{
my $self = shift;
my $force = 0;
my $localDebug = 0;
if (@_) {
$force = shift;
}
if ($self->noRegisterUID()) {
print STDERR "SHORTCUT NOREGISTERUID: $self\n" if ($localDebug);
return ($self->{KEEPCONSTANTS},
$self->{KEEPFIELDS}, $self->{KEEPPARAMS},
$self->{FIELDHEADING}, $self->{FUNCORMETHOD}, $self->{KEEPVARIABLES});
}
my $subreftitle = 0;
if ($self->appleRefIsDoc() == 1) {
$subreftitle = 1;
}
my $class = ref($self) || $self;
my $apio = $self->apiOwner();
my $apioclass = ref($apio) || $apio;
my $declarationRaw = $self->declaration();
my @orig_local_variables = $self->variables();
my @origconstants = $self->constants();
my @origfields = ();
my @params = ();
my $apiref = "";
my $typename = "";
my $fieldHeading = "";
my $className = "";
my $apiRefType = "";
my $func_or_method = "";
print "APIREFSETUP: IN $self LOCAL VARS: ".$#orig_local_variables."\n" if($localDebug);
if ($self->can("taggedParameters")){
print STDERR "setting params\n" if ($localDebug);
@params = $self->taggedParameters();
if ($self->can("parsedParameters")) {
$self->taggedParsedCompare();
}
} elsif ($self->can("fields")) {
if ($self->can("parsedParameters")) {
$self->taggedParsedCompare();
}
} else {
print STDERR "type $class has no taggedParameters function\n" if ($localDebug);
}
if (!$force && $self->{APIREFSETUPDONE}) {
print STDERR "SHORTCUT: $self\n" if ($localDebug);
return ($self->{KEEPCONSTANTS}, $self->{KEEPFIELDS}, $self->{KEEPPARAMS},
$self->{FIELDHEADING}, $self->{FUNCORMETHOD}, $self->{KEEPVARIABLES});
}
if ($self->{APIREFSETUPDONE}) {
if (dereferenceUIDObject($self->{APIUID}, $self)) {
unregister_force_uid_clear($self->{APIUID});
}
}
if ($self->can("fields")) { @origfields = $self->fields(); }
my @constants = ();
my @local_variables = ();
my @fields = ();
if (!$self->suppressChildren()) {
foreach my $copyfield (@origfields) {
bless($copyfield, "HeaderDoc::HeaderElement");
bless($copyfield, $copyfield->class()); print STDERR "FIELD: ".$copyfield->name."\n" if ($localDebug);
if ($copyfield->can("hidden")) {
if (!$copyfield->hidden()) {
push(@fields, $copyfield);
} else {
print STDERR "HIDDEN\n" if ($localDebug);
}
}
}
foreach my $copyconstant (@origconstants) {
bless($copyconstant, "HeaderDoc::HeaderElement");
bless($copyconstant, $copyconstant->class()); if ($copyconstant->can("hidden")) {
if (!$copyconstant->hidden()) {
push(@constants, $copyconstant);
}
}
}
} else {
print STDERR "CHILDREN SUPPRESSED\n" if ($localDebug);
}
$typename = "internal_temporary_object";
SWITCH: {
($class eq "HeaderDoc::Function") && do {
print STDERR "FUNCTION\n" if ($localDebug);
$typename = $self->getMethodType();
print STDERR "Function type: $typename\n" if ($localDebug);
if ($apioclass eq "HeaderDoc::CPPClass") {
my $paramSignature = $self->getParamSignature();
print STDERR "paramSignature: $paramSignature\n" if ($localDebug);
if (length($paramSignature)) {
$paramSignature = "/$paramSignature"; }
if ($self->sublang() eq "C") { $paramSignature = ""; }
if ($self->isTemplate()) {
$apiref = $self->apiref(0, "ftmplt", "$paramSignature");
} else {
my $declarationRaw = $self->declaration();
my $methodType = $self->getMethodType();
$apiref = $self->apiref(0, $methodType, "$paramSignature");
}
}
$fieldHeading = "Parameters";
$apiRefType = "";
$func_or_method = "function";
last SWITCH;
};
($class eq "HeaderDoc::Constant") && do {
print STDERR "CONSTANT\n" if ($localDebug);
if ($apioclass eq "HeaderDoc::Header") {
$typename = "data";
} else {
$typename = "clconst";
}
$fieldHeading = "Fields";
$apiRefType = "";
last SWITCH;
};
($class eq "HeaderDoc::Enum") && do {
print STDERR "ENUM\n" if ($localDebug);
$typename = "tag";
$fieldHeading = "Constants";
$apiRefType = "econst";
last SWITCH;
};
($class eq "HeaderDoc::PDefine") && do {
print STDERR "PDEFINE\n" if ($localDebug);
$typename = "macro";
$fieldHeading = "Parameters";
$apiRefType = "";
last SWITCH;
};
($class eq "HeaderDoc::Method") && do {
print STDERR "METHOD\n" if ($localDebug);
$typename = $self->getMethodType();
$fieldHeading = "Parameters";
$apiRefType = "";
if ($apio->can("className")) { $className = $apio->className();
} else {
$className = $apio->name();
}
$func_or_method = "method";
last SWITCH;
};
($class eq "HeaderDoc::Struct") && do {
print STDERR "TAG\n" if ($localDebug);
$typename = "tag";
$fieldHeading = "Fields";
$apiRefType = "";
last SWITCH;
};
($class eq "HeaderDoc::Typedef") && do {
print STDERR "TDEF\n" if ($localDebug);
$typename = "tdef";
if ($self->isFunctionPointer()) {
$fieldHeading = "Parameters";
last SWITCH;
}
if ($self->isEnumList()) {
$fieldHeading = "Constants";
last SWITCH;
}
$fieldHeading = "Fields";
$apiRefType = "";
$func_or_method = "function";
last SWITCH;
};
($class eq "HeaderDoc::Var" || ($class eq "HeaderDoc::MinorAPIElement" && $self->autodeclaration())) && do {
print STDERR "VAR\n" if ($localDebug);
my $isProperty = $self->can('isProperty') ? $self->isProperty() : 0;
if ($isProperty) {
$typename = "instp";
} else {
$typename = "data";
}
$fieldHeading = "Fields";
if ($self->can('isFunctionPointer')) {
if ($self->isFunctionPointer()) {
$fieldHeading = "Parameters";
}
}
$apiRefType = "";
last SWITCH;
};
}
if (!length($apiref)) {
$apiref = $self->apiref(0, $typename);
}
if (@constants) {
foreach my $element (@constants) {
$element->appleRefIsDoc($subreftitle);
my $uid = $element->apiuid("econst");
}
}
if (@params) {
foreach my $element (@params) {
if (length($apiRefType)) {
$element->appleRefIsDoc($subreftitle);
$apiref = $element->apiref(0, $apiRefType);
}
}
}
foreach my $copylocal (@orig_local_variables) {
bless($copylocal, "HeaderDoc::HeaderElement");
bless($copylocal, $copylocal->class()); print STDERR "LOCAL VARIABLE: ".$copylocal->name."\n" if ($localDebug);
if (length($apiRefType)) {
$copylocal->appleRefIsDoc($subreftitle);
$apiref = $copylocal->apiref(0, $apiRefType);
}
if ($copylocal->can("hidden")) {
if (!$copylocal->hidden()) {
push(@local_variables, $copylocal);
}
}
}
$self->{KEEPVARIABLES} = \@local_variables;
$self->{KEEPCONSTANTS} = \@constants;
$self->{KEEPFIELDS} = \@fields;
$self->{KEEPPARAMS} = \@params;
$self->{FIELDHEADING} = $fieldHeading;
$self->{FUNCORMETHOD} = $func_or_method;
$self->{APIREFSETUPDONE} = 1;
return (\@constants, \@fields, \@params, $fieldHeading, $func_or_method, \@local_variables);
}
sub tagNameRegexpAndSuperclassFieldNameForType
{
my $self = shift;
my $class = ref($self) || $self;
my $tagname = "";
my $tag_re = "";
my $superclassfieldname = "Superclass";
SWITCH: {
($class =~ /HeaderDoc\:\:Constant/) && do {
$tag_re = "const(?:ant)?|var";
$tagname = "constant";
last SWITCH;
};
($class =~ /HeaderDoc\:\:Enum/) && do {
$tag_re = "enum";
$tagname = "enum";
last SWITCH;
};
($class =~ /HeaderDoc\:\:Function/) && do {
$tag_re = "method|function";
$tagname = "function or method";
last SWITCH;
};
($class =~ /HeaderDoc\:\:Method/) && do {
$tag_re = "method";
$tagname = "method";
last SWITCH;
};
($class =~ /HeaderDoc\:\:PDefine/) && do {
$tag_re = "define(?:d)?|function";
$tagname = "CPP macro";
last SWITCH;
};
($class =~ /HeaderDoc\:\:Struct/) && do {
$tag_re = "struct|union";
if ($self->isUnion()) { $tagname = "union"; }
else { $tagname = "struct"; }
last SWITCH;
};
($class =~ /HeaderDoc\:\:Typedef/) && do {
$tag_re = "typedef|function|class";
$tagname = "typedef";
last SWITCH;
};
($class =~ /HeaderDoc\:\:Var/) && do {
if ($self->isProperty()) {
$tag_re = "var|method|property|const(?:ant)?";
$tagname = "variable";
} else {
$tag_re = "var|property|const(?:ant)?";
$tagname = "variable";
}
last SWITCH;
};
($class =~ /HeaderDoc\:\:ObjCClass/) && do {
$tag_re = "class|template";
$tagname = "Objective-C class";
$superclassfieldname = "Extends Class";
last SWITCH;
};
($class =~ /HeaderDoc\:\:ObjCCategory/) && do {
$tag_re = "category|template";
$tagname = "Objectice-C category";
$superclassfieldname = "Extends Class";
last SWITCH;
};
($class =~ /HeaderDoc\:\:ObjCProtocol/) && do {
$tag_re = "protocol|template";
$tagname = "Objectice-C protocol";
$superclassfieldname = "Extends Protocol";
last SWITCH;
};
($class =~ /HeaderDoc\:\:CPPClass/) && do {
$tag_re = "class|interface";
$tagname = "class or interface";
last SWITCH;
};
{
print STDERR "Unknown type: $class\n";
}
};
return ($tagname, $tag_re, $superclassfieldname);
}
sub taggedParamFind
{
my $self = shift;
my $name = shift;
foreach my $parm ($self->taggedParameters()) {
if ($parm->name() eq $name) {
return $parm;
}
}
return undef;
}
sub processComment
{
my($self) = shift;
my $fieldArrayRef = shift;
my @fields = @$fieldArrayRef;
my $fullpath = $self->fullpath();
my $linenuminblock = $self->linenuminblock();
my $blockoffset = $self->blockoffset();
my $linenum = $self->linenum();
my $localDebug = 0;
my $olddisc = $self->halfbaked_discussion();
my $isProperty = $self->can('isProperty') ? $self->isProperty() : 0;
my $vargroup = "";
if ($localDebug) {
printFields($fieldArrayRef);
cluck("BT\n");
}
print STDERR "SELF IS $self\n" if ($localDebug);
my $lang = $self->lang();
my $sublang = $self->sublang();
my $lastField = scalar(@fields);
my $class = ref($self) || $self;
if ($class =~ /HeaderDoc::HeaderElement/) {
return;
}
$self->{HASPROCESSEDCOMMENT} = 1;
my ($tagname, $tag_re, $superclassfieldname) = $self->tagNameRegexpAndSuperclassFieldNameForType();
my $seen_top_level_field = 0;
my $first_field = 1;
my $callbackObj = 0;
foreach my $field (@fields) {
print STDERR "Comment field is |$field|\n" if ($localDebug);
print STDERR "Seen top level field: $seen_top_level_field\n" if ($localDebug);
my $fieldname = "";
my $top_level_field = 0;
if ($field =~ /^(\w+)(\s|$)/) {
$fieldname = $1;
$top_level_field = validTag($fieldname, 1);
if ($top_level_field && $seen_top_level_field && ($fieldname !~ /const(ant)?/) &&
($fieldname !~ /var/) && (!$self->isBlock() || $fieldname ne "define")) {
$field =~ s/^(\w+)(\s)//s;
my $spc = $2;
my $newtag = "field";
if ($class =~ /HeaderDoc\:\:Enum/) {
$newtag = "constant";
} elsif ($class =~ /HeaderDoc\:\:Function/ ||
$class =~ /HeaderDoc\:\:Method/) {
$newtag = "param";
} elsif ($class =~ /HeaderDoc\:\:ObjCClass/ ||
$class =~ /HeaderDoc\:\:ObjCProtocol/ ||
$class =~ /HeaderDoc\:\:ObjCCategory/ ||
$class =~ /HeaderDoc\:\:ObjCContainer/ ||
$class =~ /HeaderDoc\:\:CPPClass/) {
$newtag = "discussion";
} elsif ($class =~ /HeaderDoc\:\:Typedef/) {
if ($fieldname eq "function") {
$newtag = "callback";
} elsif ($fieldname =~ /define(d)?/ || $fieldname eq "var") {
$newtag = "constant";
}
}
$field = "$newtag$spc$field";
$top_level_field = 0;
warn "$fullpath:$linenum: Duplicate top level tag \"$fieldname\" detected\n".
"in comment. Maybe you meant \"$newtag\".\n";
} elsif ($top_level_field && $seen_top_level_field && ($fieldname eq "constant" || $fieldname eq "const")) {
$top_level_field = 0;
} elsif ($top_level_field && $seen_top_level_field && ($fieldname eq "var")) {
$top_level_field = 0;
}
if ($class =~ /HeaderDoc\:\:Var/ && !$isProperty) {
if (!$seen_top_level_field && $fieldname eq "field") {
if ($sublang !~ /^occ/o) {
warn "Field \@$fieldname found in \@var declaration.\nYou probably meant \@var instead.\n" if (!$HeaderDoc::running_test);
$field =~ s/^(\w+)(\s)//s;
my $spc = $2;
$field = "var$spc$field";
$top_level_field = 1;
}
}
}
}
SWITCH: {
($field =~ /^\/(\*|\/)\!/o && $first_field) && do {
my $copy = $field;
$copy =~ s/^\/(\*|\/)\!\s*//s;
if (length($copy)) {
$self->discussion($copy);
$seen_top_level_field = 1;
}
last SWITCH;
};
($self->isAPIOwner() && $field =~ s/^alsoinclude\s+//sio) && do {
$self->alsoInclude($field);
last SWITCH;
};
($callbackObj) &&
do {
my $fallthrough = 0;
my $cbName = $callbackObj->name();
print STDERR "In callback: field is '$field'\n" if ($localDebug);
if ($field =~ s/^(param|field)\s+//sio) {
$field =~ s/^\s+|\s+$//go;
$field =~ /(\w*)\s*(.*)/so;
my $paramName = $1;
my $paramDesc = $2;
$callbackObj->addToUserDictArray({"$paramName" => "$paramDesc"});
} elsif ($field =~ s/^internal\s+//sio) {
$callbackObj->isInternal(1);
} elsif ($field =~ s/^apiuid\s+//sio) {
$callbackObj->requestedUID($field);
} elsif ($field =~ s/^return(s)?\s+//sio) {
$field =~ s/^\s+|\s+$//go;
$callbackObj->addToUserDictArray({"Returns" => "$field"});
} elsif ($field =~ s/^result\s+//sio) {
$field =~ s/^\s+|\s+$//go;
$field =~ /(\w*)\s*(.*)/so;
$callbackObj->addToUserDictArray({"Result" => "$field"});
} else {
print STDERR "Adding callback field to typedef[1]. Callback name: $cbName.\n" if ($localDebug);
if ($callbackObj->{ISDEFINE}) {
$self->addTaggedParameter($callbackObj);
} else {
$self->addToFields($callbackObj);
}
$callbackObj = undef;
$fallthrough = 1;
}
if (!$fallthrough) {
last SWITCH;
}
};
($field =~ s/^internal\s+//sio) && do {
$self->isInternal(1);
last SWITCH;
};
($field =~ s/^apiuid\s+//sio) && do {
$self->requestedUID($field);
last SWITCH;
};
($field =~ s/^serial\s+//sio) && do {$self->attribute("Serial Field Info", $field, 1); last SWITCH;};
(($class =~ /HeaderDoc\:\:Function/ ||
$class =~ /HeaderDoc\:\:Method/) && $field =~ s/^serialData\s+//io) && do {$self->attribute("Serial Data", $field, 1); last SWITCH;};
($field =~ s/^serialfield\s+//sio) && do {
if (!($field =~ s/(\S+)\s+(\S+)\s+//so)) {
warn "$fullpath:$linenum: warning: serialfield format wrong.\n";
} else {
my $name = $1;
my $type = $2;
my $description = "(no description)";
my $att = "$name<br>\nType: $type";
$field =~ s/^(<br>|\s)*//sgio;
if (length($field)) {
$att .= "<br>\nDescription: $field";
}
$self->attributelist("Serial Fields", $att, 1);
}
last SWITCH;
};
($field =~ s/^unformatted(\s+|$)//sio) && do {
$self->preserve_spaces(1);
last SWITCH;
};
(!$self->isAPIOwner() && $field =~ s/^templatefield\s+//sio) && do {
$self->attributelist("Template Field", $
field);
last SWITCH;
};
($self->isAPIOwner() && $field =~ s/^templatefield(\s+)/$1/sio) && do {
$field =~ s/^\s+|\s+$//go;
$field =~ /(\w*)\s*(.*)/so;
my $fName = $1;
my $fDesc = $2;
my $fObj = HeaderDoc::MinorAPIElement->new("LANG" => $lang, "SUBLANG" => $sublang);
$fObj->apiOwner($self);
$fObj->linenuminblock($linenuminblock);
$fObj->blockoffset($blockoffset);
$fObj->apiOwner($self);
$fObj->outputformat($self->outputformat);
$fObj->name($fName);
$fObj->discussion($fDesc);
$self->addToFields($fObj);
last SWITCH;
};
($self->isAPIOwner() && $field =~ s/^super(class|)(\s+)/$2/sio) && do {
$self->attribute($superclassfieldname, $field, 0);
$self->explicitSuper(1);
last SWITCH;
};
($self->isAPIOwner() && $field =~ s/^instancesize(\s+)/$1/sio) && do {$self->attribute("Instance Size", $field, 0); last SWITCH;};
($field =~ s/^performance(\s+)/$1/sio) && do {$self->attribute("Performance", $field, 1); last SWITCH;};
($self->isAPIOwner() && $field =~ s/^nestedclass(\s+)/$1/sio) && do {$self->attributelist("Nested Classes", $field); last SWITCH;};
($self->isAPIOwner() && $field =~ s/^coclass(\s+)/$1/sio) && do {$self->attributelist("Co-Classes", $field); last SWITCH;};
($self->isAPIOwner() && $field =~ s/^helper(class|)(\s+)/$2/sio) && do {$self->attributelist("Helper Classes", $field); last SWITCH;};
($self->isAPIOwner() && $field =~ s/^helps(\s+)/$1/sio) && do {$self->attribute("Helps", $field, 0); last SWITCH;};
($self->isAPIOwner() && $field =~ s/^classdesign(\s+)/$1/sio) && do {$self->attribute("Class Design", $field, 1); last SWITCH;};
($self->isAPIOwner() && $field =~ s/^dependency(\s+)/$1/sio) && do {$self->attributelist("Dependencies", $field); last SWITCH;};
($self->isAPIOwner() && $field =~ s/^ownership(\s+)/$1/sio) && do {$self->attribute("Ownership Model", $field, 1); last SWITCH;};
($field =~ s/^security(\s+)/$1/sio) && do {$self->attribute("Security", $field, 1); last SWITCH;};
($self->isAPIOwner() && $field =~ s/^whysubclass(\s+)/$1/sio) && do {$self->attribute("Reason to Subclass", $field, 1); last SWITCH;};
(($self->isAPIOwner() || $class =~ /HeaderDoc\:\:Function/ ||
$class =~ /HeaderDoc\:\:Method/ ||
($class =~ /HeaderDoc\:\:Var/ && $isProperty)) &&
$field =~ s/^(throws|exception)(\s+)/$2/sio) && do {
$self->throws($field);
last SWITCH;
};
($field =~ s/^namespace(\s+)/$1/sio) && do {$self->namespace($field); last SWITCH;};
($self->isAPIOwner() && $field =~ s/^unsorted\s+//sio) && do {$self->unsorted(1); last SWITCH;};
($field =~ s/^abstract\s+//sio) && do {$self->abstract($field); last SWITCH;};
($field =~ s/^brief\s+//sio) && do {$self->abstract($field, 1); last SWITCH;};
($field =~ s/^(discussion|details|description)(\s+|$)//sio) && do {
if ($class =~ /HeaderDoc\:\:PDefine/ && $self->inDefineBlock() && length($olddisc)) {
}
if (!length($field)) { $field = "\n"; }
$self->discussion($field);
last SWITCH;
};
($field =~ s/^availability\s+//sio) && do {$self->availability($field); last SWITCH;};
($field =~ s/^since\s+//sio) && do {$self->availability($field); last SWITCH;};
($field =~ s/^author\s+//sio) && do {$self->attribute("Author", $field, 0); last SWITCH;};
($field =~ s/^group\s+//sio) && do {$self->group($field); last SWITCH;};
($field =~ s/^vargroup\s+//sio) && do {
$field =~ s/[\n\r]/ /sg;
$field =~ s/^\s*//sg;
$field =~ s/\s*$//sg;
$vargroup = $field;
last SWITCH;
};
($class =~ /HeaderDoc\:\:PDefine/ && $self->isBlock() && $field =~ s/^hidesingletons(\s+)/$1/sio) && do {$self->{HIDESINGLETONS} = 1; last SWITCH;};
(($class =~ /HeaderDoc\:\:PDefine/ || $class =~ /HeaderDoc\:\:Function/ || $class =~ /HeaderDoc\:\:Method/) && $field =~ s/^hidecontents(\s+)/$1/sio) && do {$self->hideContents(1); last SWITCH;};
(($class =~ /HeaderDoc\:\:Function/ || $class =~ /HeaderDoc\:\:Method/) && $field =~ s/^(function|method)group\s+//sio) &&
do {$self->group($field); last SWITCH;};
($class =~ /HeaderDoc\:\:PDefine/ && $field =~ s/^parseOnly(\s+|$)//sio) && do { $self->parseOnly(1); last SWITCH; };
($class =~ /HeaderDoc\:\:PDefine/ && $field =~ s/^noParse(\s+|$)//sio) && do { print STDERR "Parsing will be skipped.\n" if ($localDebug); $HeaderDoc::skipNextPDefine = 1; last SWITCH; };
($field =~ s/^indexgroup\s+//sio) && do {$self->indexgroup($field); last SWITCH;};
($field =~ s/^version\s+//sio) && do {$self->attribute("Version", $field, 0); last SWITCH;};
($field =~ s/^deprecated\s+//sio) && do {$self->attribute("Deprecated", $field, 0); last SWITCH;};
($field =~ s/^updated\s+//sio) && do {$self->updated($field); last SWITCH;};
($field =~ s/^attribute\s+//sio) && do {
my ($attname, $attdisc, $namedisc) = &getAPINameAndDisc($field, $self->lang());
if (length($attname) && length($attdisc)) {
$attdisc =~ s/^\s*//s;
$attdisc =~ s/\s*$//s;
$self->attribute($attname, $attdisc, 0);
} else {
warn "$fullpath:$linenum: warning: Missing name/discussion for attribute\n";
}
last SWITCH;
};
($field =~ s/^attributelist\s+//sio) && do {
$field =~ s/^\s*//so;
$field =~ s/\s*$//so;
my ($name, $lines) = split(/\n/, $field, 2);
$name =~ s/^\s*//so;
$name =~ s/\s*$//so;
$lines =~ s/^\s*//so;
$lines =~ s/\s*$//so;
if (length($name) && length($lines)) {
my @attlines = split(/\n/, $lines);
foreach my $line (@attlines) {
$self->attributelist($name, $line);
}
} else {
warn "$fullpath:$linenum: warning: Missing name/discussion for attributelist\n";
}
last SWITCH;
};
($field =~ s/^attributeblock\s+//sio) && do {
my ($attname, $attdisc, $namedisc) = &getAPINameAndDisc($field, $self->lang());
if (length($attname) && length($attdisc)) {
$self->attribute($attname, $attdisc, 1);
} else {
warn "$fullpath:$linenum: warning: Missing name/discussion for attributeblock\n";
}
last SWITCH;
};
($field =~ /^see(also|)\s+/sio) &&
do {
my $rest;
($field, $rest) = splitOnPara($field);
$self->see($field);
if ($rest =~ /\S/s) {
if ($class =~ /HeaderDoc\:\:PDefine/ && $self->inDefineBlock() && length($olddisc)) {
}
$self->discussion($rest);
};
last SWITCH;
};
(($class =~ /HeaderDoc\:\:(?:Function|Method|CPPClass|ObjC(?:Container|Category|Class|Protocol))/) && $field =~ s/^var?\s+//sio) &&
do {
$field =~ s/^\s+|\s+$//go;
$field =~ /(\S*)\s*(.*)/so; my $cName = $1;
my $cDesc = $2;
if ($field =~ /^(.*?)\n(.*)$/so) {
$cName = $1;
$cDesc = $2;
}
my $cObj = HeaderDoc::MinorAPIElement->new("LANG" => $lang, "SUBLANG" => $sublang);
$cObj->apiOwner($self);
$cObj->outputformat($self->outputformat);
$cObj->name($cName);
$cObj->fullpath($self->fullpath());
$cObj->group($vargroup);
$cObj->autodeclaration(1);
$cObj->abstract($cDesc);
$self->addVariable($cObj);
$self->apirefSetup();
my $name = $self->name();
if ($name eq "") {
$name = "$cName";
$self->firstconstname($name);
}
last SWITCH;
};
(($class =~ /HeaderDoc\:\:Enum/ || $class =~ /HeaderDoc\:\:Typedef/) && $field =~ s/^const(ant)?\s+//sio) &&
do {
if ($self->can("isEnumList")) {
$self->isEnumList(1);
}
$field =~ s/^\s+|\s+$//go;
$field =~ /(\S*)\s*(.*)/so; my $cName = $1;
my $cDesc = $2;
my $cObj = HeaderDoc::MinorAPIElement->new("LANG" => $lang, "SUBLANG" => $sublang);
$cObj->apiOwner($self);
$cObj->outputformat($self->outputformat);
$cObj->name($cName);
$cObj->discussion($cDesc);
$self->addConstant($cObj);
my $name = $self->name();
if ($name eq "") {
$name = "$cName";
$self->firstconstname($name);
}
last SWITCH;
};
(($class =~ /HeaderDoc\:\:Struct/ || $class =~ /HeaderDoc\:\:Typedef/) && $field =~ s/^callback\s+//sio) &&
do {
$field =~ s/^\s+|\s+$//go;
$field =~ /(\w*)\s*(.*)/so;
my $cbName = $1;
my $cbDesc = $2;
if ($callbackObj && $callbackObj->{ISDEFINE}) {
$self->addTaggedParameter($callbackObj);
} elsif ($callbackObj) {
$self->addToFields($callbackObj);
}
$callbackObj = HeaderDoc::MinorAPIElement->new("LANG" => $lang, "SUBLANG" => $sublang);
$callbackObj->apiOwner($self);
$callbackObj->outputformat($self->outputformat);
$callbackObj->name($cbName);
$callbackObj->discussion($cbDesc);
$callbackObj->type("callback");
print STDERR "Found callback. Callback name: $cbName.\n" if ($localDebug);
last SWITCH;
};
(($class =~ /HeaderDoc\:\:Function/ || $class =~ /HeaderDoc\:\:Method/ || $class =~ /HeaderDoc\:\:Struct/ ||
$class =~ /HeaderDoc\:\:Typedef/ || $class =~ /HeaderDoc\:\:PDefine/ ||
$class =~ /HeaderDoc\:\:Var/) && $field =~ s/^(param|field)\s+//sio) &&
do {
my $fieldname = $1;
my $rest;
$field =~ s/^\s+|\s+$//go; # trim leading and trailing whitespace
$field =~ /(\S*)\s*(.*)/so;
my $pName = $1;
my $pDesc = $2;
my $param = $self->taggedParamFind($pName);
my $new = 0;
if (!$param) { $param = HeaderDoc::MinorAPIElement->new("LANG" => $lang, "SUBLANG" => $sublang); $new = 1;}
$param->apiOwner($self);
$param->outputformat($self->outputformat);
$param->name($pName);
if ($new) {
$param->discussion($pDesc);
if (($class =~ /HeaderDoc\:\:Typedef/ || $class =~ /HeaderDoc\:\:Struct/) &&
$field =~ /^param\s+/) {
$param->type("funcPtr");
$self->addToFields($param);
} else {
$self->addTaggedParameter($param);
}
} else {
$param->discussion($param->discussion()."\n\n".$pDesc);
}
if ($class =~ /HeaderDoc\:\:Var/ && !$isProperty) {
warn "Field \@$fieldname found in \@var declaration.\nYou should use \@property instead.\n" if (!$HeaderDoc::running_test);
}
if ($rest =~ /\S/s) {
if ($class =~ /HeaderDoc\:\:PDefine/ && $self->inDefineBlock() && length($olddisc)) {
}
$self->discussion($rest);
};
last SWITCH;
};
(($class =~ /HeaderDoc\:\:Function/ || $class =~ /HeaderDoc\:\:Method/ ||
$class =~ /HeaderDoc\:\:Typedef/ || $class =~ /HeaderDoc\:\:Struct/ ||
$class =~ /HeaderDoc\:\:PDefine/ ||
$class =~ /HeaderDoc\:\:Var/) && $field =~ s/^return(s)?\s+//sio) &&
do {
if ($class =~ /HeaderDoc\:\:Typedef/) {
$self->isFunctionPointer(1);
}
if ($class =~ /HeaderDoc\:\:Var/ && !$isProperty) {
warn "Field \@return found in \@var declaration.\nYou should use \@property instead.\n" if (!$HeaderDoc::running_test);
}
$self->result($field);
last SWITCH;
};
(($class =~ /HeaderDoc\:\:Function/ || $class =~ /HeaderDoc\:\:Method/ ||
$class =~ /HeaderDoc\:\:Typedef/ || $class =~ /HeaderDoc\:\:Struct/ ||
$class =~ /HeaderDoc\:\:PDefine/ ||
$class =~ /HeaderDoc\:\:Var/) && $field =~ s/^result\s+//sio) &&
do {
if ($class =~ /HeaderDoc\:\:Typedef/) {
$self->isFunctionPointer(1);
}
if ($class =~ /HeaderDoc\:\:Var/ && !$isProperty) {
warn "Field \@result found in \@var declaration.\nYou should use \@property instead.\n" if (!$HeaderDoc::running_test);
}
$self->result($field);
last SWITCH;
};
($top_level_field == 1) &&
do {
my $keepname = 1;
my $blockrequest = 0;
my $isavmacro = 0;
print STDERR "TLF: $field\n" if ($localDebug);
my $pattern = "";
if ($class =~ /HeaderDoc\:\:PDefine/ && $field =~ s/^(availabilitymacro)(\s+|$)/$2/sio) {
$self->isAvailabilityMacro(1);
$keepname = 1;
$self->parseOnly(1);
$isavmacro = 1;
} elsif ($class =~ /HeaderDoc\:\:PDefine/ && $field =~ s/^(define(?:d)?block)(\s+)/$2/sio) {
$keepname = 1;
$self->isBlock(1);
$blockrequest = 1;
} elsif ($class =~ /HeaderDoc\:\:CPPClass/) {
$pattern = ":|public|private|[()]";
} elsif ($class =~ /HeaderDoc\:\:Method/) {
$pattern = ":|[()]";
} elsif ($class =~ /HeaderDoc\:\:Function/) {
$pattern = "::|[()]";
} elsif ($field =~ /category\s+/) {
$pattern = "[():]";
}
if (!$blockrequest && $field =~ s/^($tag_re)(\s+|$)/$2/i) {
print STDERR "tag_re[1]: tag matches\n" if ($localDebug);
$keepname = 1;
} elsif (!$blockrequest && !$isavmacro) {
print STDERR "tag_re[2] tag does NOT match\n" if ($localDebug);
$field =~ s/(\w+)(\s|$)/$2/sio;
$keepname = 0;
}
my ($name, $abstract_or_disc, $namedisc) = getAPINameAndDisc($field, $self->lang(), $pattern);
print STDERR "FIELD: $field\nNAME: $name AOD: $abstract_or_disc ND: $namedisc" if ($localDebug);
print STDERR "KEEPNAME: $keepname\n" if ($localDebug);
if ($class =~ /HeaderDoc\:\:PDefine/ && $self->isBlock()) {
print STDERR "ISBLOCK (BLOCKREQUEST=$blockrequest)\n" if ($localDebug);
if ($blockrequest) {
print STDERR "Added block name $name\n" if ($localDebug);
if (length($abstract_or_disc)) {
if ($namedisc) {
$self->name($name." ".$abstract_or_disc);
} else {
$self->name($name);
$self->discussion($abstract_or_disc);
}
} else {
$self->name($name);
}
} else {
print STDERR "Added block member $name\n" if ($localDebug);
if ($callbackObj && $callbackObj->{ISDEFINE}) {
$self->addTaggedParameter($callbackObj);
} elsif ($callbackObj) {
$self->addToFields($callbackObj);
}
$callbackObj = HeaderDoc::MinorAPIElement->new("LANG" => $lang, "SUBLANG" => $sublang);
$callbackObj->apiOwner($self);
$callbackObj->name($name);
my $ref = $self->addToIncludedDefines($callbackObj);
$callbackObj = ${$ref};
bless($callbackObj, "HeaderDoc::HeaderElement");
bless($callbackObj, $callbackObj->class());
if (length($abstract_or_disc)) {
if ($namedisc) {
$callbackObj->nameline_discussion($abstract_or_disc);
} else {
$callbackObj->discussion($abstract_or_disc);
}
}
$callbackObj->{ISDEFINE} = 1;
}
} else {
if (length($name)) {
if ($keepname && (!$self->isAPIOwner() || !$HeaderDoc::ignore_apiowner_names)) {
print STDERR "SET NAME TO $name\n" if ($localDebug);
$self->name($name);
}
}
if (length($abstract_or_disc)) {
if ($namedisc) {
$self->nameline_discussion($abstract_or_disc);
} else {
$self->discussion($abstract_or_disc);
}
}
}
last SWITCH;
};
{
if (length($field)) {
warn "$fullpath:$linenum: warning: Unknown field (\@$field) in $tagname comment (".$self->name().")\n";
}
};
}
$first_field = 0;
if ($top_level_field) { $seen_top_level_field = 1; }
}
if ($callbackObj) {
if ($callbackObj->{ISDEFINE}) {
$self->addTaggedParameter($callbackObj);
} else {
$self->addToFields($callbackObj);
}
}
return;
}
sub hideContents
{
my $self = shift;
if (@_) {
$self->{HIDECONTENTS} = shift;
}
return $self->{HIDECONTENTS};
}
sub inDefineBlock
{
my $self = shift;
if (@_) {
$self->{INDEFINEBLOCK} = shift;
}
return $self->{INDEFINEBLOCK};
}
sub strcasecmp($$)
{
my $a = shift;
my $b = shift;
return (lc($a) cmp lc($b));
}
sub unregister
{
my $self = shift;
my @arr = ();
my $localDebug = 0;
my $group = $self->group();
if ($group) {
$self->apiOwner()->removeFromGroup($group, $self);
}
foreach my $tp ($self->taggedParameters()) {
push(@arr, $tp);
}
foreach my $const ($self->constants()) {
push(@arr, $const);
}
foreach my $variable ($self->variables()) {
push(@arr, $variable);
}
if ($self->can("fields")) {
foreach my $field ($self->fields()) {
push(@arr, $field);
}
}
foreach my $obj (@arr) {
my $uid = $obj->apiuid();
print STDERR "Unregistering UID $uid\n" if ($localDebug);
unregisterUID($uid, $obj->name(), $obj);
unregister_force_uid_clear($uid);
}
$self->noRegisterUID(1);
}
sub noRegisterUID
{
my $self = shift;
my $localDebug = 0;
if (@_) {
my $val = shift;
print STDERR "No register uid set to $val ($self).\n" if ($localDebug);
$self->{NOREGISTERUID} = $val;
}
return $self->{NOREGISTERUID};
}
sub wipeUIDCache
{
my $self = shift;
my $localDebug = 0;
print STDERR "APIUID and LINKUID wiped ($self).\n" if ($localDebug);
$self->{APIUID} = undef;
$self->{LINKUID} = undef;
}
sub suppressChildren
{
my $self = shift;
my $localDebug = 0;
if (@_) {
my $val = shift;
cluck("Suppress children set to $val ($self).\n") if ($localDebug);
$self->{SUPPRESSCHILDREN} = $val;
}
return $self->{SUPPRESSCHILDREN};
}
sub declaredIn
{
my $self = shift;
my $class = ref($self) || $self;
my $apio = $self->apiOwner();
if (!$apio) { return ""; }
if ($apio->outputformat() eq "hdxml") {
return "";
}
if ($self->isAPIOwner()) {
if ($class =~ /HeaderDoc::Header/) {
return "";
} else {
my $name = $apio->name();
my $apiref = $apio->apiuid();
return "<a href=\"../../index.html\" logicalPath=\"$apiref\" target=\"_top\" machineGenerated=\"true\">$name</a>";
}
} else {
my $name = $apio->name();
my $apiref = $apio->apiuid();
return "<!-- a logicalPath=\"$apiref\" target=\"_top\" machineGenerated=\"true\" -->$name<!-- /a -->";
}
return "";
}
sub headerDocMark
{
my $self = shift;
my $type = shift;
my $startend = shift;
my $uid = $self->apiuid();
return "<!-- headerDoc=$type;uid=".$uid.";name=$startend -->";
}
sub doExternalStyle
{
my $self = shift;
my $liststring = shift;
my @list = split(/\s/, $liststring);
my $string = "";
foreach my $styleSheet (@list) {
$styleSheet =~ s/{\@docroot}/\@\@docroot/sg;
$string .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"$styleSheet\">\n";
}
if ($self->outputformat eq "hdxml") {
return xml_fixup_links($self, $string);
} else {
return html_fixup_links($self, $string);
}
}
sub free
{
my $self = shift;
my $freechildrenraw = shift; my $keepParseTreeAndState = shift;
my $newParseTreeOwner = shift;
print STDERR "NPTO: $newParseTreeOwner\n" if ($HeaderDoc::debugAllocations);
my $parseTree_ref = $self->parseTree();
cluck("FREEING $self\n") if ($HeaderDoc::debugAllocations);
if ($parseTree_ref) {
my $parseTree = ${$parseTree_ref};
bless($parseTree, "HeaderDoc::ParseTree");
print "REMOVING FROM MAIN ".$parseTree."\n" if ($HeaderDoc::debugAllocations);
$parseTree->apiOwnerSub($self, $newParseTreeOwner || undef, 1);
$parseTree->dbprint(1) if ($HeaderDoc::debugAllocations);
if (!$keepParseTreeAndState) { $parseTree->dispose(); }
$self->{PARSETREE} = undef;
}
if ($self->{PARSETREELIST}) {
foreach my $treeref (@{$self->{PARSETREELIST}}) {
print "REMOVING FROM PARSETREELIST ".${$treeref}."\n" if ($HeaderDoc::debugAllocations);
${$treeref}->apiOwnerSub($self, $newParseTreeOwner || undef, 1);
${$treeref}->dbprint(1) if ($HeaderDoc::debugAllocations);
if (!$keepParseTreeAndState) { ${$treeref}->dispose(); }
}
}
$self->{PARSETREELIST} = undef;
if ($self->{PARSETREECLEANUP}) {
foreach my $treeref (@{$self->{PARSETREECLEANUP}}) {
print "REMOVING FROM CLEANUP ".${$treeref}."\n" if ($HeaderDoc::debugAllocations);
${$treeref}->apiOwnerSub($self, $newParseTreeOwner || undef, 1);
${$treeref}->dbprint(1) if ($HeaderDoc::debugAllocations);
if (!$keepParseTreeAndState) { ${$treeref}->dispose(); }
}
}
$self->{PARSETREECLEANUP} = undef;
my $state = $self->{PARSERSTATE};
if ($state && !$keepParseTreeAndState) { $state->free(); }
$self->{PARSERSTATE} = undef;
if (!$self->noRegisterUID()) {
dereferenceUIDObject($self->apiuid(), $self);
}
$self->{APIOWNER} = undef;
$self->{MASTERENUM} = undef;
$self->{MAINOBJECT} = undef;
if ($self->{NAMEREFS}) {
my @arr = @{$self->{NAMEREFS}};
foreach my $name (@arr) {
$HeaderDoc::namerefs{$name} = undef;
}
}
$self->{NAMEREFS} = undef;
$self->setAPIOBackReferences( $self->{CONSTANTS}, 1, $newParseTreeOwner);
$self->setAPIOBackReferences( $self->{FIELDS}, 1, $newParseTreeOwner);
$self->setAPIOBackReferences( $self->{VARIABLES}, 1, $newParseTreeOwner);
$self->setAPIOBackReferences( $self->{INCLUDED_DEFINES}, 1, $newParseTreeOwner);
$self->setAPIOBackReferences( $self->{KEEPPARAMS}, 1, $newParseTreeOwner);
$self->setAPIOBackReferences( $self->{KEEPVARIABLES}, 1, $newParseTreeOwner);
$self->setAPIOBackReferences( $self->{KEEPFIELDS}, 1, $newParseTreeOwner);
$self->setAPIOBackReferences( $self->{KEEPCONSTANTS}, 1, $newParseTreeOwner);
my $class = ref($self) || $self;
if ((!$self->isBlock()) || ($newParseTreeOwner)) {
$self->setAPIOBackReferences( $self->{PARSEDPARAMETERS}, 1, $newParseTreeOwner);
}
$self->setAPIOBackReferences( $self->{TAGGEDPARAMETERS}, 1, $newParseTreeOwner);
$self->{CONSTANTS} = undef;
$self->{FIELDS} = undef;
$self->{VARIABLES} = undef;
$self->{INCLUDED_DEFINES} = undef;
$self->{ATTRIBUTELISTS} = undef;
$self->{SEEALSODUPCHECK} = undef;
$self->{KEEPPARAMS} = undef;
$self->{KEEPVARIABLES} = undef;
$self->{KEEPFIELDS} = undef;
$self->{KEEPCONSTANTS} = undef;
$self->{PARSEDPARAMETERS} = undef;
$self->{TAGGEDPARAMETERS} = undef;
if ($HeaderDoc::debugAllocations) {
print STDERR "Dumping hash $self\n";
printHash(%{$self});
print STDERR "DUMPING $self WITH DEBUG INFO\n";
DumpWithOP($self);
}
$self = ();
}
sub DESTROY
{
my $self = shift;
print STDERR "Destroying $self\n" if ($HeaderDoc::debugAllocations);
}
sub dbprint_expanded
{
my $unknown_var = shift;
my $leadspace = "";
if ($_) {
$leadspace = shift;
}
if ($unknown_var =~ "REF") { $unknown_var = ref($unknown_var); }
my $retstring = $unknown_var;
if (ref($unknown_var) eq "ARRAY") {
print STDERR "REF IS ".ref($unknown_var)."\n";
$retstring .= "\n".$leadspace."ARRAY ELEMENTS:\n";
my $pos = 0;
while ($pos < scalar(@{$unknown_var})) {
$retstring .= $leadspace." ".sprintf("%08d : ", $pos). dbprint_expanded(@{$unknown_var}[$pos], $leadspace." ")."\n";
$pos++;
}
} elsif (ref($unknown_var) ne "") {
$retstring .= "\n".$leadspace."HASH ELEMENTS:\n";
foreach my $elt (keys %{$unknown_var}) {
if ($elt =~ "APIOWNER" || $elt =~ "MASTERENUM") { next; }
$retstring .= $leadspace." ".sprintf("%8s : ", $elt). dbprint_expanded($unknown_var->{$elt}, $leadspace." ")."\n";
}
}
return $retstring;;
}
sub isBlock {
my $self = shift;
if (@_) {
$self->{ISBLOCK} = shift;
if ($self->{ISBLOCK}) {
$self->fixParseTrees();
}
}
return $self->{ISBLOCK};
}
sub dbprint
{
my $self = shift;
my $expanded = shift;
my @keys = keys %{$self};
print STDERR "Dumping object $self...\n";
foreach my $key (@keys) {
if ($expanded) {
print STDERR "$key => ".dbprint_expanded($self->{$key})."\n";
} else {
print STDERR "$key => ".$self->{$key}."\n";
}
}
print STDERR "End dump of object $self.\n";
}
sub preserve_spaces
{
my $self = shift;
if (@_) {
$self->{PRESERVESPACES} = shift;
}
if (!defined($self->{PRESERVESPACES})) {
return 0;
}
return $self->{PRESERVESPACES};
}
sub isFramework
{
return 0;
}
sub getDoxyKind
{
my $self = shift;
my $class = ref($self) || $self;
if ($self->isAPIOwner()) {
if ($class =~ /HeaderDoc::Header/) {
return "file";
}
return "class";
}
if ($class =~ /HeaderDoc::Function/ || $class =~ /HeaderDoc::Method/) {
return "function";
}
if ($class =~ /HeaderDoc::Constant/) {
return "variable";
}
if ($class =~ /HeaderDoc::Var/) {
return "variable";
}
if ($class =~ /HeaderDoc::Struct/) {
return "struct";
}
if ($class =~ /HeaderDoc::Typedef/) {
return "typedef";
}
if ($class =~ /HeaderDoc::Union/) {
return "union";
}
if ($class =~ /HeaderDoc::Enum/) {
return "enumeration";
}
if ($class =~ /HeaderDoc::PDefine/) {
return "define";
}
if ($class =~ /HeaderDoc::MinorAPIElement/) {
my $parent = $self->apiOwner();
my $parentclass = ref($parent) || $parent;
if ($parentclass =~ /HeaderDoc::Enum/) {
return "enumvalue";
} else {
return "variable";
}
}
}
sub _getDoxyTagString
{
my $self = shift;
my $prespace = shift;
my $class = ref($self) || $self;
my $doxyTagString = "";
my $kind = $self->getDoxyKind();
my $accessControl = "";
if ($self->can("accessControl")) {
$accessControl = $self->accessControl();
}
if ($accessControl =~ /\S/) {
$accessControl = " protection=\"$accessControl\"";
} else {
$accessControl = "";
}
$doxyTagString .= "$prespace<member kind=\"$kind\"$accessControl>\n";
my $arglist = "";
my $type = "";
if ($class =~ /HeaderDoc::Function/ || $class =~ /HeaderDoc::Method/) {
$type = $self->returntype();
$type =~ s/^\s*//s;
$type =~ s/\s*$//s;
$type =~ s/\s*\.\s*/./s;
$doxyTagString .= "$prespace <type>$type</type>\n";
my @args = $self->parsedParameters();
my $comma = "";
foreach my $obj (@args) {
$arglist .= $comma;
my $type .= $obj->type();
if ($class =~ /HeaderDoc::Method/) {
my $tagname = $obj->tagname();
if ($tagname =~ /\S/) {
$arglist .= "[$tagname] ";
}
$type =~ s/^\s*\(//s;
$type =~ s/\)\s*$//s;
}
$arglist .= $self->textToXML($type);
if ($arglist !~ /[ *]$/) {
$arglist .= " ";
}
$arglist .= $obj->name();
$comma = ",";
}
$arglist = "($arglist)";
} elsif ($class =~ /HeaderDoc::Var/ || $class =~ /HeaderDoc::Constant/) {
$type = $self->returntype();
$type =~ s/^\s*//s;
$type =~ s/\s*$//s;
$type =~ s/\s*\.\s*/./s;
$doxyTagString .= "$prespace <type>".$self->textToXML($type)."</type>\n";
}
$doxyTagString .= "$prespace <name>".$self->textToXML($self->rawname())."</name>\n";
$doxyTagString .= "$prespace <anchorfile></anchorfile>\n";
$doxyTagString .= "$prespace <anchor></anchor>\n";
$doxyTagString .= "$prespace <arglist>$arglist</arglist>\n";
$doxyTagString .= "$prespace</member>\n";
return $doxyTagString;
}
sub requestedUID
{
my $self = shift;
if (@_) {
my $rquid = shift;
$rquid =~ s/^\s*//s;
$rquid =~ s/\s*$//sg;
if ($rquid =~ /\s/) {
warn($self->filename().":".$self->linenum().": WARNING: Ignoring illegal apple_ref markup (contains whitespace)\n");
return $self->{REQUESTEDUID};
}
$self->{REQUESTEDUID} = $rquid;
registerUID($rquid, $self->rawname(), $self);
}
return $self->{REQUESTEDUID};
}
sub headerDump
{
my $self = shift;
print "HEADER\n";
print " |\n";
print " +-- Functions\n";
foreach my $obj ($self->functions()) {
print " | +-- ".$obj->name()."\n";
print " | | +-- obj: ".$obj."\n";
print " | | +-- isBlock: ".$obj->isBlock()."\n";
}
print " |\n";
print " +-- #defines\n";
foreach my $obj ($self->pDefines()) {
print " | +-- ".$obj->name()."\n";
print " | | +-- obj: ".$obj."\n";
print " | | +-- isBlock: ".$obj->isBlock()."\n";
}
}
sub getMethodType
{
my $self = shift;
my $class = ref($self) || $self;
my $apio = $self->apiOwner();
my $apioclass = ref($apio) || $apio;
if ($class =~ /HeaderDoc::PDefine/) {
return "define";
}
if ($apioclass eq "HeaderDoc::Header") {
return "func";
}
my $typename = "instm";
if ($class =~ /HeaderDoc::Method/) {
if (!$self->parserState()) {
cluck("We shouldn't hit this ($self).\n");
}
if ($self->parserState()->{occmethodtype} eq "+") {
$self->setIsInstanceMethod("NO");
if ($apioclass =~ /HeaderDoc::ObjCProtocol/) {
$typename = "intfcm";
} else {
$typename = "clm";
}
} else {
$self->setIsInstanceMethod("YES");
if ($apioclass =~ /HeaderDoc::ObjCProtocol/) {
$typename = "intfm";
} else {
$typename = "instm";
}
}
} else {
if (($self->lang() ne "C") && ($self->lang() ne "Csource")) {
return "instm";
}
if ($self->sublang() eq "C") {
return "intfm";
}
if ($self->returntype() =~ /(^|\s)static(\s|$)/) {
$typename = "clm";
} else {
$typename = "instm";
}
}
if ($self->isTemplate()) {
$typename = "ftmplt";
}
return $typename;
}
sub parserState {
my $self = shift;
if (@_) {
my $newstate = shift;
$self->{PARSERSTATE} = $newstate;
}
return $self->{PARSERSTATE};
}
sub isInternal {
my $self = shift;
if (@_) {
my $newval = shift;
$self->{ISINTERNAL} = $newval;
}
return $self->{ISINTERNAL};
}
sub namespace {
my $self = shift;
my $localDebug = 0;
if (@_) {
$self->{NAMESPACE} = shift;
}
print STDERR "namespace ".$self->{NAMESPACE}."\n" if ($localDebug);
return $self->{NAMESPACE};
}
sub setAPIOBackReferences
{
my $self = shift;
my $listref = shift;
my $freechildren = shift;
my $newowner = shift;
if ($listref) {
my @list = @{$listref};
foreach my $item (@list) {
$item->{APIOWNER} = $newowner;
if ($freechildren && !$newowner) {
$item->free();
}
}
}
}
sub addToNameRefs
{
my $self = shift;
my $name = shift;
my @arr = ();
if ($self->{NAMEREFS}) {
@arr = @{$self->{NAMEREFS}};
}
push(@arr, $name);
$self->{NAMEREFS} = \@arr;
}
sub addToCleanup
{
my $self = shift;
my $name = shift;
my @arr = ();
if ($self->{PARSETREECLEANUP}) {
@arr = @{$self->{PARSETREECLEANUP}};
}
push(@arr, $name);
$self->{PARSETREECLEANUP} = \@arr;
}
sub encoding
{
my $self = shift;
return $self->apiOwner()->encoding();
}
sub result {
my $self = shift;
if (@_) {
$self->{RESULT} = shift;
}
return filterHeaderDocTagContents($self->{RESULT});
}
sub origType
{
my $self = shift;
if (@_) {
my $origtype = shift;
$self->{ORIGTYPE} = $origtype;
}
return $self->{ORIGTYPE};
}
sub autoRelate
{
my $self = shift;
my @ar = ();
if ($self->{AUTORELATE}) {
@ar = @{$self->{AUTORELATE}};
}
if (@_) {
my $newvalue = shift;
my @parts = split(/\s+/, $newvalue);
push(@ar, $parts[1]);
}
$self->{AUTORELATE} = \@ar;
return $self->{AUTORELATE};
}
sub discussionLocked
{
my $self = shift;
if (@_) {
$self->{DISCUSSIONLOCKED} = $self->{DISCUSSION};
$self->{ABSTRACTLOCKED} = $self->{ABSTRACT};
$self->{DISCUSSION_SETLOCKED} = $self->{DISCUSSION_SET};
}
return $self->{DISCUSSIONLOCKED} ? 1 : 0;
}
sub unlockDiscussion
{
my $self = shift;
$self->{DISCUSSION} = $self->{DISCUSSIONLOCKED};
$self->{ABSTRACT} = $self->{ABSTRACTLOCKED};
$self->{DISCUSSION_SET} = $self->{DISCUSSION_SETLOCKED};
}
sub prepareDiscussionForTemporary
{
my $self = shift;
$self->{DISCUSSION} = undef;
$self->{ABSTRACT} = undef;
$self->{DISCUSSION_SET} = undef;
}
1;