Perl_function_2.test [plain text]
FrT;@1|>>0|$15|HeaderDoc::Test%22|$4|CODE$7|COMMENT$7|CPPCODE$15|EXPECTED_RESULT$23|EXPECTED_RESULT_ALLDECS$7|FAILMSG$8|FILENAME$4|LANG$4|NAME$7|SUBLANG$4|TYPE$155247|sub blockParse
{
my $filename = shift;
my $fileoffset = shift;
my $inputLinesRef = shift;
my $inputCounter = shift;
my $argparse = shift;
my $ignoreref = shift;
my $perheaderignoreref = shift;
my $perheaderignorefuncmacrosref = shift;
my $keywordhashref = shift;
my $case_sensitive = shift;
my $apwarn = 0;
if ($argparse && $apwarn) {
print STDERR "argparse\n";
}
# Initialize stuff
my @inputLines = @{$inputLinesRef};
my $declaration = "";
my $publicDeclaration = "";
# $HeaderDoc::fileDebug = 1;
# Debugging switches
my $retDebug = 0;
my $localDebug = 0 || $HeaderDoc::fileDebug;
my $operatorDebug = 0;
my $listDebug = 0;
my $parseDebug = 0 || $HeaderDoc::fileDebug;
my $sodDebug = 0 || $HeaderDoc::fileDebug;
my $valueDebug = 0;
my $parmDebug = 0;
my $cbnDebug = 0;
my $macroDebug = 0;
my $apDebug = 0;
my $tsDebug = 0;
my $treeDebug = 0;
my $ilcDebug = 0;
my $regexpDebug = 0;
my $parserStackDebug = 0 || $HeaderDoc::fileDebug;
my $hangDebug = 0;
my $offsetDebug = 0;
my $classDebug = 0; # prints changes to inClass, etc.
my $gccAttributeDebug = 0; # also for availability macro argument handling.
my $occMethodNameDebug = 0;
my $moduleDebug = 0; # prints changes to INMODULE
my $liteDebug = 0 || $HeaderDoc::fileDebug; # Just prints the tokens.
my $parserStateInsertDebug = 0;
$cppDebug = $cppDebugDefault || $HeaderDoc::fileDebug;
# State variables (part 1 of 3)
# my $typestring = "";
my $continue = 1; # set low when we're done.
my $parsedParamParse = 0; # set high when current token is part of param.
# my @parsedParamList = (); # currently active parsed parameter list.
# my @pplStack = (); # stack of parsed parameter lists. Used to handle
# fields and parameters in nested callbacks/structs.
# my @freezeStack = (); # copy of pplStack when frozen.
# my $frozensodname = "";
# my $stackFrozen = 0; # set to prevent fake parsed params with inline funcs
my $lang = $HeaderDoc::lang;
my $perl_or_shell = 0;
my $sublang = $HeaderDoc::sublang;
my $callback_typedef_and_name_on_one_line = 1; # deprecated
# my $returntype = "";
# my $freezereturn = 0; # set to prevent fake return types with inline funcs
my $treeNest = 0; # 1: nest future content under this node.
# 2: used if you want to nest, but have already
# inserted the contents of the node.
my $sethollow = 0;
my $setNoInsert = 0;
my $treepart = ""; # There are some cases where you want to drop a token
# for formatting, but keep it in the parse tree.
# In that case, treepart contains the original token,
# while part generally contains a space.
# my $availability = ""; # holds availability string if we find an av macro.
# my $seenTilde = 0; # set to 1 for C++ destructor.
if ($argparse && $tsDebug) { $tsDebug = 0; }
# Configure the parse tree output.
my $treeTop = HeaderDoc::ParseTree->new(); # top of parse tree.
my $treeCur = $treeTop; # current position in parse tree
my $treeSkip = 0; # set to 1 if "part" should be dropped in tree.
# my $treePopTwo = 0; # set to 1 for tokens that nest, but have no
# explicit ending token ([+-:]).
my $treePopOnNewLine = 0; # set to 1 for single-line comments, macros.
my @treeStack = (); # stack of parse trees. Used for popping
# our way up the tree to simplify tree structure.
# Leak a node here so that every real node has a parent.
$treeCur = $treeCur->addChild("");
$treeTop = $treeCur;
my $lastACS = "";
# The argparse switch is a trigger....
if ($argparse && $apDebug) {
$localDebug = 1;
$retDebug = 1;
$listDebug = 1;
$parseDebug = 1;
$sodDebug = 1;
$valueDebug = 1;
$parmDebug = 1;
$cbnDebug = 1;
$macroDebug = 1;
# $apDebug = 1;
$tsDebug = 1;
$treeDebug = 1;
$ilcDebug = 1;
$regexpDebug = 1;
}
my $spaceDebug = 0;
if ($localDebug || $apDebug || $liteDebug || $parseDebug) {
print STDERR "ENTERED BLOCKPARSE\n";
}
my $disable_cpp = 0;
if ($argparse && ($localDebug || $apDebug || $liteDebug)) {
print STDERR "ARGPARSE MODE!\n";
print STDERR "IPC: $inputCounter\nNLINES: ".$#inputLines."\n";
cluck("Call backtrace\n");
}
print STDERR "INBP\n" if ($localDebug);
if ($argparse) {
# Avoid double-processing macro inclusions.
$disable_cpp = 1;
}
if ($lang ne "C" || $sublang eq "PHP") { # || $sublang eq "IDL")
$disable_cpp = 1;
}
print STDERR "INITIAL LANG: $lang INITIAL SUBLANG: $sublang\n" if ($localDebug);
# warn("in BlockParse\n");
# State variables (part 2 of 3)
my $parserState = HeaderDoc::ParserState->new();
# $parserState->{hollow} = $treeTop;
setHollowWithLineNumbers(\$parserState, $treeTop, $fileoffset, $inputCounter);
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = 0; # included for consistency....
my @parserStack = ();
# print STDERR "TEST: ";
# if (defined($parserState->{parsedParamList})) {
# print STDERR "defined\n"
# } else { print STDERR "undefined.\n"; }
# print STDERR "\n";
# my $inComment = 0;
# my $inInlineComment = 0;
# my $inString = 0;
# my $inChar = 0;
# my $inTemplate = 0;
my @braceStack = ();
# my $inOperator = 0;
my $inPrivateParamTypes = 0; # after a colon in a C++ function declaration.
# my $onlyComments = 1; # set to 0 to avoid switching to macro parse.
# mode after we have seen a code token.
# my $inMacro = 0;
# my $inMacroLine = 0; # for handling macros in middle of data types.
# my $seenMacroPart = 0; # used to control dropping of macro body.
# my $macroNoTrunc = 1; # used to avoid truncating body of macros
# that don't begin with parenthesis or brace.
# my $inBrackets = 0; # square brackets ([]).
my $inPType = 0; # in pascal types.
my $inRegexp = 0; # in perl regexp.
my $regexpNoInterpolate = 0; # Don't interpolate (e.g. tr)
my $inRegexpTrailer = 0; # in the cruft at the end of a regexp.
my $hollowskip = 0;
my $ppSkipOneToken = 0; # Comments are always dropped from parsed
# parameter lists. However, inComment goes
# to 0 on the end-of-comment character.
# This prevents the end-of-comment character
# itself from being added....
my $regexppattern = ""; # optional characters at start of regexp
my $singleregexppattern = ""; # members of regexppattern that take only
# one argument instead of two.
my $regexpcharpattern = ""; # legal chars to start a regexp.
my @regexpStack = (); # stack of RE tokens (since some can nest).
# Get the parse tokens from Utilities.pm.
my ($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
$soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
$enumname,
$typedefname, $varname, $constname, $structisbrace, $macronameref,
$classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
$requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
my $macrore_pound = macroRegexpFromList($macronameref, 1);
my $macrore_nopound = macroRegexpFromList($macronameref, 2);
# print STDERR "LANG: $lang SUBLANG: $sublang";
print STDERR "MACRORE_POUND: \"$macrore_pound\"\n" if ($localDebug || $parseDebug);
print STDERR "MACRORE_NOPOUND: \"$macrore_nopound\"\n" if ($localDebug || $parseDebug);
# print STDERR "INITIAL PROPNAME $propname\n";
if ($parseDebug) {
print STDERR "SOT: $sotemplate EOF: $eotemplate OP: $operator SOC: $soc EOC: $eoc ILC: $ilc ILC_B: $ilc_b\n";
print STDERR "SOFUNC: $sofunction SOPROC: $soprocedure SOPREPROC: $sopreproc LBRACE: $lbrace RBRACE: $rbrace\n";
print STDERR "UNION: $unionname STRUCT: $structname TYPEDEF: $typedefname VAR: $varname CONST: $constname\n";
print STDERR "STRUCTISBRACE: $structisbrace MACRONAMEREF: $macronameref CLASSRE: $classregexp\n";
print STDERR "CLASSBRACERE: $classbraceregexp CLASSCLOSEBRACERE: $classclosebraceregexp ACCESSRE: $accessregexp\n";
print STDERR "MODULERE: $moduleregexp\n";
}
# Set up regexp patterns for perl, variable for perl or shell.
if ($lang eq "perl" || $lang eq "shell") {
$perl_or_shell = 1;
if ($lang eq "perl") {
$regexpcharpattern = '\\{|\\#\\(|\\/|\\\'|\\"|\\<|\\[|\\`';
# } vi bug workaround for previous line
$regexppattern = "qq|qr|qx|qw|q|m|s|tr|y";
$singleregexppattern = "qq|qr|qx|qw|q|m";
}
}
my $pascal = 0;
if ($lang eq "pascal") { $pascal = 1; }
# State variables (part 3 of 3)
# my $lastsymbol = ""; # Name of the last token, wiped by braces,
# parens, etc. This is not what you are
# looking for. It is used mostly for
# handling names of typedefs.
# my $name = ""; # Name of a basic data type.
# my $callbackNamePending = 0; # 1 if callback name could be here. This is
# only used for typedef'ed callbacks. All
# other callbacks get handled by the parameter
# parsing code. (If we get a second set of
# parsed parameters for a function, the first
# one becomes the callback name.)
# my $callbackName = ""; # Name of this callback.
# my $callbackIsTypedef = 0; # 1 if the callback is wrapped in a typedef---
# sets priority order of type matching (up
# one level in headerdoc2HTML.pl).
# my $namePending = 0; # 1 if name of func/variable is coming up.
# my $basetype = ""; # The main name for this data type.
# my $posstypes = ""; # List of type names for this data type.
# my $posstypesPending = 1; # If this token could be one of the
# type names of a typedef/struct/union/*
# declaration, this should be 1.
# my $sodtype = ""; # 'start of declaration' type.
# my $sodname = ""; # 'start of declaration' name.
# my $sodclass = ""; # 'start of declaration' "class". These
# bits allow us keep track of functions and
# callbacks, mostly, but not the name of a
# callback.
# my $simpleTypedef = 0; # High if it's a typedef w/o braces.
# my $simpleTDcontents = ""; # Guts of a one-line typedef. Don't ask.
# my $seenBraces = 0; # Goes high after initial brace for inline
# functions and macros -only-. We
# essentially stop parsing at this point.
# my $kr_c_function = 0; # Goes high if we see a K&R C declaration.
# my $kr_c_name = ""; # The name of a K&R function (which would
# otherwise get lost).
my $lastchar = ""; # Ends with the last token, but may be longer.
my $lastnspart = ""; # The last non-whitespace token.
my $lasttoken = ""; # The last token seen (though [\n\r] may be
# replaced by a space in some cases.
# my $startOfDec = 1; # Are we at the start of a declaration?
my $prespace = 0; # Used for indentation (deprecated).
my $prespaceadjust = 0; # Indentation is now handled by the parse
# tree (colorizer) code.
my $scratch = ""; # Scratch space.
my $curline = ""; # The current line. This is pushed onto
# the declaration at a newline and when we
# enter/leave certain constructs. This is
# deprecated in favor of the parse tree.
my $curstring = ""; # The string we're currently processing.
my $continuation = 0; # An obscure spacing workaround. Deprecated.
my $forcenobreak = 0; # An obscure spacing workaround. Deprecated.
# my $occmethod = 0; # 1 if we're in an ObjC method.
my $occspace = 0; # An obscure spacing workaround. Deprecated.
# my $occmethodname = ""; # The name of an objective C method (which
# gets augmented to be this:that:theother).
# my $preTemplateSymbol = ""; # The last symbol prior to the start of a
# C++ template. Used to determine whether
# the type returned should be a function or
# a function template.
# my $preEqualsSymbol = ""; # Used to get the name of a variable that
# is followed by an equals sign.
# my $valuepending = 0; # True if a value is pending, used to
# return the right value.
# my $value = ""; # The current value.
my $parsedParam = ""; # The current parameter being parsed.
my $postPossNL = 0; # Used to force certain newlines to be added
# to the parse tree (to end macros, etc.)
# my $categoryClass = "";
# my $classtype = "";
# my $inClass = 0;
my $pushParserStateAfterToken = 0;
my $pushParserStateAfterWordToken = 0;
my $pushParserStateAtBrace = 0;
my $occPushParserStateOnWordTokenAfterNext = 0;
$HeaderDoc::hidetokens = 0;
# Loop unti the end of file or until we've found a declaration,
# processing one line at a time.
my $nlines = $#inputLines;
my $incrementoffsetatnewline = 0;
print "INCOMING INPUTCOUNTER: $inputCounter\n" if ($HeaderDoc::inputCounterDebug);
while ($continue && ($inputCounter <= $nlines)) {
$HeaderDoc::CurLine = $inputCounter + $fileoffset;
my $line = $inputLines[$inputCounter++];
print STDERR "GOT LINE: $line\n" if (($localDebug && $apDebug) || $HeaderDoc::inputCounterDebug);
print STDERR "INCREMENTED INPUTCOUNTER [1]\n" if ($HeaderDoc::inputCounterDebug);
my @parts = ();
# $line =~ s/^\s*//go; # Don't strip leading spaces, please.
$line =~ s/\s*$//go;
# $scratch = nspaces($prespace);
# $line = "$scratch$line\n";
# $curline .= $scratch;
$line .= "\n";
if ($lang eq "C" && $sublang eq "IDL") {
if ($line =~ /cpp_quote\s*\(\s*\"(.*)\"\s*\)\s*$/) {
print "CHANGED LINE FROM \"$line\" to \"$1\"\n" if ($localDebug || $liteDebug);
$line = $1."\n";
}
}
print STDERR "LINE[$inputCounter] : $line\n" if ($offsetDebug);
# The tokenizer
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\^|\W)/, $line);
}
# See note about similar block below. This block is for fixing the
# "missing newline" problem, which otherwise would cause line numbers
# to sometimes be wrong.
push(@parts, "BOGUSBOGUSBOGUSBOGUSBOGUS");
my $xpart = "";
foreach my $nextxpart (@parts) {
if (!length($nextxpart)) { next; }
if (!length($xpart)) { $xpart = $nextxpart; next; }
if ($xpart eq "\n" && $nextxpart ne "BOGUSBOGUSBOGUSBOGUSBOGUS") {
print STDERR "FOUND EXTRA NEWLINE\n" if ($offsetDebug);
# $fileoffset++;
$incrementoffsetatnewline++;
}
$xpart = $nextxpart;
}
pop(@parts);
$parserState->{inInlineComment} = 0;
print STDERR "inInlineComment -> 0\n" if ($ilcDebug);
# warn("line $inputCounter\n");
if ($localDebug || $cppDebug || $spaceDebug) {foreach my $partlist (@parts) {print STDERR "PARTLIST: \"$partlist\"\n"; }}
# We have to do the C preprocessing work up front because token substitution
# must occur prior to actual parsing in order to do any good. This block does
# the work.
my $cpp_in_argparse = 0;
if (!$disable_cpp && (1 || $HeaderDoc::enable_cpp)) {
my $newrawline = "";
my $incppargs = 0;
my $cppstring = "";
my $cppname = "";
my $lastcpppart = "";
my @cppargs = ();
my $inChar = 0; my $inString = 0; my $inComment = $parserState->{inComment}; my $inSLC = $parserState->{inInlineComment};
my $inParen = 0;
my $inMacro = $parserState->{inMacro};
my $inCPPSpecial = $parserState->{inMacro} || $parserState->{inMacroLine};
my $inMacroTail = 0;
if ($parserState->{sodname} && ($parserState->{sodname} ne "")) {
$inMacroTail = 1;
}
print STDERR "INMACROTAIL: $inMacroTail\n" if ($cppDebug);
my @cpptrees;
my $cpptreecur = HeaderDoc::ParseTree->new();
my $cpptreetop = $cpptreecur;
# print STDERR "CHECK LINE $line\n";
if ($line =~ /^\s*#include (.*)$/) {
my $rest = $1;
$rest =~ s/^\s*//s;
$rest =~ s/\s*$//s;
if ($rest !~ s/^\<(.*)\>$/$1/s) {
$rest =~ s/^\"(.*)\"$/$1/s;
}
my $filename = basename($rest);
if ($HeaderDoc::HeaderFileCPPHashHash{$filename}) {
my $includehash = HeaderDoc::IncludeHash->new();
$includehash->{FILENAME} = $filename;
$includehash->{LINENUM} = $inputCounter + $fileoffset;
$includehash->{HASHREF} = $HeaderDoc::HeaderFileCPPHashHash{$filename};
push(@HeaderDoc::cppHashList, $includehash);
# print STDERR "PUSH HASH\n";
push(@HeaderDoc::cppArgHashList, $HeaderDoc::HeaderFileCPPArgHashHash{$filename});
}
} elsif ($line =~ /^\s*$definename\s+/) {
# print STDERR "inMacro -> 1\n";
# print STDERR "inMacro -> 1\n" if ($macroDebug || $cppDebug);
# This is a throwaway line.
$inMacro = 1;
}
if ($macrore_pound ne "" && $line =~ /^\s*\#\s*$macrore_pound\s+/) {
print STDERR "CPPSPECIAL -> 1\n" if ($macroDebug || $cppDebug);
$inCPPSpecial = 1;
}
my $cppleaddebug = 0;
do {
my $pos = 0;
my $dropargs = 0;
while ($pos < scalar(@parts)) {
my $part = $parts[$pos];
my $noCPPThisToken = 0;
if (length($part)) {
if (!$inChar && !$inString && !$inComment && !$inSLC) {
if ($parserState->{NEXTTOKENNOCPP} == 1) {
# We're in an "if" block.
if ($part eq "defined") {
$parserState->{NEXTTOKENNOCPP} = 3;
}
} elsif ($parserState->{NEXTTOKENNOCPP} == 2) {
# We're in an "ifdef"/"ifndef" block, so first word token
# ends this mode completely.
if ($part !~ /(\s|\()/) {
$parserState->{NEXTTOKENNOCPP} = 0;
$noCPPThisToken = 1;
}
} elsif ($parserState->{NEXTTOKENNOCPP} == 3) {
# We're in an "if" block, so first word token
# drops us back to default "if" block state.
if ($part !~ /(\s|\()/) {
$parserState->{NEXTTOKENNOCPP} = 1;
$noCPPThisToken = 1;
}
}
if ($inCPPSpecial && $part =~ /(ifdef|ifndef)/) {
$parserState->{NEXTTOKENNOCPP} = 2;
} elsif ($inCPPSpecial && $part =~ /if/) {
$parserState->{NEXTTOKENNOCPP} = 1;
}
}
print STDERR "TOKEN: $part NEXTTOKENNOCPP: ".$parserState->{NEXTTOKENNOCPP}." INMACRO: $inMacro INCPPSPECIAL: $inCPPSpecial\n" if ($cppleaddebug || $macroDebug || $cppDebug);
print STDERR "CPPLEADPART: $part\n"if ($cppleaddebug);
if (!$inString && !$inChar) {
if ($inComment && $part eq $eoc) {
print STDERR "EOC\n"if ($cppleaddebug);
$inComment = 0;
} elsif ($inSLC && $part =~ /[\r\n]/) {
# Handle newline in single-line comments.
print STDERR "EOSLC\n"if ($cppleaddebug);
$inSLC = 0;
} elsif (!$inSLC && $part eq $soc) {
print STDERR "SOC\n"if ($cppleaddebug);
$inComment = 1;
} elsif (!$inComment && ($part eq $ilc || $part eq $ilc_b)) {
print STDERR "INSLC\n"if ($cppleaddebug);
$inSLC = 1;
}
}
my $skip = 0;
if (!$incppargs) {
my $newpart = $part;
my $hasargs = 0;
if (!$inComment && !$inSLC && !$noCPPThisToken) {
($newpart, $hasargs) = cpp_preprocess($part, $HeaderDoc::CurLine);
# Don't drop tokens in macros.
if ($hasargs == 2 && $inMacro) {
$newpart = $part;
$hasargs = 0;
}
# Don't change the macro name. (If a
# macro gets redefined, ignore it.)
if ($inMacro && !$inMacroTail) {
$newpart = $part;
$hasargs = 0;
}
}
if ($hasargs) {
$incppargs = 1;
$cppname = $part;
if ($hasargs == 2) {
$dropargs = 1;
print STDERR "Dropping arguments for ignored macro \"$part\"\n" if ($cppDebug);
}
} else {
my $newpartnl = $newpart;
my $newpartnlcount = ($newpartnl =~ tr/\n//);
my $partnl = $part;
my $partnlcount = ($partnl =~ tr/\n//);
my $nlchange = ($newpartnlcount - $partnlcount);
print STDERR "NLCHANGE: $nlchange (FILEOFFSET = $fileoffset)\n" if ($offsetDebug);
$fileoffset -= $nlchange;
if ($inMacro) {
if ($newpart ne $part) {
print STDERR "CHANGING NEWPART FROM \"$newpart\" TO " if ($cppDebug);
$newpart =~ s/^\s*/ /s;
$newpart =~ s/\s*$//s;
$newpart =~ s/(.)\n/$1 \\\n/sg;
$newpart =~ s/\\$/ /s;
print STDERR "$newpart\n" if ($cppDebug);
}
}
$newrawline .= $newpart;
}
} elsif ($incppargs == 1) {
if ($part eq "(") {
# Don't do anything until leading parenthesis.
$incppargs = 3;
$inParen++;
}
} elsif ($incppargs == 3) {
if ($part eq '\\') {
if (!$inMacro && ($lastcpppart eq '\\')) { $lastcpppart = ""; } # @@@ CHECKME. inMacro test may not be needed.
# else {
# $lastcpppart = $part;
# if ($inMacro) {
# print STDERR "IMTEST\n" if ($cppDebug > 1);
# my $npos = $pos + 1;
# while ($npos < scalar(@parts)) {
# my $npart = $parts[$npos];
# if (length($npart)) {
# print STDERR "NEXTPART: \"".$parts[$npos]."\"\n" if ($cppDebug > 1);
# if ($npart =~ /\s/) {
# if ($npart =~ /[\n\r]/) {
# print STDERR "SKIP1\n" if ($cppDebug > 1);
# $skip = 1; last;
# } else {
# print STDERR "SPC\n" if ($cppDebug > 1);
# }
# } else {
# print STDERR "LAST\n" if ($cppDebug > 1);
# last;
# }
# }
# $npos++;
# }
# }
# }
} elsif ($part eq '"') {
if ($lastcpppart ne '\\') {
if (!$inChar && !$inComment && !$inSLC) {
$inString = !$inString;
}
}
$lastcpppart = $part;
} elsif ($part eq "'") {
if ($lastcpppart ne '\\') {
if (!$inString && !$inComment && !$inSLC) {
$inChar = !$inChar;
}
}
$lastcpppart = $part;
} elsif (!$inChar && !$inString && !$inComment && !$inSLC) {
if ($part eq "(") {
# Put in the token first, then nest.
$cpptreecur = $cpptreecur->next(HeaderDoc::ParseTree->new());
$cpptreecur->token($part);
$skip = 1;
$inParen++;
push(@cpptrees, $cpptreecur);
$cpptreecur = $cpptreecur->firstchild(HeaderDoc::ParseTree->new());
} elsif ($part eq ")") {
$inParen--;
# Go out one nesting level, then
# insert the token.
if (scalar(@cpptrees)) {
$cpptreecur = pop(@cpptrees);
while ($cpptreecur && $cpptreecur->next()) {
$cpptreecur = $cpptreecur->next();
}
}
if (!$inParen) {
push(@cppargs, $cpptreetop);
$cppstring = "";
$cpptreetop = HeaderDoc::ParseTree->new();
$cpptreecur = $cpptreetop;
$skip = 1;
$incppargs = 0;
if (!$dropargs) {
print STDERR "CALLING ARGPARSE FROM blockParse() [1].\n" if ($cppDebug);
my $addon = cpp_argparse($cppname, $HeaderDoc::CurLine, \@cppargs);
if ($inMacro) {
print STDERR "CHANGING ADDON FROM \"$addon\" TO " if ($cppDebug);
$addon =~ s/^\s*/ /s;
$addon =~ s/\s*$//s;
$addon =~ s/(.)\n/$1 \\\n/sg;
$addon =~ s/\\$/ /s;
print STDERR "$addon\n" if ($cppDebug);
}
$newrawline .= $addon;
}
$dropargs = 0;
}
} elsif (($inParen == 1) && (!$inChar && !$inString && !$inComment && !$inSLC) && ($part eq ",")) {
push(@cppargs, $cpptreetop);
$cpptreetop = HeaderDoc::ParseTree->new();
$cpptreecur = $cpptreetop;
$cppstring = "";
$skip = 1;
} elsif (($part =~ /\s/) && (!$inParen)) {
$incppargs = 0;
if (!$dropargs) {
print STDERR "CALLING ARGPARSE FROM blockParse() [2].\n" if ($cppDebug);
my $addon = cpp_argparse($cppname, $HeaderDoc::CurLine, \@cppargs);
if ($inMacro) {
print STDERR "CHANGING ADDON FROM \"$addon\" TO " if ($cppDebug);
$addon =~ s/^\s*/ /s;
$addon =~ s/\s*$//s;
$addon =~ s/(.)\n/$1 \\\n/sg;
$addon =~ s/\\$/ /s;
print STDERR "$addon\n" if ($cppDebug);
}
$newrawline .= $addon;
}
$dropargs = 0;
}
$lastcpppart = $part;
}
if ($skip) { $skip = 0; }
else {
my $xpart = $part;
# Strip newline in CPP argument list.
if ($part =~ /[\r\n]/) { $xpart = " "; }
$cpptreecur = $cpptreecur->next(HeaderDoc::ParseTree->new());
$cpptreecur->token($xpart);
}
$cppstring .= $part;
}
if ($inMacro && $part ne "define" &&
$part =~ /\w/ && !$inParen) {
$inMacroTail = 1;
}
}
$pos++;
}
if ($incppargs) {
# print STDERR "YO\n";
if ($parserState->{inMacro} || $inMacro) {
# print STDERR "YOYO\n";
if ($cppstring !~ s/\\\s*$//s) {
print STDERR "CPPS: \"$cppstring\"\n";
warn "Non-terminated macro.\n";
$incppargs = 0;
}
}
}
if ($incppargs || $inComment) {
print STDERR "Fetching new line ($incppargs, $inComment)\n" if ($cppleaddebug);
$HeaderDoc::CurLine = $inputCounter + $fileoffset;
$line = $inputLines[$inputCounter++];
if ($lang eq "C" && $sublang eq "IDL") {
if ($line =~ /cpp_quote\s*\(\s*\"(.*)\"\s*\)\s*$/) {
print "CHANGED LINE FROM \"$line\" to \"$1\"\n" if ($localDebug || $liteDebug);
$line = $1."\n";
}
}
print STDERR "INCREMENTED INPUTCOUNTER [2]\n" if ($HeaderDoc::inputCounterDebug);
# @parts = split(/(\W)/, $line);
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
}
}
} until (!$incppargs && !$inComment);
# The tokenizer
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $newrawline);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\W)/, $newrawline);
}
while (scalar(@cpptrees)) {
my $temptree = pop(@cpptrees);
if ($temptree != $cpptreetop) {
$temptree->dispose();
}
}
$cpptreetop->dispose();
}
if (!$parserState->{inMacro}) {
$parserState->{NEXTTOKENNOCPP} = 0;
}
# Throw away any empty entries caused by Perl seeing two
# adjacent tokens that match the split regexp. We don't
# want them or care about them, and they break things
# rather badly if we don't....
my @stripparts = @parts;
@parts = ();
print STDERR "BEGIN PARTLIST 2:\n" if ($spaceDebug);
foreach my $strippart (@stripparts) {
if (length($strippart)) {
print STDERR "MYPART: \"$strippart\"\n" if ($spaceDebug);
push(@parts, $strippart);
}
}
print STDERR "END PARTLIST 2.\n" if ($spaceDebug);
# This bit of code needs a bit of explanation, I think.
# We need to be able to see the token that follows the one we
# are currently processing. To do this, we actually keep track
# of the current token, and the previous token, but name then
# $nextpart and $part. We do processing on $part, which gets
# assigned the value from $nextpart at the end of the loop.
#
# To avoid losing the last part of the declaration (or needing
# to unroll an extra copy of the entire loop code) we push a
# bogus entry onto the end of the stack, which never gets
# used (other than as a bogus "next part") because we only
# process the value in $part.
#
# To avoid problems, make sure that you don't ever have a regexp
# that would match against this bogus token.
#
my $part = "";
push(@parts, "BOGUSBOGUSBOGUSBOGUSBOGUS");
if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POSTCPPPARTLIST: \"$partlist\"\n"; }}
foreach my $nextpart (@parts) {
my $hideTokenAndMaybeContents = 0;
$treeSkip = 0;
# $treePopTwo = 0;
# $treePopOnNewLine = 0;
# The current token is now in "part", and the literal next
# token in "nextpart". We can't just work with this as-is,
# though, because you can have multiple spaces, null
# tokens when two of the tokens in the split list occur
# consecutively, etc.
print STDERR "MYPART: \"$part\"\n" if ($localDebug || $spaceDebug);
$forcenobreak = 0;
if ($nextpart eq "\r") { $nextpart = "\n"; }
if ($localDebug && $nextpart eq "\n") { print STDERR "NEXTPART IS NEWLINE!\n"; }
if ($localDebug && $part eq "\n") { print STDERR "PART IS NEWLINE!\n"; }
### if ($nextpart ne "\n" && $nextpart =~ /\s/o) {
### # Replace tabs with spaces.
### $nextpart = " ";
### }
# Replace tabs with spaces.
$part =~ s/\t/ /g;
$nextpart =~ s/\t/ /g;
if ($part ne "\n" && $part =~ /\s/o && $nextpart ne "\n" &&
$nextpart =~ /\s/o) {
# we're a space followed by a space. Join the tokens.
print STDERR "MERGED \"$part\" and \"$nextpart\" into " if ($spaceDebug);
$nextpart = $part.$nextpart;
print STDERR "\"$nextpart\".\n" if ($spaceDebug);
$part = $nextpart;
next;
}
print STDERR "PART IS \"$part\"\n" if ($localDebug || $parserStackDebug || $parseDebug || $liteDebug || $spaceDebug);
print STDERR "CURLINE IS \"$curline\"\n" if ($localDebug || $hangDebug);
print STDERR "INOP: ".$parserState->{inOperator}."\n" if ($operatorDebug);
if (!length($nextpart)) {
print STDERR "SKIP NP\n" if ($localDebug);
next;
}
if (!length($part)) {
print STDERR "SKIP PART\n" if ($localDebug);
$part = $nextpart;
next;
}
if ($occPushParserStateOnWordTokenAfterNext > 1) {
if ($part =~ /\w/) {
$occPushParserStateOnWordTokenAfterNext--;
print STDERR "occPushParserStateOnWordTokenAfterNext -> $occPushParserStateOnWordTokenAfterNext (--)\n" if ($localDebug || $parseDebug);
}
} elsif ($occPushParserStateOnWordTokenAfterNext) {
# if ($part !~ /(\s|<)/)
if ($part =~ /(\/\/|\/\*|\-|\+|\w|\@)/) {
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[occPushParserStateOnWordTokenAfterNext]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 0;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
}
}
# If we get here, we aren't skipping a null or whitespace token.
# Let's print a bunch of noise if debugging is enabled.
# if ($part eq "\n" && $nextpart ne "BOGUSBOGUSBOGUSBOGUSBOGUS") {
# $fileoffset++;
# }
if ($part eq "\n" && $incrementoffsetatnewline) {
$incrementoffsetatnewline--;
$fileoffset++;
}
print STDERR "IN LOOP LANG: $lang INITIAL SUBLANG: $sublang\n" if ($localDebug || $parseDebug);
if ($parseDebug) {
print STDERR "PART: $part, type: $parserState->{typestring}, inComment: $parserState->{inComment}, inInlineComment: $parserState->{inInlineComment}, inChar: $parserState->{inChar}.\n" if ($localDebug);
print STDERR "PART: inBrackets: $parserState->{inBrackets}\n" if ($localDebug);
print STDERR "PART: onlyComments: $parserState->{onlyComments}, inClass: $parserState->{inClass}\n";
print STDERR "PART: cbsodname: $parserState->{cbsodname}\n";
print STDERR "PART: classIsObjC: $parserState->{classIsObjC}, PPSAT: $pushParserStateAfterToken, PPSAWordT: $pushParserStateAfterWordToken, PPSABrace: $pushParserStateAtBrace, occPPSOnWordTokenAfterNext: $occPushParserStateOnWordTokenAfterNext\n";
print STDERR "PART: bracecount: " . scalar(@braceStack) . " (init was $parserState->{initbsCount}).\n";
print STDERR "PART: inString: $parserState->{inString}, callbackNamePending: $parserState->{callbackNamePending}, namePending: $parserState->{namePending}, lastsymbol: $parserState->{lastsymbol}, lasttoken: $lasttoken, lastchar: $lastchar, SOL: $parserState->{startOfDec}\n" if ($localDebug);
print STDERR "PART: sodclass: $parserState->{sodclass} sodname: $parserState->{sodname}\n";
print STDERR "PART: sodtype: $parserState->{sodtype}\n";
print STDERR "PART: simpleTypedef: $parserState->{simpleTypedef}\n";
print STDERR "PART: posstypes: $parserState->{posstypes}\n";
print STDERR "PART: seenBraces: $parserState->{seenBraces} inRegexp: $inRegexp\n";
print STDERR "PART: regexpNoInterpolate: $regexpNoInterpolate\n";
print STDERR "PART: seenTilde: $parserState->{seenTilde}\n";
print STDERR "PART: CBN: $parserState->{callbackName}\n";
print STDERR "PART: regexpStack is:";
foreach my $token (@regexpStack) { print STDERR " $token"; }
print STDERR "\n";
print STDERR "PART: npplStack: ".scalar(@{$parserState->{pplStack}})." nparsedParamList: ".scalar(@{$parserState->{parsedParamList}})." nfreezeStack: ".scalar(@{$parserState->{freezeStack}})." frozen: $parserState->{stackFrozen}\n";
print STDERR "PART: inMacro: $parserState->{inMacro} treePopOnNewLine: $treePopOnNewLine\n";
print STDERR "PART: occmethod: $parserState->{occmethod} occmethodname: $parserState->{occmethodname}\n";
print STDERR "PART: returntype is $parserState->{returntype}\n";
print STDERR "length(declaration) = " . length($declaration) ."; length(curline) = " . length($curline) . "\n";
print STDERR "REQUIREDREGEXP IS \"$requiredregexp\"\n";
print STDERR "DEC: $declaration\n$curline\n";
} elsif ($tsDebug || $treeDebug) {
print STDERR "BPPART: $part\n";
}
if ($parserStackDebug) {
print STDERR "parserState: STACK CONTAINS ".scalar(@parserStack)." STATES\n";
print STDERR "parserState is $parserState\n";
}
# The ignore function returns either null, an empty string,
# or a string that gives the text equivalent of an availability
# macro. If the token is non-null and the length is non-zero,
# it's an availability macro, so blow it in as if the comment
# contained an @availability tag.
#
my $tempavail = ignore($part, $ignoreref, $perheaderignoreref);
printf("PART: $part TEMPAVAIL: $tempavail\n") if ($localDebug || $gccAttributeDebug);
if ($tempavail && ($tempavail ne "1") && ($tempavail ne "2")) {
$parserState->{availability} = $tempavail;
} elsif ($tempavail eq "2") {
# Reusing the GCC attribute handling code because that does exactly what we need.
print STDERR "Function-like availability macro detected. Collecting.\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = 1;
$parserState->{attributeParts} = ();
# Add __attribute__ as the next token.
$treeCur = $treeCur->addSibling($part, 0);
push(@treeStack, $treeCur);
my @tempAvailabilityNodesArray = ();
if ($parserState->{availabilityNodesArray}) {
@tempAvailabilityNodesArray = @{$parserState->{availabilityNodesArray}};
}
push(@tempAvailabilityNodesArray, $treeCur);
# print STDERR "ADDED $treeCur\n";
# $treeCur->dbprint();
$parserState->{availabilityNodesArray} = \@tempAvailabilityNodesArray;
# Nest all contents one level lower.
$treeCur = $treeCur->addChild("", 0);
$part = $nextpart;
next;
}
# Handle the GCC "__attribute__" extension outside the context of
# the parser because it isn't part of the language and massively
# breaks the syntax.
if ($lang eq "C" && isKeyword($part, $keywordhashref, $case_sensitive) == 2) {
print STDERR "GCC attribute detected. Collecting.\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = 1;
$parserState->{attributeParts} = ();
# Add __attribute__ as the next token.
$treeCur = $treeCur->addSibling($part, 0);
push(@treeStack, $treeCur);
# Nest all contents one level lower.
$treeCur = $treeCur->addChild("", 0);
$part = $nextpart;
next;
} elsif ($parserState->{attributeState} == 1) {
if ($part eq "(") {
print STDERR "GCC attribute open paren\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = -1;
}
$treeCur = $treeCur->addSibling($part, 0);
$part = $nextpart;
next;
} elsif ($parserState->{attributeState} < 0) {
if ($part eq "(") {
$parserState->{attributeState}--;
print STDERR "GCC attribute open paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug);
} elsif ($part eq ")") {
$parserState->{attributeState}++;
print STDERR "GCC attribute close paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug);
}
$treeCur = $treeCur->addSibling($part, 0);
if (($localDebug || $gccAttributeDebug) && !$parserState->{attributeState}) {
print STDERR "GCC attribute: done collecting.\n";
# Get back to where we started.
$treeCur = pop(@treeStack);
}
$part = $nextpart;
next;
}
# Here be the parser. Abandon all hope, ye who enter here.
$treepart = "";
if ($parserState->{inProtocol} == 1) {
print STDERR "INPROTOCOL: 1\n" if ($parseDebug || $classDebug);
if ($part =~ /\w/) {
print STDERR "INPROTOCOL: 1 -> 2\n" if ($parseDebug || $classDebug);
$parserState->{inProtocol} = 2;
}
} elsif ($parserState->{inProtocol} == 2) {
print STDERR "INPROTOCOL: 2\n" if ($parseDebug || $classDebug);
if ($part eq "<") {
print STDERR "INPROTOCOL: 2 -> 3\n" if ($parseDebug || $classDebug);
$parserState->{extendsProtocol} = "";
$parserState->{inProtocol} = 3;
} elsif ($part =~ /\S/) {
# PUSH PARSER STATE
print STDERR "parserState pushed onto stack[PROTOCOL]\n" if ($parserStackDebug);
$parserState->{inProtocol} = -1;
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterWordToken = 0;
}
} elsif ($parserState->{inProtocol} == 3) {
print STDERR "INPROTOCOL: 3\n" if ($parseDebug || $classDebug);
if ($part eq ">") {
print STDERR "INPROTOCOL: 3 -> 2\n" if ($parseDebug || $classDebug);
$parserState->{inProtocol} = 2;
} else {
$parserState->{extendsProtocol} .= $part;
}
}
if ($parserState->{inClass} == 3) {
print STDERR "INCLASS3\n" if ($parseDebug || $classDebug);
if ($part eq ")") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [1]\n" if ($classDebug);
$parserState->{categoryClass} .= $part;
print STDERR "parserState will be pushed onto stack[cparen3]\n" if ($parserStackDebug);
# $parserState->{lastTreeNode} = $treeCur;
# push(@parserStack, $parserState);
# $parserState = HeaderDoc::ParserState->new();
# $parserState->{lang} = $lang;
# $parserState->{inputCounter} = $inputCounter;
# $parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterToken = 1;
} elsif ($part eq ":") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [2]\n" if ($classDebug);
if ($parserState->{classIsObjC}) {
print STDERR "occPushParserStateOnWordTokenAfterNext -> 2\n" if ($localDebug || $parseDebug);
$occPushParserStateOnWordTokenAfterNext = 2;
} else {
$pushParserStateAfterWordToken = 1;
}
# if ($sublang eq "occ") {
# $pushParserStateAtBrace = 2;
# }
} elsif ($part =~ /</ && $parserState->{classIsObjC}) {
print STDERR "pushParserStateAfterWordToken -> 0 (Conforming)\n" if ($localDebug || $parseDebug);
print STDERR "inClassConformingToProtocol -> 1\n" if ($localDebug || $parseDebug);
$pushParserStateAfterWordToken = 0;
$parserState->{inClassConformingToProtocol} = 1;
$occPushParserStateOnWordTokenAfterNext = 0;
} elsif ($part =~ />/ && $parserState->{classIsObjC} && $parserState->{inClassConformingToProtocol}) {
print STDERR "inClassConformingToProtocol -> 0\n" if ($localDebug || $parseDebug);
$pushParserStateAfterToken = 1;
print STDERR "pushParserStateAfterWordToken -> 1 (Conforming)\n" if ($localDebug || $parseDebug);
$parserState->{inClassConformingToProtocol} = 0;
} else {
$parserState->{categoryClass} .= $part;
}
} elsif ($parserState->{inClass} == 2) {
print STDERR "INCLASS2\n" if ($parseDebug || $classDebug);
if ($part eq ")") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [3]\n" if ($classDebug);
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[cparen2]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
} elsif ($part eq ":") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [4]\n" if ($classDebug);
if ($parserState->{classIsObjC}) {
print STDERR "occPushParserStateOnWordTokenAfterNext -> 2\n" if ($localDebug || $parseDebug);
$occPushParserStateOnWordTokenAfterNext = 2;
} else {
$pushParserStateAfterWordToken = 2;
}
} elsif ($part =~ /\w/) {
# skip the class name itself.
$parserState->{inClass} = 3;
print STDERR "inClass -> 3 [5]\n" if ($classDebug);
}
} elsif ($parserState->{inClass} == 1) {
print STDERR "INCLASS1\n" if ($parseDebug || $classDebug);
# print STDERR "inclass Part is $part\n";
if ($part eq ":") {
print STDERR "INCLASS COLON\n" if ($parseDebug || $classDebug);
$parserState->{forceClassName} = $parserState->{sodname};
$parserState->{forceClassSuper} = "";
# print STDERR "XSUPER: $parserState->{forceClassSuper}\n";
} elsif ($part eq "{" || $part eq ";") {
print STDERR "INCLASS BRCSEMI\n" if ($parseDebug || $classDebug);
$parserState->{forceClassDone} = 1;
if ($parserState->{classIsObjC} && $part eq "{") {
$parserState->{ISFORWARDDECLARATION} = 0;
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[OCC-BRCSEMI]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 0;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack) + 1; # NOTE: add one here because it will change in the SWITCH to follow.
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
$pushParserStateAfterToken = 1;
} elsif ($part eq ";") {
if (!defined($parserState->{ISFORWARDDECLARATION})) {
print STDERR "FORWARD DECLARATION DETECTED\n" if ($parseDebug || $localDebug || $liteDebug);
# print STDERR "PREVIOUS FD STATE: ".$parserState->{ISFORWARDDECLARATION}."\n";
$parserState->{ISFORWARDDECLARATION} = 1;
}
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
$pushParserStateAfterToken = 0;
}
} elsif ($parserState->{forceClassName} && !$parserState->{forceClassDone}) {
print STDERR "INCLASS ADD\n" if ($parseDebug || $classDebug);
if ($part =~ /[\n\r]/) {
$parserState->{forceClassSuper} .= " ";
} else {
$parserState->{forceClassSuper} .= $part;
}
# print STDERR "SUPER IS $parserState->{forceClassSuper}\n";
} elsif ($part =~ /</ && $parserState->{classIsObjC} && $occPushParserStateOnWordTokenAfterNext) {
print STDERR "INCLASS <\n" if ($parseDebug || $classDebug);
print STDERR "pushParserStateAfterWordToken -> 0 (Conforming)\n" if ($localDebug || $parseDebug);
print STDERR "inClassConformingToProtocol -> 1\n" if ($localDebug || $parseDebug);
$pushParserStateAfterWordToken = 0;
$parserState->{inClassConformingToProtocol} = 1;
$occPushParserStateOnWordTokenAfterNext = 0;
} elsif ($part =~ />/ && $parserState->{classIsObjC} && $parserState->{inClassConformingToProtocol}) {
print STDERR "INCLASS >\n" if ($parseDebug || $classDebug);
print STDERR "inClassConformingToProtocol -> 0\n" if ($localDebug || $parseDebug);
$pushParserStateAfterToken = 1;
print STDERR "pushParserStateAfterWordToken -> 1 (Conforming)\n" if ($localDebug || $parseDebug);
$parserState->{inClassConformingToProtocol} = 0;
} elsif ($occPushParserStateOnWordTokenAfterNext && $part =~ /\w/) {
print STDERR "INCLASS OCCSUPER\n" if ($parseDebug || $classDebug);
$parserState->{occSuper} = $part;
# $occPushParserStateOnWordTokenAfterNext = 0;
# $pushParserStateAfterToken = 1;
} elsif (!$parserState->{classIsObjC}) {
print STDERR "INCLASS NOTOBJC (OTHER)\n" if ($parseDebug || $classDebug);
if ($part =~ /[*(^]/) {
print STDERR "INCLASS DROP\n" if ($parseDebug || $classDebug);
$parserState->{inClass} = 0; # We're an instance. Either a variable or a function.
print STDERR "inClass -> 0 [6]\n" if ($classDebug);
$parserState->{sodtype} = $parserState->{preclasssodtype} . $parserState->{sodtype};
}
# } else {
# print STDERR "BUG\n";
}
};
if ($parserState->{inClassConformingToProtocol} == 1) {
$parserState->{inClassConformingToProtocol} = 2;
} elsif ($parserState->{inClassConformingToProtocol}) {
$parserState->{conformsToList} .= $part;
}
if ($macroDebug) {
print STDERR "MNT: ".$parserState->{macroNoTrunc}."\n";
}
# if (($part eq $ilc || $part eq $ilc_b) && ($lang ne "perl" || $lasttoken ne "\$")) {
# print STDERR "should be ILC?\n";
# } else {
# print STDERR "NO CHANEC: PART \"$part\" ILC \"$ilc\" ILC_B: \"ilc_b\" LANG: \"$lang\" LASTTOKEN: \"$lasttoken\"\n";
# }
SWITCH: {
# Blank declaration handlers (mostly for misuse of
# OSMetaClassDeclareReservedUsed and similar)
(($part eq ";") && ($parserState->{startOfDec} == 1) && !$parserState->{inMacro} && !$parserState->{inMacroLine} && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "LEADING SEMICOLON: CASE 01\n" if ($liteDebug);
print STDERR "Dropping empty declaration\n" if ($localDebug || $parseDebug);
$part = "";
last SWITCH;
};
# Macro handlers
(($parserState->{inMacro} == 1) && ($part eq "define")) && do {
print STDERR "INMACRO/DEFINE: CASE 02\n" if ($liteDebug);
# define may be a multi-line macro
print STDERR "INMACRO AND DEFINE\n" if ($parseDebug || $localDebug);
$parserState->{inMacro} = 3;
print STDERR "inMacro -> 3\n" if ($macroDebug || $cppDebug);
$parserState->{sodname} = "";
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [1]\n"; }
$treePopOnNewLine = 2;
$pound .= $part;
$treeCur->token($pound);
}
last SWITCH;
};
# (($parserState->{inMacro} == 1 && $macrore_pound ne "" && $part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)/ && ($part ne $definename)) || ($parserState->{inMacro} == 0 && $macrore_nopound ne "" && $part =~ /$macrore_nopound/))
# (($parserState->{inMacro} == 1 && $part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)/ )) && do
(!$parserState->{inComment} && (($parserState->{inMacro} == 1 && $macrore_pound ne "" && $part =~ /^$macrore_pound$/ && ($part ne $definename)) || ($parserState->{inMacro} == 0 && $macrore_nopound ne "" && $part =~ /^$macrore_nopound$/))) && do {
print STDERR "MACRORE-v: \"$macrore_pound\"\n" if ($macroDebug);
print STDERR "MACRORE-r: \"(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)\"\n" if ($macroDebug);
print STDERR "MACRORE-n: \"$macrore_nopound\"\n" if ($macroDebug);
print STDERR "INMACRO/IF: CASE 03\n" if ($liteDebug);
print STDERR "INMACRO AND IF/IFDEF/IFNDEF/ENDIF/ELSE/PRAGMA/IMPORT/INCLUDE\n" if ($parseDebug || $localDebug);
# these are all single-line macros
$parserState->{inMacro} = 4;
print STDERR "inMacro -> 4\n" if ($macroDebug || $cppDebug);
$parserState->{sodname} = "";
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [2]\n"; }
$treePopOnNewLine = 1;
$pound .= $part;
$treeCur->token($pound);
if ($part eq "endif") {
# the rest of the line is not part of the macro
# NOTE: Do not change treeCur in the
# next line.
$treeCur->addChild("\n", 0);
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [3]\n"; }
$treePopOnNewLine = 0;
$treeSkip = 1;
}
}
last SWITCH;
};
(($parserState->{inMacroLine} == 1) && ($part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include|define)/o)) && do {
print STDERR "INMACROLINE/IF: CASE 04\n" if ($liteDebug);
print STDERR "INMACROLINE AND IF/IFDEF/IFNDEF/ENDIF/ELSE/PRAGMA/IMPORT/INCLUDE\n" if ($parseDebug || $localDebug);
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$pound .= $part;
$treeCur->token($pound);
if ($part =~ /define/o) {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [4]\n"; }
$treePopOnNewLine = 2;
} elsif ($part eq "endif") {
# the rest of the line is not part of the macro
# NOTE: Do not change treeCur in the
# next line.
$treeCur->addChild("\n", 0);
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [5]\n"; }
$treePopOnNewLine = 0;
$treeSkip = 1;
} else {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [6]\n"; }
$treePopOnNewLine = 1;
}
}
last SWITCH;
};
($parserState->{inMacro} == 1 && ($part ne $soc) && ($part ne $eoc) && $part =~ /\s/) && do {
$treepart = $part; $part = "";
last SWITCH;
};
($parserState->{inMacro} == 1 && ($part ne $soc) && ($part ne $eoc)) && do {
print STDERR "INMACRO PPTOKEN: CASE 05\n" if ($liteDebug);
print STDERR "INMACRO IS 1, CHANGING TO 2 (NO PROCESSING)\n" if ($parseDebug || $localDebug);
# error case.
$parserState->{inMacro} = 2;
print STDERR "inMacro -> 2\n" if ($macroDebug || $cppDebug);
last SWITCH;
};
($parserState->{inMacro} > 1 && $part ne "//" && $part !~ /[\n\r]/ && ($part ne $soc) && ($part ne $eoc)) && do {
print STDERR "INMACRO OTHERTOKEN: CASE 06\n" if ($liteDebug);
print STDERR "INMACRO > 1, PART NE //" if ($parseDebug || $localDebug);
if ($part eq "\\") {
$parserState->addBackslash();
} elsif ($part !~ /[ \t]/) {
$parserState->addBackslash();
}
print STDERR "PART: $part\n" if ($macroDebug);
if ($parserState->{seenMacroPart} && $HeaderDoc::truncate_inline) {
print STDERR "MACRO: SMP&TI\n" if ($macroDebug);
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
print STDERR "MACRO: NOSTACK\n" if ($macroDebug);
if ($part =~ /\s/o && $parserState->{macroNoTrunc} == 1) {
print STDERR "MACRO: ENDOFNAME\n" if ($macroDebug);
$parserState->{macroNoTrunc} = 0;
} elsif ($part =~ /[\{\(]/o) {
print STDERR "MACRO: BRACE\n" if ($macroDebug);
if (!$parserState->{macroNoTrunc}) {
# $parserState->{seenBraces} = 1;
$HeaderDoc::hidetokens = 3;
}
} else {
print STDERR "MACRO: OTHERTOKEN\n" if ($macroDebug);
$parserState->{macroNoTrunc} = 2;
}
}
}
if ($part =~ /[\{\(]/o) {
push(@braceStack, $part);
print STDERR "PUSH\n" if ($macroDebug);
} elsif ($part =~ /[\}\)]/o) {
if ($part ne peekmatch(\@braceStack, $filename, $inputCounter)) {
if ($parserState->{macroNoTrunc} == 1) {
# We haven't reached the end of the first part of the declaration, so this is an error.
warn("$filename:$inputCounter: warning: Initial braces in macro name do not match.\nWe may have a problem.\n");
}
}
pop(@braceStack);
print STDERR "POP\n" if ($macroDebug);
}
if ($part =~ /\S/o) {
$parserState->{seenMacroPart} = 1;
$parserState->{lastsymbol} = $part;
if (($parserState->{sodname} eq "") && ($parserState->{inMacro} == 3)) {
print STDERR "DEFINE NAME IS $part\n" if ($macroDebug);
$parserState->{sodname} = $part;
}
}
$lastchar = $part;
last SWITCH;
};
# Regular expression handlers
# print STDERR "IRE: $inRegexp IRT: $inRegexpTrailer IS: $parserState->{inString} ICo $parserState->{inComment} ILC: $parserState->{inInlineComment} ICh $parserState->{inChar}\n";
(length($regexppattern) && $part =~ /^($regexppattern)$/ && !($inRegexp || $inRegexpTrailer || $parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "REGEXP PATTERN: CASE 07\n" if ($liteDebug);
my $match = $1;
print STDERR "REGEXP WITH PREFIX\n" if ($regexpDebug);
$regexpNoInterpolate = 0;
if ($match =~ /^($singleregexppattern)$/) {
# e.g. perl PATTERN?
$inRegexp = 2;
} else {
$inRegexp = 4;
# print STDERR "REGEXP PART IS \"$part\"\n";
if ($part eq "tr") { $regexpNoInterpolate = 1; }
# if ($part =~ /tr/) { $regexpNoInterpolate = 1; }
}
last SWITCH;
}; # end regexppattern
(($inRegexp || $parserState->{lastsymbol} eq "~") && (length($regexpcharpattern) && $part =~ /^($regexpcharpattern)$/ && (!scalar(@regexpStack) || $part eq peekmatch(\@regexpStack, $filename, $inputCounter)))) && do {
print STDERR "REGEXP CHARACTER: CASE 08\n" if ($liteDebug);
print STDERR "REGEXP?\n" if ($regexpDebug);
if (!$inRegexp) {
$inRegexp = 2;
}
# if ($lasttoken eq "\\")
if ($parserState->isQuoted($lang. $sublang)) {
# jump to next match.
$lasttoken = $part;
$parserState->{lastsymbol} = $part;
next SWITCH;
}
print STDERR "REGEXP POINT A\n" if ($regexpDebug);
$lasttoken = $part;
$parserState->{lastsymbol} = $part;
if ($part eq "#" &&
((scalar(@regexpStack) != 1) ||
(peekmatch(\@regexpStack, $filename, $inputCounter) ne "#"))) {
if ($nextpart =~ /^\s/o) {
# it's a comment. jump to next match.
next SWITCH;
}
}
print STDERR "REGEXP POINT B\n" if ($regexpDebug);
if (!scalar(@regexpStack)) {
push(@regexpStack, $part);
$inRegexp--;
} else {
my $match = peekmatch(\@regexpStack, $filename, $inputCounter);
my $tos = pop(@regexpStack);
if (!scalar(@regexpStack) && ($match eq $part)) {
$inRegexp--;
if ($inRegexp == 2 && $tos eq "/") {
# we don't double the slash in the
# middle of a s/foo/bar/g style
# expression.
$inRegexp--;
}
if ($inRegexp) {
push(@regexpStack, $tos);
}
} elsif (scalar(@regexpStack) == 1) {
push(@regexpStack, $tos);
if ($tos =~ /['"`]/o || $regexpNoInterpolate) {
# these don't interpolate.
next SWITCH;
}
} else {
push(@regexpStack, $tos);
if ($tos =~ /['"`]/o || $regexpNoInterpolate) {
# these don't interpolate.
next SWITCH;
}
push(@regexpStack, $part);
}
}
print STDERR "REGEXP POINT C\n" if ($regexpDebug);
if (!$inRegexp) {
$inRegexpTrailer = 2;
}
last SWITCH;
}; # end regexpcharpattern
# Start of preprocessor macros
($part eq "$sopreproc") && do {
print STDERR "SOPREPROC: CASE 09\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parserState->{onlyComments}) {
print STDERR "inMacro -> 1\n" if ($macroDebug || $cppDebug);
$parserState->{inMacro} = 1;
## @@@ FIXME DAG NEXT TWO LINES NEEDED FOR IDL TO AVOID
## "warning: Declaration starts with # but is not preprocessor macro"
## ERROR MESSAGE, BUT THIS BREAKS C/C++.
## WHY !?!?!
##
## if ($$treepart = " ";
## $nextpart = $part.$nextpart;
##
## END IDL-ONLY BLOCK
# $continue = 0;
# print STDERR "continue -> 0 [1]\n" if ($localDebug || $macroDebug);
} elsif ($curline =~ /^\s*$/o) {
$parserState->{inMacroLine} = 1;
print STDERR "IML\n" if ($localDebug);
} elsif ($postPossNL) {
print STDERR "PRE-IML \"$curline\"\n" if ($localDebug || $macroDebug);
$treeCur = $treeCur->addSibling("\n", 0);
bless($treeCur, "HeaderDoc::ParseTree");
$parserState->{inMacroLine} = 1;
$postPossNL = 0;
}
}
};
# Start of token-delimited functions and procedures (e.g.
# Pascal and PHP)
($part eq "$sofunction" || $part eq "$soprocedure") && do {
print STDERR "SOFUNC: CASE 10\n" if ($liteDebug);
$parserState->{sodclass} = "function";
print STDERR "K&R C FUNCTION FOUND [1].\n" if ($localDebug);
$parserState->{kr_c_function} = 1;
$parserState->{typestring} = "function";
$parserState->{startOfDec} = 2;
$parserState->{namePending} = 1;
# if (!$parserState->{seenBraces}) { # TREEDONE
# $treeNest = 1;
# $treePopTwo++;
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
# }
print STDERR "namePending -> 1 [1]\n" if ($parseDebug);
last SWITCH;
};
# C++ destructor handler.
($part =~ /\~/o && $lang eq "C" && $sublang eq "cpp" && !!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "C++ DESTRUCTOR: CASE 11\n" if ($liteDebug);
print STDERR "TILDE\n" if ($localDebug);
$parserState->{seenTilde} = 2;
$lastchar = $part;
$parserState->{onlyComments} = 0;
# $name .= '~';
last SWITCH;
};
# Objective-C method handler.
($part =~ /[-+]/o && $parserState->{onlyComments}) && do {
print STDERR "OBJC METHOD: CASE 12\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
print STDERR "OCCMETHOD\n" if ($localDebug);
# Objective C Method.
$parserState->{occmethod} = 1;
$parserState->{occmethodtype} = $part;
$lastchar = $part;
$parserState->{onlyComments} = 0;
print STDERR "[a]onlyComments -> 0\n" if ($macroDebug);
if (!$parserState->{seenBraces}) { # TREEDONE
if (!$parserState->{hollow}) {
print STDERR "SETHOLLOW -> 1\n" if ($parserStackDebug);
$sethollow = 1;
}
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [7]\n"; }
$parserState->{treePopTwo} = 1;
}
}
last SWITCH;
};
# Newline handler.
($part =~ /[\n\r]/o) && do {
print STDERR "NEWLINE: CASE 13\n" if ($liteDebug);
# NEWLINE FOUND
$treepart = $part;
if ($inRegexp) {
warn "$filename:$inputCounter: warning: multi-line regular expression\n";
}
print STDERR "NLCR\n" if ($tsDebug || $treeDebug || $localDebug);
if ($lastchar !~ /[\,\;\{\(\)\}]/o && $nextpart !~ /[\{\}\(\)]/o) {
if ($lastchar ne "*/" && $nextpart ne "/*") {
if (!$parserState->{inMacro} && !$parserState->{inMacroLine} && !$treePopOnNewLine) {
print STDERR "NL->SPC\n" if ($localDebug);
$part = " ";
print STDERR "LC: $lastchar\n" if ($localDebug);
print STDERR "NP: $nextpart\n" if ($localDebug);
$postPossNL = 2;
} else {
$parserState->{inMacroLine} = 0;
# Don't push parsed parameter here. Just clear it.
# push(@{$parserState->{parsedParamList}}, $parsedParam);
# print STDERR "pushed $parsedParam into parsedParamList [1]\n" if ($parmDebug);
print STDERR "skipped pushing CPP directive $parsedParam into parsedParamList [1]\n" if ($parmDebug || $cppDebug || $localDebug);
$parsedParam = "";
}
}
}
if ($treePopOnNewLine < 0) {
# pop once for //, possibly again for macro
$treePopOnNewLine = 0 - $treePopOnNewLine;
$treeCur = $treeCur->addSibling($treepart, 0);
bless($treeCur, "HeaderDoc::ParseTree");
# push(@treeStack, $treeCur);
$treeSkip = 1;
$treeCur = pop(@treeStack);
if (!$treeCur) {
$treeCur = $treeTop;
warn "$filename:$inputCounter: warning: Attempted to pop off top of tree\n";
}
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [1]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($treePopOnNewLine == 1 || ($treePopOnNewLine && !$parserState->isQuoted())) {
# $parserState->{lastsymbol} ne "\\"
$treeCur = $treeCur->addSibling($treepart, 0);
bless($treeCur, "HeaderDoc::ParseTree");
# push(@treeStack, $treeCur);
$treeSkip = 1;
$treeCur = pop(@treeStack);
if (!$treeCur) {
$treeCur = $treeTop;
warn "$filename:$inputCounter: warning: Attempted to pop off top of tree\n";
}
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->addSibling("", 0); # empty token
print STDERR "TSPOP [1a]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
$treePopOnNewLine = 0;
$HeaderDoc::hidetokens = 0;
} else {
print STDERR "Not popping from tree. Probably quoted.\n" if ($localDebug || $parseDebug);
}
next SWITCH;
};
# C++ template handlers
($part eq $sotemplate && !$parserState->{seenBraces} && ($parserState->{inOperator} != 1)) && do {
print STDERR "C++ TEMPLATE: CASE 14\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($HeaderDoc::hideIDLAttributes && $lang eq "C" && $sublang eq "IDL") { $hideTokenAndMaybeContents = 3; }
print STDERR "inTemplate -> ".($parserState->{inTemplate}+1)."\n" if ($localDebug);
print STDERR "SBS: " . scalar(@braceStack) . ".\n" if ($localDebug);
$parserState->{inTemplate}++;
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
$parserState->{preTemplateSymbol} = $parserState->{lastsymbol};
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{onlyComments} = 0;
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if (!$parserState->{hollow}) { $sethollow = 1; } # IDL can have this at the start of declaration.
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [8]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
print STDERR "[b]onlyComments -> 0\n" if ($macroDebug);
}
last SWITCH;
};
($part eq $eotemplate && !$parserState->{seenBraces} && ($parserState->{inOperator} != 1)) && do {
print STDERR "C++ TEMPLATE END: CASE 15\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && (!(scalar(@braceStack)-$parserState->{initbsCount}) || $parserState->{inTemplate})) {
if ($parserState->{inTemplate}) {
print STDERR "parserState->{inTemplate} -> ".($parserState->{inTemplate}-1)."\n" if ($localDebug);
$parserState->{inTemplate}--;
$parserState->{lastsymbol} = "";
$lastchar = $part;
$curline .= " ";
$parserState->{onlyComments} = 0;
print STDERR "[c]onlyComments -> 0\n" if ($macroDebug);
}
my $top = pop(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [2]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($top ne "$sotemplate") {
warn("$filename:$inputCounter: warning: Template (angle) brackets do not match.\nWe may have a problem.\n");
}
}
last SWITCH;
};
#
# Handles C++ access control state, e.g. "public:"
#
($part eq ":") && do {
print STDERR "Access control colon: CASE 16\n" if ($liteDebug);
print STDERR "TS IS \"$parserState->{typestring}\"\n" if ($localDebug || $parseDebug);
# fall through to next colon handling case if we fail.
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (length($accessregexp) && ($lastnspart =~ /$accessregexp/)) {
# We're special.
print STDERR "PERMANENT ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$parserState->{typestring} = "";
print STDERR "RESET HOLLOW at $part\n" if ($parserStackDebug);
$parserState->{hollow} = undef;
$parserState->{onlyComments} = 1;
print STDERR "hollowskip -> 1 (ACS)\n" if ($parserStateInsertDebug);
$hollowskip = 1;
$HeaderDoc::AccessControlState = $1;
$lastACS = $1;
last SWITCH;
} elsif ($parserState->{typestring} eq "struct") {
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
if (!$parserState->{structClassName}) {
$parserState->{structClassName} = $parserState->{lastsymbol};
$parserState->{bracePending} = 2;
}
}
}
}
};
(length($accessregexp) && ($part =~ /$accessregexp/)) && do {
print STDERR "Access regexp: CASE 17\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
# We're special.
if ($part =~ /^\@(.*)$/) {
print STDERR "PERMANENT ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$parserState->{typestring} = "";
print STDERR "RESET HOLLOW at $part\n" if ($parserStackDebug);
$parserState->{hollow} = undef;
$parserState->{onlyComments} = 1;
$hollowskip = 1;
print STDERR "hollowskip -> 1 (\@ACS)\n" if ($parserStateInsertDebug);
$HeaderDoc::AccessControlState = $1;
$lastACS = $1;
last SWITCH;
} else {
print STDERR "TEMPORARY ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$lastACS = $HeaderDoc::AccessControlState;
$HeaderDoc::AccessControlState = $1;
}
} else {
next SWITCH;
}
};
(length($requiredregexp) && $part =~ /$requiredregexp/) && do {
print STDERR "REQUIRED REGEXP MATCH: \"$part\"\n" if ($localDebug || $parseDebug);
$hollowskip = 1;
print STDERR "hollowskip -> 1 (requiredregexp)\n" if ($parserStateInsertDebug);
last SWITCH;
};
#
# C++ copy constructor handler. For example:
#
# char *class(void *a, void *b) :
# class(pri_type, pri_type);
#
($part eq ":") && do {
print STDERR "Copy constructor: CASE 18\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parserState->{occmethod}) {
$parserState->{name} = $parserState->{lastsymbol};
if ($parserState->{occparmlabelfound}) {
$parserState->{occmethodname} .= "$parserState->{lastsymbol}:";
if ($occMethodNameDebug) {
print STDERR "OCC method name now ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\").\n";
}
$parserState->{occparmlabelfound} = -1; # next token is name of this parameter, followed by label for next parameter.
} else {
if ($occMethodNameDebug) {
print STDERR "OCC method name missing.\n";
print STDERR "OCC method name still ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\").\n";
}
$parserState->{occparmlabelfound} = -2; # Special case: grab the parameter name instead because parameter has no label.
}
# Start doing line splitting here.
# Also, capture the method's name.
if ($parserState->{occmethod} == 1) {
$parserState->{occmethod} = 2;
if (!$prespace) { $prespaceadjust = 4; }
$parserState->{onlyComments} = 0;
print STDERR "[d]onlyComments -> 0\n" if ($macroDebug);
}
} else {
if ($lang eq "C" && $sublang eq "cpp") {
if (!(scalar(@braceStack)-$parserState->{initbsCount}) && $parserState->{sodclass} eq "function") {
$inPrivateParamTypes = 1;
$declaration .= "$curline";
$publicDeclaration = $declaration;
$declaration = "";
} else {
next SWITCH;
}
if (!$parserState->{stackFrozen}) {
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
# print STDERR "SEOPPLS\n";
# for my $item (@{$parserState->{pplStack}}) {
# print STDERR "PPLS: $item\n";
# }
# print STDERR "OEOPPLS\n";
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
} else {
next SWITCH;
}
}
if (!$parserState->{seenBraces} && !$parserState->{occmethod}) { # TREEDONE
# $treeCur->addSibling($part, 0); $treeSkip = 1;
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [9]\n"; }
$parserState->{treePopTwo} = 1;
# $treeCur = pop(@treeStack) || $treeTop;
# bless($treeCur, "HeaderDoc::ParseTree");
}
last SWITCH;
} else {
next SWITCH;
}
};
# Non-newline, non-carriage-return whitespace handler.
($part =~ /\s/o) && do {
print STDERR "Whitespace: CASE 19\n" if ($liteDebug);
# just add white space silently.
# if ($part eq "\n") { $parserState->{lastsymbol} = ""; };
$lastchar = $part;
last SWITCH;
};
# backslash handler (largely useful for macros, strings).
($part =~ /\\/o) && do {
print STDERR "BACKSLASH: CASE 20\n" if ($liteDebug);
$parserState->{lastsymbol} = $part; $lastchar = $part;
$parserState->addBackslash();
};
# quote and bracket handlers.
($part eq "\"") && do {
print STDERR "DOUBLE QUOTE: CASE 21\n" if ($liteDebug);
print STDERR "dquo\n" if ($localDebug);
# print STDERR "QUOTEDEBUG: CURSTRING IS '$curstring'\n";
# print STDERR "QUOTEDEBUG: CURLINE IS '$curline'\n";
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{onlyComments} = 0;
print STDERR "[e]onlyComments -> 0\n" if ($macroDebug);
print STDERR "LASTTOKEN: $lasttoken\nCS: $curstring\n" if ($localDebug);
# if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o))
if (!$parserState->isQuoted($lang, $sublang)) {
if (!$parserState->{inString}) {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [10]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} else {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [3]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
$parserState->{inString} = (1-$parserState->{inString});
}
}
$lastchar = $part;
$parserState->{lastsymbol} = "";
last SWITCH;
};
($part eq "[") && do {
print STDERR "LEFT BRACKET: CASE 22\n" if ($liteDebug);
# left square bracket (square brace)
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
print STDERR "lbracket\n" if ($localDebug);
print STDERR "LBRACKET DEBUG TRACE: SODNAME: ".$parserState->{sodname}." SODTYPE: ".$parserState->{sodtype}." SIMPLETDCONTENTS: ".$parserState->{simpleTDcontents}."\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
$parserState->{onlyComments} = 0;
print STDERR "[f]onlyComments -> 0\n" if ($macroDebug);
}
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [11]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$parserState->{inBrackets} += 1;
}
$lastchar = $part;
last SWITCH;
};
($part eq "]") && do {
print STDERR "CLOSE BRACKET: CASE 23\n" if ($liteDebug);
# right square bracket (square brace)
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
print STDERR "rbracket\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
$parserState->{onlyComments} = 0;
print STDERR "[g]onlyComments -> 0\n" if ($macroDebug);
}
my $top = pop(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [4]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($top ne "[") {
warn("$filename:$inputCounter: warning: Square brackets do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
}
pbs(@braceStack);
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$parserState->{inBrackets} -= 1;
}
$lastchar = $part;
last SWITCH;
};
($part eq "'") && do {
print STDERR "SINGLE QUOTE: CASE 24\n" if ($liteDebug);
print STDERR "squo\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
# if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o))
if (!$parserState->isQuoted($lang, $sublang)) {
$parserState->{onlyComments} = 0;
print STDERR "[h]onlyComments -> 0\n" if ($macroDebug);
if (!$parserState->{inChar}) {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [12]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} else {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [5]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
$parserState->{inChar} = !$parserState->{inChar};
}
if ($lastchar =~ /\=$/o) {
$curline .= " ";
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Inline comment (two slashes in c++, hash in perl/shell)
# handler.
(($part eq $ilc || $part eq $ilc_b) && ($lang ne "perl" || $lasttoken ne "\$")) && do {
print STDERR "SINGLE LINE COMMENT: CASE 25\n" if ($liteDebug);
print STDERR "ILC\n" if ($localDebug || $ilcDebug);
if (!($parserState->{inComment} || $parserState->{inChar} || $parserState->{inString} || $inRegexp)) {
$parserState->{inInlineComment} = 4;
print STDERR "inInlineComment -> 1\n" if ($ilcDebug);
$curline = spacefix($curline, $part, $lastchar, $soc, $eoc, $ilc, $ilc_b);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [13]\n"; }
if (!$treePopOnNewLine) {
$treePopOnNewLine = 1;
} else {
$treePopOnNewLine = 0 - $treePopOnNewLine;
}
print STDERR "treePopOnNewLine -> $treePopOnNewLine\n" if ($ilcDebug);
# $treeCur->addSibling($part, 0); $treeSkip = 1;
# $treePopOnNewLine = 1;
# $treeCur = pop(@treeStack) || $treeTop;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif ($parserState->{inComment}) {
my $linenum = $inputCounter + $fileoffset;
if (!$cpp_in_argparse) {
# We've already seen these.
if ($nestedcommentwarn) {
warn("$filename:$linenum: warning: Nested comment found [1]. Ignoring.\n");
}
# This isn't really a problem.
# Don't warn to avoid bogus
# warnings for apple_ref and
# URL markup in comments.
}
# warn("XX $cpp_in_argparse XX $inputCounter XX $fileoffset XX\n");
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Standard comment handlers: soc = start of comment,
# eoc = end of comment.
($part eq $soc) && do {
print STDERR "START OF MULTILINE COMMENT: CASE 26\n" if ($liteDebug);
print STDERR "SOC\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{inComment} = 4;
$curline = spacefix($curline, $part, $lastchar);
if (!$parserState->{seenBraces}) {
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [14]\n"; }
# print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug);
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild("", 0);
# bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif ($parserState->{inComment}) {
my $linenum = $inputCounter + $fileoffset;
# Modern compilers shouldn't have trouble with this. It occurs |
# frequently in apple_ref markup (e.g. //apple_ref/C/instm/ \|/
# IOFireWireDeviceInterface/AddIsochCallbackDispatcherToRunLoop/*Add
# IsochCallbackDispatcherToRunLoopIOFireWireLibDeviceRefCFRunLoopRef)
if ($nestedcommentwarn) {
warn("$filename:$linenum: warning: Nested comment found [2]. Ignoring.\n");
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
($part eq $eoc) && do {
print STDERR "END OF MULTILINE COMMENT: CASE 27\n" if ($liteDebug);
print STDERR "EOC\n" if ($localDebug);
if ($parserState->{inComment} && !($parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{inComment} = 0;
$curline = spacefix($curline, $part, $lastchar);
$ppSkipOneToken = 1;
if (!$parserState->{seenBraces}) {
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif (!$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && !$inRegexp) {
my $linenum = $inputCounter + $fileoffset;
warn("$filename:$linenum: warning: Unmatched close comment tag found. Ignoring.\n");
} elsif ($parserState->{inInlineComment}) {
my $linenum = $inputCounter + $fileoffset;
# We'll leave this one on for now.
if ((1 || $nestedcommentwarn) && (!$HeaderDoc::test_mode)) {
warn("$filename:$linenum: warning: Nested comment found [3]. Ignoring.\n");
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Parenthesis and brace handlers.
($part eq "(") && do {
print STDERR "OPEN PAREN: CASE 28\n" if ($liteDebug);
my @tempppl = undef;
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
if (!(scalar(@braceStack)-$parserState->{initbsCount})) {
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
print STDERR "parsedParamList wiped\n" if ($parmDebug);
@tempppl = @{$parserState->{parsedParamList}};
@{$parserState->{parsedParamList}} = ();
$parsedParam = "";
}
$parserState->{onlyComments} = 0;
print STDERR "[i]onlyComments -> 0\n" if ($macroDebug);
if ($parserState->{simpleTypedef} && !(scalar(@braceStack)- $parserState->{initbsCount})) {
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "Setting typedef sodname to ".$parserState->{lastsymbol}."\n" if ($localDebug || $sodDebug);
$parserState->{sodname} = $parserState->{lastsymbol};
$parserState->{sodclass} = "function";
# DAG: changed to respect freezereturn
# and hollow, but in the unlikely event
# that we should start seeing any weird
# "missing return type info" bugs,
# this next line might need to be
# put back in rather than the lines
# that follow it.
# $parserState->{returntype} = "$declaration$curline";
if (!$parserState->{freezereturn} && $parserState->{hollow}) {
$parserState->{returntype} = "$declaration$curline";
} elsif (!$parserState->{freezereturn} && !$parserState->{hollow}) {
$parserState->{returntype} = "$curline";
$declaration = "";
}
}
$parserState->{posstypesPending} = 0;
if ($parserState->{callbackNamePending} == 2) {
$parserState->{callbackNamePending} = 3;
print STDERR "callbackNamePending -> 3\n" if ($localDebug || $cbnDebug);
}
print STDERR "lparen\n" if ($localDebug);
if ($parserState->{cbsodname} && (scalar(@braceStack)-$parserState->{initbsCount}) == 0) {
if (!$parserState->{functionReturnsCallback}) {
# At the top level, if we see a second open parenthesis after setting a callback
# name, the first token in the first set of open parentheses is the name of
# the callback, so clear cbsodname.
#
# Until this point, the value in cbsodname was a copy of the already-cleared
# sodname field, and would replace the callbackName field at the end of
# processing.
$parserState->{cbsodname} = "";
} else {
# If we are in a function that returns a callback, everything from here on
# is a list of parameters for the callback, not the function, so the
# previous parameter list should be discarded (though it is useful to
# add these parameters as valid things to comment about)
@{$parserState->{parsedParamList}} = @tempppl;
$parserState->{functionReturnsCallback}--;
print STDERR "parsedParamList restored\n" if ($parmDebug);
}
}
if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) {
if ($parserState->{callbackName}) {
$parserState->{cbsodname} = $parserState->{callbackName};
$parserState->{sodclass} = "function";
# $parserState->{callbackName} = "";
$parserState->{functionReturnsCallback}++;
print "Function returning callback. NAME: $parserState->{cbsodname}\n" if ($parmDebug || $localDebug || $parseDebug);
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
print STDERR "parsedParamList wiped\n" if ($parmDebug);
@tempppl = @{$parserState->{parsedParamList}};
@{$parserState->{parsedParamList}} = ();
$parsedParam = "";
}
}
if ($parserState->{inOperator} == 1) {
$parserState->{inOperator} = 2;
}
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [15]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
print STDERR "LASTCHARCHECK: \"$lastchar\" \"$lastnspart\" \"$curline\".\n" if ($localDebug);
if ($lastnspart eq ")") { # || $curline =~ /\)\s*$/so
print STDERR "HERE: DEC IS $declaration\nENDDEC\nCURLINE IS $curline\nENDCURLINE\n" if ($localDebug);
# print STDERR "CALLBACKMAYBE: $parserState->{callbackNamePending} $parserState->{sodclass} ".scalar(@braceStack)."\n";
print STDERR "SBS: ".scalar(@braceStack)."\n" if ($localDebug);
### if (!$parserState->{callbackNamePending} && ($parserState->{sodclass} eq "function") && ((scalar(@braceStack)-$parserState->{initbsCount}) == 1)) { # && $argparse
### # Guess it must be a callback anyway.
### my $temp = pop(@tempppl);
### $parserState->{callbackName} = $temp;
### $parserState->{name} = "";
### $parserState->{sodclass} = "";
### $parserState->{sodname} = "";
### print STDERR "CALLBACKHERE ($temp)!\n" if ($cbnDebug || $parseDebug);
### }
if ($declaration =~ /.*\n(.*?)\n$/so) {
my $lastline = $1;
print STDERR "LL: $lastline\nLLDEC: $declaration" if ($localDebug);
$declaration =~ s/(.*)\n(.*?)\n$/$1\n/so;
$curline = "$lastline $curline";
$curline =~ s/^\s*//so;
$prespace -= 4;
$prespaceadjust += 4;
$forcenobreak = 1;
print STDERR "NEWDEC: $declaration\nNEWCURLINE: $curline\n" if ($localDebug);
} elsif (length($declaration) && $callback_typedef_and_name_on_one_line) {
print STDERR "SCARYCASE\n" if ($localDebug);
$declaration =~ s/\n$//so;
$curline = "$declaration $curline";
$declaration = "";
$prespace -= 4;
$prespaceadjust += 4;
$forcenobreak = 1;
}
} else { print STDERR "OPARENLC: \"$lastchar\"\nCURLINE IS: \"$curline\"\n" if ($localDebug);}
$parserState->{lastsymbol} = "";
$lastchar = $part;
if ($parserState->{startOfDec} == 2) {
$parserState->{sodclass} = "function";
$parserState->{freezereturn} = 1;
$parserState->{returntype} =~ s/^\s*//so;
$parserState->{returntype} =~ s/\s*$//so;
}
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
print STDERR "OUTGOING CURLINE: \"$curline\"\n" if ($localDebug);
last SWITCH;
};
($part eq ")") && do {
print STDERR "CLOSE PAREN: CASE 29\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate && (peek(\@regexpStack) ne "("))) {
if ((scalar(@braceStack)-$parserState->{initbsCount} - $parserState->{functionReturnsCallback}) == 1) {
# stop parameter parsing
$parsedParamParse = 0;
print STDERR "parsedParamParse -> 0\n" if ($parmDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if ($parsedParam ne "void") {
# ignore foo(void)
push(@{$parserState->{parsedParamList}}, $parsedParam);
print STDERR "pushed $parsedParam into parsedParamList [1]\n" if ($parmDebug);
}
$parsedParam = "";
}
$parserState->{onlyComments} = 0;
print STDERR "[j]onlyComments -> 0\n" if ($macroDebug);
print STDERR "rparen\n" if ($localDebug);
my $test = pop(@braceStack); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6a]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if (!($test eq "(")) { # ) brace hack for vi
warn("$filename:$inputCounter: warning: Parentheses do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
# cluck("backtrace follows\n");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace -= 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust -= 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
(casecmp($part, $lbrace, $case_sensitive)) && do {
print STDERR "LEFT BRACE: CASE 30\n" if ($liteDebug);
if ($parserState->{onlyComments} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inChar} && !($inRegexp && $regexpNoInterpolate) && scalar(@parserStack)) {
# Somebody put in a brace in the middle of
# a class or else we're seeing ObjC private
# class bits. Either way, throw away the
# curly brace.
print STDERR "NOINSERT\n" if ($parserStackDebug);
$pushParserStateAtBrace = 1;
# $setNoInsert = 1;
$parserState->{noInsert} = 1;
}
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
$parserState->{bracePending} = 0;
print STDERR "bracePending -> 0 [brace]\n" if ($localDebug);
$parserState->{onlyComments} = 0;
print STDERR "[k]onlyComments -> 0\n" if ($macroDebug);
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
# print STDERR "statecheck: ".$parserState->{inClass}."X".$parserState->{sodclass}."X".$parserState->{inOperator}."X".$parserState->{occmethod}."\n"; # @@@ CHECKME - Do this for Obj-C methods too?
if (!$parserState->{inClass} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator} || $parserState->{occmethod})) {
# This is the opening brace of a function. Start ignoring everything
# until the matching brace is encountered.
print "seenBraces -> 1\n" if ($parseDebug);
$parserState->{seenBraces} = 1;
if (!$parserState->{stackFrozen}) {
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
@{$parserState->{pplStack}} = ();
}
$parserState->{posstypesPending} = 0;
$parserState->{namePending} = 0;
$parserState->{callbackNamePending} = -1;
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "callbackNamePending -> -1\n" if ($localDebug || $cbnDebug);
print STDERR "lbrace\n" if ($localDebug);
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [16]\n"; }
print STDERR "TN -> 1\n" if ($localDebug);
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
if ($parserState->{INMODULE} == 2) {
# Drop token on the floor.
$treepart = " ";
}
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
(casecmp($part, $rbrace, $case_sensitive)) && do {
print STDERR "RIGHT BRACE: CASE 31\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate && (peek(\@regexpStack) ne "$lbrace"))) {
my $oldOC = $parserState->{onlyComments};
print STDERR "rbrace???\n" if ($localDebug);
# $parserState->{onlyComments} = 0; # If this is all we've seen, there's either a bug or we're
# unrolling a class or similar anyway.
print STDERR "[l]onlyComments -> 0\n" if ($macroDebug);
my $bsCount = scalar(@braceStack);
if (scalar(@parserStack) && !($bsCount - $parserState->{initbsCount})) {
print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug);
if ($parserState->{noInsert} || $oldOC) {
print STDERR "parserState insertion skipped[RBRACE]\n" if ($parserStackDebug || $parserStateInsertDebug);
} elsif ($parserState->{hollow}) {
print STDERR "inserted parser state into tree [RBRACE]\n" if ($parserStateInsertDebug);
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[1].\n";
}
print STDERR "parserState popped from parserStack[rbrace]\n" if ($parserStackDebug);
# print STDERR "PREINMODULE: ".$parserState->{INMODULE}."\n";
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
# print STDERR "INMODULE: ".$parserState->{INMODULE}."\n";
if ($parserState->{INMODULE} == 2) {
# Drop token on the floor.
print STDERR "CURRENT: ".$treeCur->{TOKEN}."\n" if ($localDebug);
$part = "";
print STDERR "INMODULE -> 3\n" if ($localDebug || $moduleDebug);
$parserState->{INMODULE} = 3;
print STDERR "continue -> 0 [1a]\n" if ($localDebug || $liteDebug);
$parserState->{noInsert} = 0;
$continue = 0;
print STDERR "AT END: REALPS IS ".$parserState->{REALPS}."\n" if ($parserStackDebug || $localDebug);
print STDERR "STACK COUNT: ".scalar(@parserStack)."\n" if ($parserStackDebug || $localDebug);
}
if ($lang eq "php" || ($lang eq "C" && $sublang eq "IDL")) {
# print STDERR "PHP OUT OF BRACES?: ".scalar(@braceStack)."\n";
if (scalar(@braceStack) == 1) {
# PHP and IDL classes end at
# the brace.
print STDERR "continue -> 0 [1a]\n" if ($localDebug || $liteDebug);
$continue = 0;
}
}
if ($parserState->{noInsert} && scalar(@parserStack)) {
# This is to handle the end of
# the private vars in an
# Objective C class.
print STDERR "parserState: Hit me.\n" if ($localDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
# It's about to go down by 1.
$parserState->{initbsCount} = scalar(@braceStack) - 1;
}
# $parserState->{onlyComments} = 1;
} else {
print STDERR "NO CHANGE IN PARSER STATE STACK (nPARSERSTACK = ".scalar(@parserStack).", $bsCount != $parserState->{initbsCount})\n" if ($parseDebug || $parserStackDebug);
}
if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) {
# stop parameter parsing
$parsedParamParse = 0;
print STDERR "parsedParamParse -> 0\n" if ($parmDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) {
# ignore foo(void)
push(@{$parserState->{parsedParamList}}, $parsedParam);
print STDERR "pushed $parsedParam into parsedParamList [1b]\n" if ($parmDebug);
}
$parsedParam = "";
} else {
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
}
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
print STDERR "rbrace\n" if ($localDebug);
my $test = pop(@braceStack); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [7]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if (!($test eq "$lbrace") && (!length($structname) || (!($test eq $structname) && $structisbrace))) {
warn("$filename:$inputCounter: warning: Braces do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace -= 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust -= 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
# Typedef, struct, enum, and union handlers.
# Merge the '@' symbol onto @protocol, @property, @public, and similar.
(length($part) && length($nextpart) && ((length($propname) && $propname =~ /\@/) || length($objcdynamicname) || length($objcsynthesizename) || length($classregexp) || (length($accessregexp) && $accessregexp =~ /\@/)) && $part =~ /^\@$/ && !$parserState->{inComment} && !$parserState->{inChar} && !$parserState->{inString} && !$parserState->{inInlineComment}) && do {
print STDERR "PROPERTY PREPEND AT (\@): CASE 32\n" if ($liteDebug);
my $temp = "\@".$nextpart;
# print STDERR "TEMP IS $temp PROPNAME is $propname\n";
if ($temp =~ /$accessregexp/) {
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
$parserState->{classIsObjC} = 1;
} elsif ($temp =~ /$classregexp/) {
$nextpart = "\@".$nextpart;
$parserState->{classIsObjC} = 1;
} elsif ($temp =~ /$classclosebraceregexp/) {
$nextpart = "\@".$nextpart;
} elsif ($temp eq $propname) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif (length($requiredregexp) && $temp =~ /$requiredregexp/) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif ($temp eq $objcdynamicname) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif ($temp eq $objcsynthesizename) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
}
next SWITCH;
};
($modules_are_special && !$parserState->{inTemplate} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && length($moduleregexp) && $part =~ /$moduleregexp/) && do {
print STDERR "INMODULE -> 1\n" if ($localDebug || $moduleDebug);
$parserState->{INMODULE} = 1;
print STDERR "MODULE START TOKEN: CASE 32-M-1\n" if ($localDebug || $liteDebug);
};
(length($classclosebraceregexp) && ($part =~ /$classclosebraceregexp/) && !$parserState->{inComment} && !$parserState->{inChar} && !$parserState->{inString} && !$parserState->{inInlineComment}) && do {
print STDERR "CLASS CLOSE BRACE: CASE 33\n" if ($liteDebug);
if ($part ne peekmatch(\@braceStack, $filename, $inputCounter)) {
warn("$filename:inputCounter: warning: Class braces do not match.\nWe may have a problem.\n");
}
$parserState->{seenBraces} = 1;
pop(@braceStack);
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
$part =~ s/^\@//s;
if ( 1 || $nextpart ne ";") {
# Objective C protocol/interface declarations end at the close curly brace.
# No ';' necessary (though we'll eat it if it's there.
# No, we won't. Deal with it.
if (scalar(@parserStack) == 1) {
# Throw away current parser state, since
# it will always be empty anyway.
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
$continue = 0;
print STDERR "continue -> 0 [occend]\n" if ($localDebug);
} else {
if (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[\@end]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
print STDERR "inserted parser state into tree [\@end]\n" if ($parserStateInsertDebug);
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[2].\n";
}
print STDERR "parserState: Created parser state[1].\n" if ($parserStackDebug);
print STDERR "CURLINE CLEAR[PRS2]\n" if ($localDebug);
$curline = "";
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
}
print STDERR "parserState popped from parserStack[\@end]\n" if ($parserStackDebug);
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
}
}
# fall through to next case. WHY???
};
(!$parserState->{inTemplate} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && length($classregexp) && $part =~ /$classregexp/) && do {
print STDERR "START OF CLASS: CASE 34\n" if ($liteDebug);
### if ($parserState->{classIsObjC}) { $sublang = "occ"; }
### else { $sublang = "cpp"; }
### print STDERR "LANG $lang SUBLANG $sublang\n" if ($localDebug || $parseDebug || $classDebug);
### # Update the class regular expressions because our language has changed.
### ($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
### $soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
### $enumname,
### $typedefname, $varname, $constname, $structisbrace, $macronameref,
### $classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
### $requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
### print STDERR "PROPNAME NOW $propname\n" if ($localDebug || $parseDebug || $classDebug);
my $localclasstype = $1;
if ($part =~ /^\@/) { $part =~ s/^\@//s; }
if (!(scalar(@braceStack)-$parserState->{initbsCount})) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
print STDERR "ITISACLASS\n" if ($localDebug);
if (!length($parserState->{sodclass})) {
print STDERR "GOOD.\n" if ($localDebug);
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [7]\n" if ($classDebug);
$pushParserStateAtBrace = 1;
if ($localclasstype =~ /\@interface/) {
$parserState->{inClass} = 2;
print STDERR "inClass -> 2 [8]\n" if ($classDebug);
$pushParserStateAtBrace = 0;
} elsif ($localclasstype =~ /\@protocol/) {
$pushParserStateAtBrace = 0;
$pushParserStateAfterWordToken = 0;
$parserState->{inClass} = 0;
print STDERR "inClass -> 0 [9]\n" if ($classDebug);
$parserState->{inProtocol} = 1;
} elsif ($localclasstype =~ /\@implementation/) {
$pushParserStateAtBrace = 0;
$pushParserStateAfterWordToken = 2;
}
$parserState->{sodclass} = "class";
$parserState->{classtype} = $localclasstype;
$parserState->{preclasssodtype} = $parserState->{sodtype} . $part;
$parserState->{sodtype} = "";
$parserState->{startOfDec} = 1;
$parserState->{onlyComments} = 0;
print STDERR "[m]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
# Get the parse tokens from Utilities.pm.
if (length($classbraceregexp) && ($localclasstype =~ /$classbraceregexp/)) {
print STDERR "CLASS ($localclasstype) IS A BRACE.\n" if ($localDebug);
push(@braceStack, $localclasstype); pbs(@braceStack);
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [17]\n"; }
# } else {
# print STDERR "CBRE: \"$classbraceregexp\"\n";
}
($lang, $sublang) = getLangAndSublangFromClassType($localclasstype);
$HeaderDoc::lang = $lang;
$HeaderDoc::sublang = $sublang;
($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
$soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
$enumname,
$typedefname, $varname, $constname, $structisbrace, $macronameref,
$classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
$requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
my $macrore = macroRegexpFromList($macronameref);
# print STDERR "PROPNAME2: $propname\n";
print STDERR "ARP: $accessregexp\n" if ($localDebug);
last SWITCH;
}
}
}
};
($part eq $objcdynamicname) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $objcsynthesizename) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $propname) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $structname || $part eq $enumname || $part eq $unionname) && do {
print STDERR "STRUCT/ENUM/UNION: CASE 36\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($structisbrace) {
if ($parserState->{sodclass} eq "function") {
$parserState->{seenBraces} = 1;
if (!$parserState->{stackFrozen}) {
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
@{$parserState->{pplStack}} = ();
}
$parserState->{posstypesPending} = 0;
$parserState->{callbackNamePending} = -1;
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "callbackNamePending -> -1\n" if ($localDebug || $cbnDebug);
print STDERR "lbrace\n" if ($localDebug);
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [18]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
} else {
if (!$parserState->{simpleTypedef}) {
print STDERR "simpleTypedef -> 2\n" if ($localDebug);
$parserState->{simpleTypedef} = 2;
}
# if (!$parserState->{seenBraces}) { # TREEDONE
# $treePopTwo++;
# $treeNest = 1;
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
# }
}
$parserState->{onlyComments} = 0;
print STDERR "[n]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
# $parserState->{simpleTypedef} = 0;
if ($parserState->{basetype} eq "") { $parserState->{basetype} = $part; }
# fall through to default case when we're done.
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString} || $parserState->{inChar})) {
$parserState->{namePending} = 2;
print STDERR "namePending -> 2 [2]\n" if ($parseDebug);
if ($parserState->{posstypesPending}) { $parserState->{posstypes} .=" $part"; }
}
if ($parserState->{sodclass} eq "") {
$parserState->{startOfDec} = 0; $parserState->{sodname} = "";
print STDERR "sodname cleared (seu)\n" if ($sodDebug);
}
$lastchar = $part;
}; # end if
}; # end do
($part =~ /^$typedefname$/) && do {
print STDERR "TYPEDEF: CASE 37\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (!(scalar(@braceStack)-$parserState->{initbsCount})) { $parserState->{callbackIsTypedef} = 1; $parserState->{inTypedef} = 1; }
$parserState->{onlyComments} = 0;
print STDERR "[o]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
$parserState->{simpleTypedef} = 1; print STDERR "simpleTypedef -> 1\n" if ($localDebug);
# previous case falls through, so be explicit.
if ($part =~ /^$typedefname$/) {
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString} || $parserState->{inChar})) {
if ($pascal) {
$parserState->{namePending} = 2;
$inPType = 1;
print STDERR "namePending -> 2 [3]\n" if ($parseDebug);
}
if ($parserState->{posstypesPending}) { $parserState->{posstypes} .=" $part"; }
if (!($parserState->{callbackNamePending})) {
print STDERR "callbackNamePending -> 1\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 1;
}
}
}
if ($parserState->{sodclass} eq "") {
$parserState->{startOfDec} = 0; $parserState->{sodname} = "";
print STDERR "sodname cleared ($typedefname)\n" if ($sodDebug);
}
$lastchar = $part;
}; # end if
}; # end do
# C++ operator keyword handler
($part eq "$operator") && do {
print STDERR "OPERATOR KEYWORD: CASE 38\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{inOperator} = 1;
$parserState->{sodname} = "";
}
$parserState->{lastsymbol} = $part;
$lastchar = $part;
last SWITCH;
# next;
};
# Punctuation handlers
($part =~ /;/o) && do {
print STDERR "SEMICOLON: CASE 39\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parsedParamParse) {
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) { push(@{$parserState->{parsedParamList}}, $parsedParam); }
print STDERR "pushed $parsedParam into parsedParamList [2semi]\n" if ($parmDebug);
$parsedParam = "";
}
# skip this token
$parsedParamParse = 2;
$parserState->{freezereturn} = 1;
# $parserState->{onlyComments} = 0; # If this is all we've seen, there's either a bug or we're
# unrolling a class or similar anyway.
$parserState->{temponlyComments} = $parserState->{onlyComments};
print STDERR "[p]onlyComments -> 0\n" if ($macroDebug);
print STDERR "valuepending -> 0\n" if ($valueDebug);
$parserState->{valuepending} = 0;
$continuation = 1;
if ($parserState->{occmethod}) {
$prespaceadjust = -$prespace;
}
# previous case falls through, so be explicit.
if ($part =~ /;/o && !$parserState->{inMacroLine} && !$parserState->{inMacro}) {
my $bsCount = scalar(@braceStack)-$parserState->{initbsCount};
if (!$bsCount && !$parserState->{kr_c_function}) {
if ($parserState->{startOfDec} == 2) {
$parserState->{sodclass} = "constant";
$parserState->{startOfDec} = 1;
} elsif (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{startOfDec} = 1;
}
# $parserState->{lastsymbol} .= $part;
}
if (!$bsCount) {
$treeCur = $treeCur->addSibling(";"); $treepart = " "; # $treeSkip = 1;
if (0) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [8]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
# $parserState->{lastTreeNode} = $treeCur;
# print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n";
while ($parserState->{treePopTwo}--) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [9]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
$parserState->{treePopTwo} = 0;
}
}
$lastchar = $part;
}; # end if
}; # end do
($part eq "=" && ($parserState->{lastsymbol} ne "operator") && (!(($parserState->{inOperator} == 1) && $parserState->{lastsymbol} =~ /\W/ && $parserState->{lastsymbol} =~ /\S/)) && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "EQUALS: CASE 40\n" if ($liteDebug);
$parserState->{onlyComments} = 0;
print STDERR "[q]onlyComments -> 0\n" if ($macroDebug);
if ($part =~ /=/o && !(scalar(@braceStack)-$parserState->{initbsCount}) &&
$nextpart !~ /=/o && $lastchar !~ /=/o &&
$parserState->{sodclass} ne "function" && !$inPType) {
print STDERR "valuepending -> 1\n" if ($valueDebug);
$parserState->{valuepending} = 1;
$parserState->{preEqualsSymbol} = $parserState->{lastsymbol};
$parserState->{sodclass} = "constant";
$parserState->{startOfDec} = 0;
}; # end if
}; # end do
($part =~ /,/o) && do {
print STDERR "COMMA: CASE 41\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{onlyComments} = 0;
print STDERR "[r]onlyComments -> 0\n" if ($macroDebug);
}
if ($part =~ /,/o && $parsedParamParse && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && ((scalar(@braceStack)-$parserState->{initbsCount}-$parserState->{functionReturnsCallback}) == 1) && (peek(\@braceStack) eq '(' || peek(\@braceStack) eq '{')) {
print STDERR "$part is a comma\n" if ($localDebug || $parseDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) { push(@{$parserState->{parsedParamList}}, $parsedParam); }
print STDERR "pushed $parsedParam into parsedParamList [2]\n" if ($parmDebug);
$parsedParam = "";
# skip this token
$parsedParamParse = 2;
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
}; # end if
}; # end do
($part =~ /[*^]/) && do {
if ($lastnspart eq "(" && # ")"
!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) &&
!$parserState->{callbackNamePending} &&
((scalar(@braceStack)-$parserState->{initbsCount}) == 1)) {
# print "CBNP\n";
$parserState->{callbackNamePending} = 3;
}
# Fall through to the default case.
}; # end star/asterisk/caret case
{ # SWITCH default case
print STDERR "DEFAULT CASE: CASE 42\n" if ($liteDebug);
# Handler for all other text (data types, string contents,
# comment contents, character contents, etc.)
print STDERR "DEFAULT CASE\n" if ($localDebug || $parseDebug);
# print STDERR "TEST CURLINE IS \"$curline\".\n";
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (!ignore($part, $ignoreref, $perheaderignoreref)) {
if ($part =~ /\S/o) {
$parserState->{onlyComments} = 0;
print STDERR "[s]onlyComments -> 0\n" if ($macroDebug);
}
if (!$continuation && !$occspace) {
$curline = spacefix($curline, $part, $lastchar);
} else {
$continuation = 0;
$occspace = 0;
}
# print STDERR "BAD CURLINE IS \"$curline\".\n";
if (length($part) && !($parserState->{inComment} || $parserState->{inInlineComment})) {
if ($localDebug && $lastchar eq ")") {print STDERR "LC: $lastchar\nPART: $part\n";}
# print STDERR "XXX LC: $lastchar SC: $parserState->{sodclass} LG: $lang\n";
if ($lastchar eq ")" && $parserState->{sodclass} eq "function" && ($lang eq "C" || $lang eq "Csource") && !(scalar(@braceStack)-$parserState->{initbsCount})) {
if ($part !~ /^\s*;/o) {
# warn "K&R C FUNCTION FOUND.\n";
# warn "NAME: $parserState->{sodname}\n";
if (!isKeyword($part, $keywordhashref, $case_sensitive)) {
my $tempavail = ignore($part, $ignoreref, $perheaderignoreref);
if (!$tempavail) {
print STDERR "K&R C FUNCTION FOUND [2].\n" if ($localDebug);
print STDERR "TOKEN: \"$part\"\n" if ($localDebug);
print STDERR "TA: \"$tempavail\"\n" if ($localDebug);
$parserState->{kr_c_function} = 1;
$parserState->{kr_c_name} = $parserState->{sodname};
$parsedParamParse = 1;
print STDERR "parsedParamParse -> 1\n" if ($parmDebug);
}
}
}
}
$lastchar = $part;
if ($part =~ /\w/o || $part eq "::") {
if ($parserState->{callbackNamePending} == 1) {
if (!($part eq $structname || $part eq $enumname || $part eq $unionname || $part eq $typedefname)) {
# we've seen the initial type. The name of
# the callback is after the next open
# parenthesis.
print STDERR "callbackNamePending -> 2\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 2;
}
} elsif ($parserState->{callbackNamePending} == 3) {
print STDERR "callbackNamePending -> 4\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 4;
$parserState->{callbackName} = $part;
$parserState->{name} = "";
$parserState->{sodclass} = "";
$parserState->{cbsodname} = $parserState->{sodname};
$parserState->{sodname} = "";
} elsif ($parserState->{callbackNamePending} == 4) {
if ($part eq "::") {
print STDERR "callbackNamePending -> 5\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 5;
$parserState->{callbackName} .= $part;
} elsif ($part !~ /\s/o) {
print STDERR "callbackNamePending -> 0\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 0;
}
} elsif ($parserState->{callbackNamePending} == 5) {
if ($part !~ /\s/o) {
print STDERR "callbackNamePending -> 4\n" if ($localDebug || $cbnDebug);
if ($part !~ /\*/ && $part !~ /\^/) {
$parserState->{callbackNamePending} = 4;
}
$parserState->{callbackName} .= $part;
}
}
if ($parserState->{namePending} == 2) {
$parserState->{namePending} = 1;
print STDERR "namePending -> 1 [4]\n" if ($parseDebug);
if (!(scalar(@braceStack)-$parserState->{initbsCount}) && ($parserState->{simpleTypedef} == 2)) {
print STDERR "bracePending -> 1\n" if ($localDebug);
$parserState->{bracePending} = 1;
}
} elsif ($parserState->{namePending}) {
if ($parserState->{name} eq "") { $parserState->{name} = $part; }
$parserState->{namePending} = 0;
print STDERR "namePending -> 0 [5]\n" if ($parseDebug);
} elsif ($parserState->{bracePending} == 1) {
if ($part eq "::") {
# struct foo::bar ....
# "foo::bar" is the name of
# the struct and should not
# trigger this (though we might
# trigger it on the following
# word.
print STDERR "bracePending -> 2 [classmember]\n" if ($localDebug);
$parserState->{bracePending} = 2;
} else {
# Word token when brace pending. It's
# a variable.
print STDERR "IT'S A VARIABLE! NAME WAS \"$part\".\n" if ($localDebug);
print STDERR "Word token before brace. Setting sodname to ".$parserState->{lastsymbol}."\n" if ($localDebug || $sodDebug);
$parserState->{sodname} = $part;
# $parserState->{sodtype} = $parserState->{returntype}; # . " " . $parserState->{name};
$parserState->{sodtype} = "$declaration$curline";
$parserState->{sodclass} = "constant";
$parserState->{frozensodname} = $part;
print STDERR "bracePending -> 0 [word]\n" if ($localDebug);
$parserState->{bracePending} = 0;
}
} elsif ($parserState->{bracePending} == 2) {
$parserState->{bracePending}--;
}
} # end if ($part =~ /\w/o)
if ($part !~ /[,;\[\]]/o && !$parserState->{inBrackets}) {
my $opttilde = "";
if ($parserState->{seenTilde}) { $opttilde = "~"; }
print STDERR "CHECKPOINT: INTEMPLATE IS ".$parserState->{inTemplate}." SOD IS ".$parserState->{startOfDec}."\n" if ($localDebug || $sodDebug);
if ($parserState->{startOfDec} == 1) { # @@@ FIXME DAG. This should not set sodname, but otherwise, we're losing classes!!!
if (!$parserState->{inTemplate}) {
print STDERR "Setting sodname (maybe type) to \"$part\"\n" if ($sodDebug);
$parserState->{sodname} = $opttilde.$part;
if ($part =~ /\w/o) {
$parserState->{startOfDec}++;
}
} else {
print STDERR "Not adjusting startOfDec or sodname because in template.\n" if ($localDebug || $sodDebug);
}
} elsif ($parserState->{startOfDec} == 2) {
if ($part =~ /\w/o && !$parserState->{inTemplate}) {
$parserState->{preTemplateSymbol} = "";
}
if (!$parserState->{inTemplate}) {
if ($parserState->{inOperator} == 1) {
$parserState->{sodname} .= $part;
} else {
if (length($parserState->{sodname})) {
$parserState->{sodtype} .= " $parserState->{sodname}";
}
$parserState->{sodname} = $opttilde.$part;
}
print STDERR "sodname set to $part\n" if ($sodDebug);
} else {
print STDERR "Not adjusting startOfDec or sodname because in template.\n" if ($localDebug || $sodDebug);
}
} else {
$parserState->{startOfDec} = 0;
}
} elsif ($part eq "[") { # if ($part !~ /[;\[\]]/o)
$parserState->{inBrackets} += 1;
print STDERR "inBrackets -> $parserState->{inBrackets}\n" if ($sodDebug);
} elsif ($part eq "]") {
$parserState->{inBrackets} -= 1;
print STDERR "inBrackets -> $parserState->{inBrackets}\n" if ($sodDebug);
} # end if ($part !~ /[;\[\]]/o)
if (!($part eq $eoc)) {
print STDERR "SETTING LS ($part)\n" if ($parseDebug);
if ($parserState->{typestring} eq "") { $parserState->{typestring} = $part; }
if ($parserState->{lastsymbol} =~ /\,\s*$/o) {
$parserState->{lastsymbol} .= $part;
} elsif ($parserState->{inTypedef} && !(scalar(@braceStack)-$parserState->{initbsCount}) && $part =~ /,/) {
$parserState->{lastsymbol} .= $part;
} elsif ($part =~ /^\s*\;\s*$/o) {
$parserState->{lastsymbol} .= $part;
} elsif (length($part)) {
# warn("replacing lastsymbol with \"$part\"\n");
$parserState->{lastsymbol} = $part;
}
} # end if (!($part eq $eoc))
} # end if (length($part) && !($parserState->{inComment} || $parserState->{inInlineComment}))
}
} # end if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}))
} # end SWITCH default case
} # end SWITCH
if ($parserState->{seenBraces}) {
# print "SEENBRACES. TP: $treepart PT: $part\n";
if ($treepart) {
$parserState->{functionContents} .= $treepart;
} else {
$parserState->{functionContents} .= $part;
}
# print "SEENBRACES. FC: ".$parserState->{functionContents}."\n";
}
if ($part !~ /\\/o) {
if (!($parserState->{inMacro} || $parserState->{inMacroLine}) || $part !~ /\s/) {
$parserState->resetBackslash();
}
}
if (length($part)) { $lasttoken = $part; }
if (length($part) && $inRegexpTrailer) { --$inRegexpTrailer; }
if ($postPossNL) { --$postPossNL; }
if (($parserState->{simpleTypedef} == 1) && ($part ne $typedefname) &&
!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} ||
$inRegexp)) {
# print STDERR "NP: $parserState->{namePending} PTP: $parserState->{posstypesPending} PART: $part\n";
$parserState->{simpleTDcontents} .= $part;
}
my $ignoretoken = ignore($part, $ignoreref, $perheaderignoreref);
my $hide = ( $hideTokenAndMaybeContents ||
( $ignoretoken &&
!( $parserState->{inString} || $parserState->{inComment} ||
$parserState->{inInlineComment} || $parserState->{inChar}
)
)
);
print STDERR "TPONL: $treePopOnNewLine TPTWO: ".$parserState->{treePopTwo}."\n" if ($tsDebug);
print STDERR "TN: $treeNest TS: $treeSkip nTS: ".scalar(@treeStack)."\n" if ($tsDebug || $parserStateInsertDebug);
print STDERR "sethollow: $sethollow\n" if ($parserStateInsertDebug);
if (!$treeSkip) {
if (!$parserState->{seenBraces}) { # TREEDONE
if ($treeNest != 2) {
# If we really want to skip and nest, set treeNest to 2.
if (length($treepart)) {
if ((($parserState->{inComment} == 1) || ($parserState->{inInlineComment} == 1)) && $treepart !~ /[\r\n!]/) {
$treeCur->token($treeCur->token() . $treepart);
# print STDERR "SHORT\n";
} else {
$treeCur = $treeCur->addSibling($treepart, $hide);
}
$treepart = "";
} else {
if ((($parserState->{inComment} == 1) || ($parserState->{inInlineComment} == 1)) && $treepart !~ /[\r\n!]/) {
$treeCur->token($treeCur->token() . $part);
# print STDERR "SHORT\n";
} else {
$treeCur = $treeCur->addSibling($part, $hide);
}
}
bless($treeCur, "HeaderDoc::ParseTree");
}
# print STDERR "TC IS $treeCur\n";
# $treeCur = %{$treeCur};
if ($treeNest) {
if ($sethollow) {
print STDERR "WILL INSERT STATE $parserState (SETHOLLOW) at ".$treeCur->token()."\n" if ($parserStackDebug);
# $parserState->{hollow} = $treeCur;
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$sethollow = 0;
}
print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug);
push(@treeStack, $treeCur);
$treeCur = $treeCur->addChild("", 0);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
}
if ($parserState->{inComment} > 1) { $parserState->{inComment}--; }
if ($parserState->{inInlineComment} > 1) { $parserState->{inInlineComment}--; }
if (($parserState->{inComment} == 1) && $treepart eq "!") {
$parserState->{inComment} = 3;
}
if (($parserState->{inInlineComment} == 1) && $treepart eq "!") {
$parserState->{inInlineComment} = 3;
}
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [19]\n"; }
if (!$parserState->{freezereturn} && $parserState->{hollow}) {
# print STDERR "WARNING: RETURN TYPE CHANGE[A]".$parserState->{returntype}." CHANGED TO $declaration$curline.\n";
$parserState->{returntype} = "$declaration$curline";
} elsif (!$parserState->{freezereturn} && !$parserState->{hollow}) {
# print STDERR "WARNING: RETURN TYPE CHANGE[B]".$parserState->{returntype}." CHANGED TO $curline.\n";
$parserState->{returntype} = "$curline";
$declaration = "";
# } else {
# print STDERR "WARNING: LEAVING RETURN TYPE ALONE: ".$parserState->{returntype}." NOT CHANGED TO $curline.\n";
}
# From here down is... magic. This is where we figure out how
# to handle parsed parameters, K&R C types, and in general,
# determine whether we've received a complete declaration or not.
#
# About 90% of this is legacy code to handle proper spacing.
# Those bits got effectively replaced by the parseTree class.
# The only way you ever see this output is if you don't have
# any styles defined in your config file.
if (($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) ||
!$ignoretoken) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) &&
!$ppSkipOneToken) {
if ($parsedParamParse == 1) {
$parsedParam .= $part;
} elsif ($parsedParamParse == 2) {
$parsedParamParse = 1;
print STDERR "parsedParamParse -> 1\n" if ($parmDebug);
}
}
if ($ppSkipOneToken) {
$hollowskip = $ppSkipOneToken;
print STDERR "hollowskip -> $ppSkipOneToken (ppSkipOneToken)\n" if ($parserStateInsertDebug);
}
$ppSkipOneToken = 0;
print STDERR "MIDPOINT CL: $curline\nDEC:$declaration\nSCR: \"$scratch\"\n" if ($localDebug);
if (!$parserState->{seenBraces}) {
# Add to current line (but don't put inline function/macro
# declarations in.
if ($parserState->{inString}) {
$curstring .= $part;
} else {
if (length($curstring)) {
if (length($curline) + length($curstring) >
$HeaderDoc::maxDecLen) {
$scratch = nspaces($prespace);
# Was != /\n/ which is clearly
# wrong. Suspect the next line
# if we start losing leading spaces
# where we shouldn't (or don't where
# we should). Also was just /g.
if ($curline !~ /^\s*\n/so) { $curline =~ s/^\s*//sgo; }
# NEWLINE INSERT
print STDERR "CURLINE CLEAR [1]\n" if ($localDebug);
$declaration .= "$scratch$curline\n";
$curline = "";
$prespace += $prespaceadjust;
$prespaceadjust = 0;
$prespaceadjust -= 4;
$prespace += 4;
} else {
# no wrap, so maybe add a space.
if ($lastchar =~ /\=$/o) {
$curline .= " ";
}
}
$curline .= $curstring;
$curstring = "";
}
if ((length($curline) + length($part) > $HeaderDoc::maxDecLen)) {
$scratch = nspaces($prespace);
# Was != /\n/ which is clearly
# wrong. Suspect the next line
# if we start losing leading spaces
# where we shouldn't (or don't where
# we should). Also was /g instead of /sg.
if ($curline !~ /^\s*\n/so) { $curline =~ s/^\s*//sgo; }
# NEWLINE INSERT
$declaration .= "$scratch$curline\n";
print STDERR "CURLINE CLEAR [2]\n" if ($localDebug);
$curline = "";
$prespace += $prespaceadjust;
$prespaceadjust = 0;
$prespaceadjust -= 4;
$prespace += 4;
}
if (length($curline) || $part ne " ") {
# Add it to curline unless it's a space that
# has inadvertently been wrapped to the
# start of a line.
$curline .= $part;
}
}
if (peek(\@braceStack) ne "<") {
if ($part =~ /\n/o || ($part =~ /[\(;,]/o && $nextpart !~ /\n/o &&
!$parserState->{occmethod}) ||
($part =~ /[:;.]/o && $nextpart !~ /\n/o &&
$parserState->{occmethod})) {
if ($curline !~ /\n/o && !($parserState->{inMacro} || ($pascal && (scalar(@braceStack)-$parserState->{initbsCount})) || $parserState->{inInlineComment} || $parserState->{inComment} || $parserState->{inString})) {
# NEWLINE INSERT
$curline .= "\n";
}
# Add the current line to the declaration.
$scratch = nspaces($prespace);
if ($curline !~ /\n/o) { $curline =~ s/^\s*//go; }
if ($declaration !~ /\n\s*$/o) {
$scratch = " ";
if ($localDebug) {
my $zDec = $declaration;
$zDec = s/ /z/sg;
$zDec = s/\t/Z/sg;
print STDERR "ZEROSCRATCH\n";
print STDERR "zDec: \"$zDec\"\n";
}
}
$declaration .= "$scratch$curline";
print STDERR "CURLINE CLEAR [3]\n" if ($localDebug);
$curline = "";
# $curline = nspaces($prespace);
print STDERR "PS: $prespace -> " . $prespace + $prespaceadjust . "\n" if ($localDebug);
$prespace += $prespaceadjust;
$prespaceadjust = 0;
} elsif ($part =~ /[\(;,]/o && $nextpart !~ /\n/o &&
($parserState->{occmethod} == 1)) {
print STDERR "SPC\n" if ($localDebug);
$curline .= " "; $occspace = 1;
} else {
print STDERR "NOSPC: $part:$nextpart:$parserState->{occmethod}\n" if ($localDebug);
}
}
}
if ($parserState->{temponlyComments}) {
# print STDERR "GOT TOC: ".$parserState->{temponlyComments}."\n";
$parserState->{onlyComments} = $parserState->{temponlyComments};
$parserState->{temponlyComments} = undef;
}
print STDERR "CURLINE IS \"$curline\".\n" if ($localDebug);
my $bsCount = scalar(@braceStack);
print STDERR "ENDTEST: $bsCount \"$parserState->{lastsymbol}\"\n" if ($localDebug);
print STDERR "KRC: $parserState->{kr_c_function} SB: $parserState->{seenBraces}\n" if ($localDebug);
if (!($bsCount - $parserState->{initbsCount}) && $parserState->{lastsymbol} =~ /;\s*$/o) {
# print STDERR "DPA\n";
if ((!$parserState->{kr_c_function} || $parserState->{seenBraces}) && !$parserState->{inMacro}) {
# print STDERR "DPB\n";
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [3]\n" if ($localDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[SEMI-1]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} elsif ($parserState->{classtype} && length($parserState->{classtype})) {
warn "Couldn't insert info into parse tree[3class].\n" if ($localDebug);
} else {
warn "Couldn't insert info into parse tree[3].\n";
print STDERR "Printing tree.\n";
$parserState->print();
$treeTop->dbprint();
}
print STDERR "parserState: Created parser state[2].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "NEWRETURNTYPE: $parserState->{returntype}\n" if ($localDebug);
print STDERR "CURLINE CLEAR[PRS2]\n" if ($localDebug);
$curline = "";
}
}
} else {
print STDERR "bsCount: $bsCount - $parserState->{initbsCount}, ls: $parserState->{lastsymbol}\n" if ($localDebug);
pbs(@braceStack);
}
if (!($bsCount - $parserState->{initbsCount}) && $parserState->{seenBraces} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator}) &&
($nextpart ne ";")) {
# Function declarations end at the close curly brace.
# No ';' necessary (though we'll eat it if it's there.
if ($parserState->{treePopTwo}) {
# Fix nesting.
# print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n";
while ($parserState->{treePopTwo}--) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [13]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
$treeCur = $treeCur->addSibling(";", 0);
$parserState->{lastTreeNode} = $treeCur;
$parserState->{treePopTwo} = 0;
}
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [4]\n" if ($localDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[SEMI-2]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[4].\n";
}
print STDERR "parserState: Created parser state[3].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "CURLINE CLEAR[PRS3]\n" if ($localDebug);
$curline = "";
}
}
print STDERR "INMACRO: ".$parserState->{inMacro}."\n" if ($localDebug || $cppDebug || $cppDebug);
# $parserState->{lastsymbol} ne "\\"
print STDERR "IM: ".$parserState->{inMacro}." IQ: ".$parserState->isQuoted($lang, $sublang)."\n" if ($localDebug);
if (($parserState->{inMacro} == 3 && !$parserState->isQuoted($lang, $sublang)) || $parserState->{inMacro} == 4) {
print STDERR "CHECKPART AGAINST NEWLINE\n" if ($localDebug || $cppDebug);
if ($part =~ /[\n\r]/o && !$parserState->{inComment}) {
print STDERR "MLS: $parserState->{lastsymbol}\n" if ($macroDebug);
print STDERR "PARSER STACK CONTAINS ".scalar(@parserStack)." FRAMES\n" if ($cppDebug || $parserStackDebug);
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [5]\n" if ($localDebug || $liteDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
print STDERR "NOT setting continue to 0 for macro: parser stack nonempty\n" if ($liteDebug);
print STDERR "DONE WITH MACRO. HANDLING.\n" if ($localDebug || $parseDebug);
if ($parserState->{inMacro} == 3) {
if (!$HeaderDoc::skipNextPDefine) {
cpp_add($parserState->{hollow});
} else {
cpp_add($parserState->{hollow}, 1);
$HeaderDoc::skipNextPDefine = 0;
}
}
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[5].\n";
}
print STDERR "parserState: Created parser state[4].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "CURLINE CLEAR[PRS4]\n" if ($localDebug);
$curline = "";
}
}
} elsif ($parserState->{inMacro} == 2) {
my $linenum = $inputCounter + $fileoffset;
warn "$filename:$linenum: warning: Declaration starts with # but is not preprocessor macro\n";
warn "PART: $part\n";
} elsif ($parserState->{inMacro} == 3 && $parserState->isQuoted($lang, $sublang)) {
# $parserState->{lastsymbol} eq "\\"
print STDERR "TAIL BACKSLASH ($continue)\n" if ($localDebug || $macroDebug);
}
if ($parserState->{valuepending} == 2) {
# skip the "=" part;
$parserState->{value} .= $part;
} elsif ($parserState->{valuepending}) {
$parserState->{valuepending} = 2;
print STDERR "valuepending -> 2\n" if ($valueDebug);
}
} # end if "we're not ignoring this token"
print STDERR "OOGABOOGA\n" if ($parserStackDebug);
if ($pushParserStateAfterToken == 1) {
print STDERR "parserState pushed onto stack[token]\n" if ($parserStackDebug);
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterToken = 0;
$pushParserStateAtBrace = 0;
} elsif ($pushParserStateAfterWordToken == 1) {
if ($part =~ /\w/) {
print STDERR "parserState pushed onto stack[word]\n" if ($parserStackDebug);
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterWordToken = 0;
}
} elsif ($pushParserStateAfterWordToken) {
print STDERR "PPSAFTERWT CHANGED $pushParserStateAfterWordToken -> " if ($parserStackDebug);
$pushParserStateAfterWordToken--;
print STDERR "$pushParserStateAfterWordToken\n" if ($parserStackDebug);
} elsif ($pushParserStateAtBrace) {
print STDERR "PPSatBrace?\n" if ($parserStackDebug);
if (casecmp($part, $lbrace, $case_sensitive)) {
$parserState->{ISFORWARDDECLARATION} = 0;
print STDERR "parserState pushed onto stack[brace]\n" if ($parserStackDebug);
# if ($pushParserStateAtBrace == 2) {
# print STDERR "NOINSERT parserState: $parserState\n" if ($parserStackDebug);
# $parserState->{hollow} = undef;
# $parserState->{noInsert} = 1;
# }
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
} elsif ($pushParserStateAtBrace) {
if ($part =~ /\;/) {
# It's a class instance declaration. Whoops.
$pushParserStateAtBrace = 0;
$parserState->{inClass} = 0;
print STDERR "inClass -> 0 [10]\n" if ($classDebug);
}
# if ($part =~ /\S/) { $pushParserStateAtBrace = 0; }
}
if (!$parserState->{hollow}) {
my $tok = $part; # $treeCur->token();
print STDERR "parserState: NOT HOLLOW [1]\n" if ($parserStackDebug);
print STDERR "IS: $parserState->{inString}\nICom: $parserState->{inComment}\nISLC: $parserState->{inInlineComment}\nIChar: $parserState->{inChar}\nSkipToken: $parserState->{skiptoken}\nHollowSkip: $hollowskip\n" if ($parserStackDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
print STDERR "parserState: NOT STRING/CHAR/COMMENT\n" if ($parserStackDebug);
if ($tok =~ /\S/) {
print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug);
print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug);
if (!casecmp($tok, $rbrace, $case_sensitive) && $part !~ /\)/) {
# $parserState->{hollow} = $treeCur;
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$HeaderDoc::curParserState = $parserState;
print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-1) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug);
}
}
}
$hollowskip = 0;
print STDERR "hollowskip -> 0 (NOTHOLLOW - 1)\n" if ($parserStateInsertDebug);
$parserState->{skiptoken} = 0;
}
} else {
if (!$parserState->{hollow}) {
my $tok = $part; # $treeCur->token();
print STDERR "parserState: NOT HOLLOW [2]\n" if ($parserStackDebug);
print STDERR "IS: $parserState->{inString}\nICom: $parserState->{inComment}\nISLC: $parserState->{inInlineComment}\nIChar: $parserState->{inChar}\nSkipToken: $parserState->{skiptoken}\nHollowSkip: $hollowskip\n" if ($parserStackDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
print STDERR "parserState: NOT STRING/CHAR/COMMENT\n" if ($parserStackDebug);
if ($tok =~ /\S/) {
print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug);
print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug);
if (!casecmp($tok, $rbrace, $case_sensitive) && $part !~ /\)/) {
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$HeaderDoc::curParserState = $parserState;
print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-2) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug);
}
}
}
$hollowskip = 0;
print STDERR "hollowskip -> 0 (NOTHOLLOW - 2)\n" if ($parserStateInsertDebug);
$parserState->{skiptoken} = 0;
}
}
if ($part =~ /\w+/) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
if ($parserState->{occparmlabelfound} == -2) {
if (!($parserState->{initbsCount} - scalar(@braceStack) )) { # Skip types
$parserState->{occparmlabelfound} = 0; # Next token is the label for the next parameter.
if ($HeaderDoc::useParmNameForUnlabeledParms) {
$parserState->{occmethodname} .= "$part:";
} else {
$parserState->{occmethodname} .= ":";
}
if ($occMethodNameDebug) {
print STDERR "OCC parameter name substituted; OCC method name now ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\", part was \"".$part."\").\n";
}
}
} else {
if (!($parserState->{initbsCount} - scalar(@braceStack) )) { # Skip types
$parserState->{occparmlabelfound}++;
if ($occMethodNameDebug && ($parserState->{occparmlabelfound} > 0)) {
print STDERR "OCC possible label: \"$part\".\n";
}
}
}
}
}
if (length($part) && $part =~ /\S/o) { $lastnspart = $part; }
if ($parserState->{seenTilde} && length($part) && $part !~ /\s/o) { $parserState->{seenTilde}--; }
$part = $nextpart;
} # end foreach (parts of the current line)
} # end while (continue && ...)
print STDERR "RETURNING DECLARATION\n" if ($localDebug);
# Format and insert curline into the declaration. This handles the
# trailing line. (Deprecated.)
if ($curline !~ /\n/) { $curline =~ s/^\s*//go; }
if ($curline =~ /\S/o) {
$scratch = nspaces($prespace);
$declaration .= "$scratch$curline\n";
}
print STDERR "($parserState->{typestring}, $parserState->{basetype})\n" if ($localDebug || $listDebug);
print STDERR "LS: $parserState->{lastsymbol}\n" if ($localDebug);
$parserState->{lastTreeNode} = $treeCur;
$parserState->{inputCounter} = $inputCounter;
print STDERR "PARSERSTATE: $parserState\n" if ($localDebug);
if ($parserState->{inMacro} == 3) {
if (!$HeaderDoc::skipNextPDefine) {
cpp_add($treeTop);
} else {
cpp_add($treeTop, 1);
$HeaderDoc::skipNextPDefine = 0;
}
}
print STDERR "LEFTBPMAIN\n" if ($localDebug || $hangDebug);
if ($argparse && $apwarn) {
print STDERR "end argparse\n";
}
# Return the top parser context even if we got interrupted.
my $tempParserState = pop(@parserStack);
while ($tempParserState) {
$parserState = $tempParserState;
$tempParserState = pop(@parserStack);
}
$HeaderDoc::module = $parserState->{MODULE};
if ($localDebug || $apDebug || $liteDebug || $parseDebug) {
print STDERR "LEAVING BLOCKPARSE\n";
}
if (0) {
print STDERR "Returning the following parse tree:\n";
$treeTop->dbprint();
print STDERR "End of parse tree.\n";
}
# print "FC: ".$parserState->{functionContents}."\n";
return blockParseReturnState($parserState, $treeTop, $argparse, $declaration, $inPrivateParamTypes, $publicDeclaration, $lastACS, $retDebug, $fileoffset, 0, $definename, $inputCounter);
}
$1202|# /*! The blockParse function is the core of HeaderDoc's parse engine.
# @param filename the filename being parser.
# @param fileoffset the line number where the current block begins. The line number printed is (fileoffset + inputCounter).
# @param inputLinesRef a reference to an array of code lines.
# @param inputCounter the offset within the array. This is added to fileoffset when printing the line number.
# @param argparse disable warnings when parsing arguments to avoid seeing them twice.
# @param ignoreref a reference to a hash of tokens to ignore on all headers.
# @param perheaderignoreref a reference to a hash of tokens, generated from \@ignore headerdoc comments.
# @param perheaderignorefuncmacrosref a reference to a hash of tokens, generated from \@ignorefunmacro headerdoc comments.
# @param keywordhashref a reference to a hash of keywords.
# @param case_sensitive boolean: controls whether keywords should be processed in a case-sensitive fashion.
# @result Returns ($inputCounter, $declaration, $typelist, $namelist, $posstypes, $value, \@pplStack, $returntype, $privateDeclaration, $treeTop, $simpleTDcontents, $availability).
# */
$0|$496969|-=: TOP LEVEL COMMENT PARSE VALUES :=-
inHeader: 0
inClass: 0
inInterface: 0
inCPPHeader: 0
inOCCHeader: 0
inPerlScript: 0
inShellScript: 0
inPHPScript: 0
inJavaSource: 0
inFunctionGroup: 0
inGroup: 0
inFunction: 0
inPDefine: 0
inTypedef: 0
inUnion: 0
inStruct: 0
inConstant: 0
inVar: 0
inEnum: 0
inMethod: 0
inAvailabilityMacro: 0
inUnknown: 1
classType: unknown
inputCounter: 0
blockOffset: 0
fullpath: /test_suite_bogus_path/Perl_function_2.test
-=: BLOCKPARSE PARSER STATE KEYS :=-
$parserState->{FULLPATH} => /test_suite_bogus_path/Perl_function_2.test
$parserState->{NEXTTOKENNOCPP} => 0
$parserState->{availability} =>
$parserState->{backslashcount} => 0
$parserState->{basetype} =>
$parserState->{bracePending} => 0
$parserState->{callbackIsTypedef} => 0
$parserState->{callbackName} =>
$parserState->{callbackNamePending} => -1
$parserState->{categoryClass} =>
$parserState->{classtype} =>
$parserState->{curvarstars} => *********************************************************************************
$parserState->{freezeStack} => ARRAY(OBJID)
$parserState->{freezereturn} => 1
$parserState->{frozensodname} => blockParse
$parserState->{functionContents} => {
my $filename = shift;
my $fileoffset = shift;
my $inputLinesRef = shift;
my $inputCounter = shift;
my $argparse = shift;
my $ignoreref = shift;
my $perheaderignoreref = shift;
my $perheaderignorefuncmacrosref = shift;
my $keywordhashref = shift;
my $case_sensitive = shift;
my $apwarn = 0;
if ($argparse && $apwarn) {
print STDERR "argparse\n";
}
# Initialize stuff
my @inputLines = @{$inputLinesRef};
my $declaration = "";
my $publicDeclaration = "";
# $HeaderDoc::fileDebug = 1;
# Debugging switches
my $retDebug = 0;
my $localDebug = 0 || $HeaderDoc::fileDebug;
my $operatorDebug = 0;
my $listDebug = 0;
my $parseDebug = 0 || $HeaderDoc::fileDebug;
my $sodDebug = 0 || $HeaderDoc::fileDebug;
my $valueDebug = 0;
my $parmDebug = 0;
my $cbnDebug = 0;
my $macroDebug = 0;
my $apDebug = 0;
my $tsDebug = 0;
my $treeDebug = 0;
my $ilcDebug = 0;
my $regexpDebug = 0;
my $parserStackDebug = 0 || $HeaderDoc::fileDebug;
my $hangDebug = 0;
my $offsetDebug = 0;
my $classDebug = 0; # prints changes to inClass, etc.
my $gccAttributeDebug = 0; # also for availability macro argument handling.
my $occMethodNameDebug = 0;
my $moduleDebug = 0; # prints changes to INMODULE
my $liteDebug = 0 || $HeaderDoc::fileDebug; # Just prints the tokens.
my $parserStateInsertDebug = 0;
$cppDebug = $cppDebugDefault || $HeaderDoc::fileDebug;
# State variables (part 1 of 3)
# my $typestring = "";
my $continue = 1; # set low when we're done.
my $parsedParamParse = 0; # set high when current token is part of param.
# my @parsedParamList = (); # currently active parsed parameter list.
# my @pplStack = (); # stack of parsed parameter lists. Used to handle
# fields and parameters in nested callbacks/structs.
# my @freezeStack = (); # copy of pplStack when frozen.
# my $frozensodname = "";
# my $stackFrozen = 0; # set to prevent fake parsed params with inline funcs
my $lang = $HeaderDoc::lang;
my $perl_or_shell = 0;
my $sublang = $HeaderDoc::sublang;
my $callback_typedef_and_name_on_one_line = 1; # deprecated
# my $returntype = "";
# my $freezereturn = 0; # set to prevent fake return types with inline funcs
my $treeNest = 0; # 1: nest future content under this node.
# 2: used if you want to nest, but have already
# inserted the contents of the node.
my $sethollow = 0;
my $setNoInsert = 0;
my $treepart = ""; # There are some cases where you want to drop a token
# for formatting, but keep it in the parse tree.
# In that case, treepart contains the original token,
# while part generally contains a space.
# my $availability = ""; # holds availability string if we find an av macro.
# my $seenTilde = 0; # set to 1 for C++ destructor.
if ($argparse && $tsDebug) { $tsDebug = 0; }
# Configure the parse tree output.
my $treeTop = HeaderDoc::ParseTree->new(); # top of parse tree.
my $treeCur = $treeTop; # current position in parse tree
my $treeSkip = 0; # set to 1 if "part" should be dropped in tree.
# my $treePopTwo = 0; # set to 1 for tokens that nest, but have no
# explicit ending token ([+-:]).
my $treePopOnNewLine = 0; # set to 1 for single-line comments, macros.
my @treeStack = (); # stack of parse trees. Used for popping
# our way up the tree to simplify tree structure.
# Leak a node here so that every real node has a parent.
$treeCur = $treeCur->addChild("");
$treeTop = $treeCur;
my $lastACS = "";
# The argparse switch is a trigger....
if ($argparse && $apDebug) {
$localDebug = 1;
$retDebug = 1;
$listDebug = 1;
$parseDebug = 1;
$sodDebug = 1;
$valueDebug = 1;
$parmDebug = 1;
$cbnDebug = 1;
$macroDebug = 1;
# $apDebug = 1;
$tsDebug = 1;
$treeDebug = 1;
$ilcDebug = 1;
$regexpDebug = 1;
}
my $spaceDebug = 0;
if ($localDebug || $apDebug || $liteDebug || $parseDebug) {
print STDERR "ENTERED BLOCKPARSE\n";
}
my $disable_cpp = 0;
if ($argparse && ($localDebug || $apDebug || $liteDebug)) {
print STDERR "ARGPARSE MODE!\n";
print STDERR "IPC: $inputCounter\nNLINES: ".$#inputLines."\n";
cluck("Call backtrace\n");
}
print STDERR "INBP\n" if ($localDebug);
if ($argparse) {
# Avoid double-processing macro inclusions.
$disable_cpp = 1;
}
if ($lang ne "C" || $sublang eq "PHP") { # || $sublang eq "IDL")
$disable_cpp = 1;
}
print STDERR "INITIAL LANG: $lang INITIAL SUBLANG: $sublang\n" if ($localDebug);
# warn("in BlockParse\n");
# State variables (part 2 of 3)
my $parserState = HeaderDoc::ParserState->new();
# $parserState->{hollow} = $treeTop;
setHollowWithLineNumbers(\$parserState, $treeTop, $fileoffset, $inputCounter);
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = 0; # included for consistency....
my @parserStack = ();
# print STDERR "TEST: ";
# if (defined($parserState->{parsedParamList})) {
# print STDERR "defined\n"
# } else { print STDERR "undefined.\n"; }
# print STDERR "\n";
# my $inComment = 0;
# my $inInlineComment = 0;
# my $inString = 0;
# my $inChar = 0;
# my $inTemplate = 0;
my @braceStack = ();
# my $inOperator = 0;
my $inPrivateParamTypes = 0; # after a colon in a C++ function declaration.
# my $onlyComments = 1; # set to 0 to avoid switching to macro parse.
# mode after we have seen a code token.
# my $inMacro = 0;
# my $inMacroLine = 0; # for handling macros in middle of data types.
# my $seenMacroPart = 0; # used to control dropping of macro body.
# my $macroNoTrunc = 1; # used to avoid truncating body of macros
# that don't begin with parenthesis or brace.
# my $inBrackets = 0; # square brackets ([]).
my $inPType = 0; # in pascal types.
my $inRegexp = 0; # in perl regexp.
my $regexpNoInterpolate = 0; # Don't interpolate (e.g. tr)
my $inRegexpTrailer = 0; # in the cruft at the end of a regexp.
my $hollowskip = 0;
my $ppSkipOneToken = 0; # Comments are always dropped from parsed
# parameter lists. However, inComment goes
# to 0 on the end-of-comment character.
# This prevents the end-of-comment character
# itself from being added....
my $regexppattern = ""; # optional characters at start of regexp
my $singleregexppattern = ""; # members of regexppattern that take only
# one argument instead of two.
my $regexpcharpattern = ""; # legal chars to start a regexp.
my @regexpStack = (); # stack of RE tokens (since some can nest).
# Get the parse tokens from Utilities.pm.
my ($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
$soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
$enumname,
$typedefname, $varname, $constname, $structisbrace, $macronameref,
$classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
$requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
my $macrore_pound = macroRegexpFromList($macronameref, 1);
my $macrore_nopound = macroRegexpFromList($macronameref, 2);
# print STDERR "LANG: $lang SUBLANG: $sublang";
print STDERR "MACRORE_POUND: \"$macrore_pound\"\n" if ($localDebug || $parseDebug);
print STDERR "MACRORE_NOPOUND: \"$macrore_nopound\"\n" if ($localDebug || $parseDebug);
# print STDERR "INITIAL PROPNAME $propname\n";
if ($parseDebug) {
print STDERR "SOT: $sotemplate EOF: $eotemplate OP: $operator SOC: $soc EOC: $eoc ILC: $ilc ILC_B: $ilc_b\n";
print STDERR "SOFUNC: $sofunction SOPROC: $soprocedure SOPREPROC: $sopreproc LBRACE: $lbrace RBRACE: $rbrace\n";
print STDERR "UNION: $unionname STRUCT: $structname TYPEDEF: $typedefname VAR: $varname CONST: $constname\n";
print STDERR "STRUCTISBRACE: $structisbrace MACRONAMEREF: $macronameref CLASSRE: $classregexp\n";
print STDERR "CLASSBRACERE: $classbraceregexp CLASSCLOSEBRACERE: $classclosebraceregexp ACCESSRE: $accessregexp\n";
print STDERR "MODULERE: $moduleregexp\n";
}
# Set up regexp patterns for perl, variable for perl or shell.
if ($lang eq "perl" || $lang eq "shell") {
$perl_or_shell = 1;
if ($lang eq "perl") {
$regexpcharpattern = '\\{|\\#\\(|\\/|\\\'|\\"|\\<|\\[|\\`';
# } vi bug workaround for previous line
$regexppattern = "qq|qr|qx|qw|q|m|s|tr|y";
$singleregexppattern = "qq|qr|qx|qw|q|m";
}
}
my $pascal = 0;
if ($lang eq "pascal") { $pascal = 1; }
# State variables (part 3 of 3)
# my $lastsymbol = ""; # Name of the last token, wiped by braces,
# parens, etc. This is not what you are
# looking for. It is used mostly for
# handling names of typedefs.
# my $name = ""; # Name of a basic data type.
# my $callbackNamePending = 0; # 1 if callback name could be here. This is
# only used for typedef'ed callbacks. All
# other callbacks get handled by the parameter
# parsing code. (If we get a second set of
# parsed parameters for a function, the first
# one becomes the callback name.)
# my $callbackName = ""; # Name of this callback.
# my $callbackIsTypedef = 0; # 1 if the callback is wrapped in a typedef---
# sets priority order of type matching (up
# one level in headerdoc2HTML.pl).
# my $namePending = 0; # 1 if name of func/variable is coming up.
# my $basetype = ""; # The main name for this data type.
# my $posstypes = ""; # List of type names for this data type.
# my $posstypesPending = 1; # If this token could be one of the
# type names of a typedef/struct/union/*
# declaration, this should be 1.
# my $sodtype = ""; # 'start of declaration' type.
# my $sodname = ""; # 'start of declaration' name.
# my $sodclass = ""; # 'start of declaration' "class". These
# bits allow us keep track of functions and
# callbacks, mostly, but not the name of a
# callback.
# my $simpleTypedef = 0; # High if it's a typedef w/o braces.
# my $simpleTDcontents = ""; # Guts of a one-line typedef. Don't ask.
# my $seenBraces = 0; # Goes high after initial brace for inline
# functions and macros -only-. We
# essentially stop parsing at this point.
# my $kr_c_function = 0; # Goes high if we see a K&R C declaration.
# my $kr_c_name = ""; # The name of a K&R function (which would
# otherwise get lost).
my $lastchar = ""; # Ends with the last token, but may be longer.
my $lastnspart = ""; # The last non-whitespace token.
my $lasttoken = ""; # The last token seen (though [\n\r] may be
# replaced by a space in some cases.
# my $startOfDec = 1; # Are we at the start of a declaration?
my $prespace = 0; # Used for indentation (deprecated).
my $prespaceadjust = 0; # Indentation is now handled by the parse
# tree (colorizer) code.
my $scratch = ""; # Scratch space.
my $curline = ""; # The current line. This is pushed onto
# the declaration at a newline and when we
# enter/leave certain constructs. This is
# deprecated in favor of the parse tree.
my $curstring = ""; # The string we're currently processing.
my $continuation = 0; # An obscure spacing workaround. Deprecated.
my $forcenobreak = 0; # An obscure spacing workaround. Deprecated.
# my $occmethod = 0; # 1 if we're in an ObjC method.
my $occspace = 0; # An obscure spacing workaround. Deprecated.
# my $occmethodname = ""; # The name of an objective C method (which
# gets augmented to be this:that:theother).
# my $preTemplateSymbol = ""; # The last symbol prior to the start of a
# C++ template. Used to determine whether
# the type returned should be a function or
# a function template.
# my $preEqualsSymbol = ""; # Used to get the name of a variable that
# is followed by an equals sign.
# my $valuepending = 0; # True if a value is pending, used to
# return the right value.
# my $value = ""; # The current value.
my $parsedParam = ""; # The current parameter being parsed.
my $postPossNL = 0; # Used to force certain newlines to be added
# to the parse tree (to end macros, etc.)
# my $categoryClass = "";
# my $classtype = "";
# my $inClass = 0;
my $pushParserStateAfterToken = 0;
my $pushParserStateAfterWordToken = 0;
my $pushParserStateAtBrace = 0;
my $occPushParserStateOnWordTokenAfterNext = 0;
$HeaderDoc::hidetokens = 0;
# Loop unti the end of file or until we've found a declaration,
# processing one line at a time.
my $nlines = $#inputLines;
my $incrementoffsetatnewline = 0;
print "INCOMING INPUTCOUNTER: $inputCounter\n" if ($HeaderDoc::inputCounterDebug);
while ($continue && ($inputCounter <= $nlines)) {
$HeaderDoc::CurLine = $inputCounter + $fileoffset;
my $line = $inputLines[$inputCounter++];
print STDERR "GOT LINE: $line\n" if (($localDebug && $apDebug) || $HeaderDoc::inputCounterDebug);
print STDERR "INCREMENTED INPUTCOUNTER [1]\n" if ($HeaderDoc::inputCounterDebug);
my @parts = ();
# $line =~ s/^\s*//go; # Don't strip leading spaces, please.
$line =~ s/\s*$//go;
# $scratch = nspaces($prespace);
# $line = "$scratch$line\n";
# $curline .= $scratch;
$line .= "\n";
if ($lang eq "C" && $sublang eq "IDL") {
if ($line =~ /cpp_quote\s*\(\s*\"(.*)\"\s*\)\s*$/) {
print "CHANGED LINE FROM \"$line\" to \"$1\"\n" if ($localDebug || $liteDebug);
$line = $1."\n";
}
}
print STDERR "LINE[$inputCounter] : $line\n" if ($offsetDebug);
# The tokenizer
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\^|\W)/, $line);
}
# See note about similar block below. This block is for fixing the
# "missing newline" problem, which otherwise would cause line numbers
# to sometimes be wrong.
push(@parts, "BOGUSBOGUSBOGUSBOGUSBOGUS");
my $xpart = "";
foreach my $nextxpart (@parts) {
if (!length($nextxpart)) { next; }
if (!length($xpart)) { $xpart = $nextxpart; next; }
if ($xpart eq "\n" && $nextxpart ne "BOGUSBOGUSBOGUSBOGUSBOGUS") {
print STDERR "FOUND EXTRA NEWLINE\n" if ($offsetDebug);
# $fileoffset++;
$incrementoffsetatnewline++;
}
$xpart = $nextxpart;
}
pop(@parts);
$parserState->{inInlineComment} = 0;
print STDERR "inInlineComment -> 0\n" if ($ilcDebug);
# warn("line $inputCounter\n");
if ($localDebug || $cppDebug || $spaceDebug) {foreach my $partlist (@parts) {print STDERR "PARTLIST: \"$partlist\"\n"; }}
# We have to do the C preprocessing work up front because token substitution
# must occur prior to actual parsing in order to do any good. This block does
# the work.
my $cpp_in_argparse = 0;
if (!$disable_cpp && (1 || $HeaderDoc::enable_cpp)) {
my $newrawline = "";
my $incppargs = 0;
my $cppstring = "";
my $cppname = "";
my $lastcpppart = "";
my @cppargs = ();
my $inChar = 0; my $inString = 0; my $inComment = $parserState->{inComment}; my $inSLC = $parserState->{inInlineComment};
my $inParen = 0;
my $inMacro = $parserState->{inMacro};
my $inCPPSpecial = $parserState->{inMacro} || $parserState->{inMacroLine};
my $inMacroTail = 0;
if ($parserState->{sodname} && ($parserState->{sodname} ne "")) {
$inMacroTail = 1;
}
print STDERR "INMACROTAIL: $inMacroTail\n" if ($cppDebug);
my @cpptrees;
my $cpptreecur = HeaderDoc::ParseTree->new();
my $cpptreetop = $cpptreecur;
# print STDERR "CHECK LINE $line\n";
if ($line =~ /^\s*#include (.*)$/) {
my $rest = $1;
$rest =~ s/^\s*//s;
$rest =~ s/\s*$//s;
if ($rest !~ s/^\<(.*)\>$/$1/s) {
$rest =~ s/^\"(.*)\"$/$1/s;
}
my $filename = basename($rest);
if ($HeaderDoc::HeaderFileCPPHashHash{$filename}) {
my $includehash = HeaderDoc::IncludeHash->new();
$includehash->{FILENAME} = $filename;
$includehash->{LINENUM} = $inputCounter + $fileoffset;
$includehash->{HASHREF} = $HeaderDoc::HeaderFileCPPHashHash{$filename};
push(@HeaderDoc::cppHashList, $includehash);
# print STDERR "PUSH HASH\n";
push(@HeaderDoc::cppArgHashList, $HeaderDoc::HeaderFileCPPArgHashHash{$filename});
}
} elsif ($line =~ /^\s*$definename\s+/) {
# print STDERR "inMacro -> 1\n";
# print STDERR "inMacro -> 1\n" if ($macroDebug || $cppDebug);
# This is a throwaway line.
$inMacro = 1;
}
if ($macrore_pound ne "" && $line =~ /^\s*\#\s*$macrore_pound\s+/) {
print STDERR "CPPSPECIAL -> 1\n" if ($macroDebug || $cppDebug);
$inCPPSpecial = 1;
}
my $cppleaddebug = 0;
do {
my $pos = 0;
my $dropargs = 0;
while ($pos < scalar(@parts)) {
my $part = $parts[$pos];
my $noCPPThisToken = 0;
if (length($part)) {
if (!$inChar && !$inString && !$inComment && !$inSLC) {
if ($parserState->{NEXTTOKENNOCPP} == 1) {
# We're in an "if" block.
if ($part eq "defined") {
$parserState->{NEXTTOKENNOCPP} = 3;
}
} elsif ($parserState->{NEXTTOKENNOCPP} == 2) {
# We're in an "ifdef"/"ifndef" block, so first word token
# ends this mode completely.
if ($part !~ /(\s|\()/) {
$parserState->{NEXTTOKENNOCPP} = 0;
$noCPPThisToken = 1;
}
} elsif ($parserState->{NEXTTOKENNOCPP} == 3) {
# We're in an "if" block, so first word token
# drops us back to default "if" block state.
if ($part !~ /(\s|\()/) {
$parserState->{NEXTTOKENNOCPP} = 1;
$noCPPThisToken = 1;
}
}
if ($inCPPSpecial && $part =~ /(ifdef|ifndef)/) {
$parserState->{NEXTTOKENNOCPP} = 2;
} elsif ($inCPPSpecial && $part =~ /if/) {
$parserState->{NEXTTOKENNOCPP} = 1;
}
}
print STDERR "TOKEN: $part NEXTTOKENNOCPP: ".$parserState->{NEXTTOKENNOCPP}." INMACRO: $inMacro INCPPSPECIAL: $inCPPSpecial\n" if ($cppleaddebug || $macroDebug || $cppDebug);
print STDERR "CPPLEADPART: $part\n"if ($cppleaddebug);
if (!$inString && !$inChar) {
if ($inComment && $part eq $eoc) {
print STDERR "EOC\n"if ($cppleaddebug);
$inComment = 0;
} elsif ($inSLC && $part =~ /[\r\n]/) {
# Handle newline in single-line comments.
print STDERR "EOSLC\n"if ($cppleaddebug);
$inSLC = 0;
} elsif (!$inSLC && $part eq $soc) {
print STDERR "SOC\n"if ($cppleaddebug);
$inComment = 1;
} elsif (!$inComment && ($part eq $ilc || $part eq $ilc_b)) {
print STDERR "INSLC\n"if ($cppleaddebug);
$inSLC = 1;
}
}
my $skip = 0;
if (!$incppargs) {
my $newpart = $part;
my $hasargs = 0;
if (!$inComment && !$inSLC && !$noCPPThisToken) {
($newpart, $hasargs) = cpp_preprocess($part, $HeaderDoc::CurLine);
# Don't drop tokens in macros.
if ($hasargs == 2 && $inMacro) {
$newpart = $part;
$hasargs = 0;
}
# Don't change the macro name. (If a
# macro gets redefined, ignore it.)
if ($inMacro && !$inMacroTail) {
$newpart = $part;
$hasargs = 0;
}
}
if ($hasargs) {
$incppargs = 1;
$cppname = $part;
if ($hasargs == 2) {
$dropargs = 1;
print STDERR "Dropping arguments for ignored macro \"$part\"\n" if ($cppDebug);
}
} else {
my $newpartnl = $newpart;
my $newpartnlcount = ($newpartnl =~ tr/\n//);
my $partnl = $part;
my $partnlcount = ($partnl =~ tr/\n//);
my $nlchange = ($newpartnlcount - $partnlcount);
print STDERR "NLCHANGE: $nlchange (FILEOFFSET = $fileoffset)\n" if ($offsetDebug);
$fileoffset -= $nlchange;
if ($inMacro) {
if ($newpart ne $part) {
print STDERR "CHANGING NEWPART FROM \"$newpart\" TO " if ($cppDebug);
$newpart =~ s/^\s*/ /s;
$newpart =~ s/\s*$//s;
$newpart =~ s/(.)\n/$1 \\\n/sg;
$newpart =~ s/\\$/ /s;
print STDERR "$newpart\n" if ($cppDebug);
}
}
$newrawline .= $newpart;
}
} elsif ($incppargs == 1) {
if ($part eq "(") {
# Don't do anything until leading parenthesis.
$incppargs = 3;
$inParen++;
}
} elsif ($incppargs == 3) {
if ($part eq '\\') {
if (!$inMacro && ($lastcpppart eq '\\')) { $lastcpppart = ""; } # @@@ CHECKME. inMacro test may not be needed.
# else {
# $lastcpppart = $part;
# if ($inMacro) {
# print STDERR "IMTEST\n" if ($cppDebug > 1);
# my $npos = $pos + 1;
# while ($npos < scalar(@parts)) {
# my $npart = $parts[$npos];
# if (length($npart)) {
# print STDERR "NEXTPART: \"".$parts[$npos]."\"\n" if ($cppDebug > 1);
# if ($npart =~ /\s/) {
# if ($npart =~ /[\n\r]/) {
# print STDERR "SKIP1\n" if ($cppDebug > 1);
# $skip = 1; last;
# } else {
# print STDERR "SPC\n" if ($cppDebug > 1);
# }
# } else {
# print STDERR "LAST\n" if ($cppDebug > 1);
# last;
# }
# }
# $npos++;
# }
# }
# }
} elsif ($part eq '"') {
if ($lastcpppart ne '\\') {
if (!$inChar && !$inComment && !$inSLC) {
$inString = !$inString;
}
}
$lastcpppart = $part;
} elsif ($part eq "'") {
if ($lastcpppart ne '\\') {
if (!$inString && !$inComment && !$inSLC) {
$inChar = !$inChar;
}
}
$lastcpppart = $part;
} elsif (!$inChar && !$inString && !$inComment && !$inSLC) {
if ($part eq "(") {
# Put in the token first, then nest.
$cpptreecur = $cpptreecur->next(HeaderDoc::ParseTree->new());
$cpptreecur->token($part);
$skip = 1;
$inParen++;
push(@cpptrees, $cpptreecur);
$cpptreecur = $cpptreecur->firstchild(HeaderDoc::ParseTree->new());
} elsif ($part eq ")") {
$inParen--;
# Go out one nesting level, then
# insert the token.
if (scalar(@cpptrees)) {
$cpptreecur = pop(@cpptrees);
while ($cpptreecur && $cpptreecur->next()) {
$cpptreecur = $cpptreecur->next();
}
}
if (!$inParen) {
push(@cppargs, $cpptreetop);
$cppstring = "";
$cpptreetop = HeaderDoc::ParseTree->new();
$cpptreecur = $cpptreetop;
$skip = 1;
$incppargs = 0;
if (!$dropargs) {
print STDERR "CALLING ARGPARSE FROM blockParse() [1].\n" if ($cppDebug);
my $addon = cpp_argparse($cppname, $HeaderDoc::CurLine, \@cppargs);
if ($inMacro) {
print STDERR "CHANGING ADDON FROM \"$addon\" TO " if ($cppDebug);
$addon =~ s/^\s*/ /s;
$addon =~ s/\s*$//s;
$addon =~ s/(.)\n/$1 \\\n/sg;
$addon =~ s/\\$/ /s;
print STDERR "$addon\n" if ($cppDebug);
}
$newrawline .= $addon;
}
$dropargs = 0;
}
} elsif (($inParen == 1) && (!$inChar && !$inString && !$inComment && !$inSLC) && ($part eq ",")) {
push(@cppargs, $cpptreetop);
$cpptreetop = HeaderDoc::ParseTree->new();
$cpptreecur = $cpptreetop;
$cppstring = "";
$skip = 1;
} elsif (($part =~ /\s/) && (!$inParen)) {
$incppargs = 0;
if (!$dropargs) {
print STDERR "CALLING ARGPARSE FROM blockParse() [2].\n" if ($cppDebug);
my $addon = cpp_argparse($cppname, $HeaderDoc::CurLine, \@cppargs);
if ($inMacro) {
print STDERR "CHANGING ADDON FROM \"$addon\" TO " if ($cppDebug);
$addon =~ s/^\s*/ /s;
$addon =~ s/\s*$//s;
$addon =~ s/(.)\n/$1 \\\n/sg;
$addon =~ s/\\$/ /s;
print STDERR "$addon\n" if ($cppDebug);
}
$newrawline .= $addon;
}
$dropargs = 0;
}
$lastcpppart = $part;
}
if ($skip) { $skip = 0; }
else {
my $xpart = $part;
# Strip newline in CPP argument list.
if ($part =~ /[\r\n]/) { $xpart = " "; }
$cpptreecur = $cpptreecur->next(HeaderDoc::ParseTree->new());
$cpptreecur->token($xpart);
}
$cppstring .= $part;
}
if ($inMacro && $part ne "define" &&
$part =~ /\w/ && !$inParen) {
$inMacroTail = 1;
}
}
$pos++;
}
if ($incppargs) {
# print STDERR "YO\n";
if ($parserState->{inMacro} || $inMacro) {
# print STDERR "YOYO\n";
if ($cppstring !~ s/\\\s*$//s) {
print STDERR "CPPS: \"$cppstring\"\n";
warn "Non-terminated macro.\n";
$incppargs = 0;
}
}
}
if ($incppargs || $inComment) {
print STDERR "Fetching new line ($incppargs, $inComment)\n" if ($cppleaddebug);
$HeaderDoc::CurLine = $inputCounter + $fileoffset;
$line = $inputLines[$inputCounter++];
if ($lang eq "C" && $sublang eq "IDL") {
if ($line =~ /cpp_quote\s*\(\s*\"(.*)\"\s*\)\s*$/) {
print "CHANGED LINE FROM \"$line\" to \"$1\"\n" if ($localDebug || $liteDebug);
$line = $1."\n";
}
}
print STDERR "INCREMENTED INPUTCOUNTER [2]\n" if ($HeaderDoc::inputCounterDebug);
# @parts = split(/(\W)/, $line);
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
}
}
} until (!$incppargs && !$inComment);
# The tokenizer
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $newrawline);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\W)/, $newrawline);
}
while (scalar(@cpptrees)) {
my $temptree = pop(@cpptrees);
if ($temptree != $cpptreetop) {
$temptree->dispose();
}
}
$cpptreetop->dispose();
}
if (!$parserState->{inMacro}) {
$parserState->{NEXTTOKENNOCPP} = 0;
}
# Throw away any empty entries caused by Perl seeing two
# adjacent tokens that match the split regexp. We don't
# want them or care about them, and they break things
# rather badly if we don't....
my @stripparts = @parts;
@parts = ();
print STDERR "BEGIN PARTLIST 2:\n" if ($spaceDebug);
foreach my $strippart (@stripparts) {
if (length($strippart)) {
print STDERR "MYPART: \"$strippart\"\n" if ($spaceDebug);
push(@parts, $strippart);
}
}
print STDERR "END PARTLIST 2.\n" if ($spaceDebug);
# This bit of code needs a bit of explanation, I think.
# We need to be able to see the token that follows the one we
# are currently processing. To do this, we actually keep track
# of the current token, and the previous token, but name then
# $nextpart and $part. We do processing on $part, which gets
# assigned the value from $nextpart at the end of the loop.
#
# To avoid losing the last part of the declaration (or needing
# to unroll an extra copy of the entire loop code) we push a
# bogus entry onto the end of the stack, which never gets
# used (other than as a bogus "next part") because we only
# process the value in $part.
#
# To avoid problems, make sure that you don't ever have a regexp
# that would match against this bogus token.
#
my $part = "";
push(@parts, "BOGUSBOGUSBOGUSBOGUSBOGUS");
if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POSTCPPPARTLIST: \"$partlist\"\n"; }}
foreach my $nextpart (@parts) {
my $hideTokenAndMaybeContents = 0;
$treeSkip = 0;
# $treePopTwo = 0;
# $treePopOnNewLine = 0;
# The current token is now in "part", and the literal next
# token in "nextpart". We can't just work with this as-is,
# though, because you can have multiple spaces, null
# tokens when two of the tokens in the split list occur
# consecutively, etc.
print STDERR "MYPART: \"$part\"\n" if ($localDebug || $spaceDebug);
$forcenobreak = 0;
if ($nextpart eq "\r") { $nextpart = "\n"; }
if ($localDebug && $nextpart eq "\n") { print STDERR "NEXTPART IS NEWLINE!\n"; }
if ($localDebug && $part eq "\n") { print STDERR "PART IS NEWLINE!\n"; }
### if ($nextpart ne "\n" && $nextpart =~ /\s/o) {
### # Replace tabs with spaces.
### $nextpart = " ";
### }
# Replace tabs with spaces.
$part =~ s/\t/ /g;
$nextpart =~ s/\t/ /g;
if ($part ne "\n" && $part =~ /\s/o && $nextpart ne "\n" &&
$nextpart =~ /\s/o) {
# we're a space followed by a space. Join the tokens.
print STDERR "MERGED \"$part\" and \"$nextpart\" into " if ($spaceDebug);
$nextpart = $part.$nextpart;
print STDERR "\"$nextpart\".\n" if ($spaceDebug);
$part = $nextpart;
next;
}
print STDERR "PART IS \"$part\"\n" if ($localDebug || $parserStackDebug || $parseDebug || $liteDebug || $spaceDebug);
print STDERR "CURLINE IS \"$curline\"\n" if ($localDebug || $hangDebug);
print STDERR "INOP: ".$parserState->{inOperator}."\n" if ($operatorDebug);
if (!length($nextpart)) {
print STDERR "SKIP NP\n" if ($localDebug);
next;
}
if (!length($part)) {
print STDERR "SKIP PART\n" if ($localDebug);
$part = $nextpart;
next;
}
if ($occPushParserStateOnWordTokenAfterNext > 1) {
if ($part =~ /\w/) {
$occPushParserStateOnWordTokenAfterNext--;
print STDERR "occPushParserStateOnWordTokenAfterNext -> $occPushParserStateOnWordTokenAfterNext (--)\n" if ($localDebug || $parseDebug);
}
} elsif ($occPushParserStateOnWordTokenAfterNext) {
# if ($part !~ /(\s|<)/)
if ($part =~ /(\/\/|\/\*|\-|\+|\w|\@)/) {
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[occPushParserStateOnWordTokenAfterNext]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 0;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
}
}
# If we get here, we aren't skipping a null or whitespace token.
# Let's print a bunch of noise if debugging is enabled.
# if ($part eq "\n" && $nextpart ne "BOGUSBOGUSBOGUSBOGUSBOGUS") {
# $fileoffset++;
# }
if ($part eq "\n" && $incrementoffsetatnewline) {
$incrementoffsetatnewline--;
$fileoffset++;
}
print STDERR "IN LOOP LANG: $lang INITIAL SUBLANG: $sublang\n" if ($localDebug || $parseDebug);
if ($parseDebug) {
print STDERR "PART: $part, type: $parserState->{typestring}, inComment: $parserState->{inComment}, inInlineComment: $parserState->{inInlineComment}, inChar: $parserState->{inChar}.\n" if ($localDebug);
print STDERR "PART: inBrackets: $parserState->{inBrackets}\n" if ($localDebug);
print STDERR "PART: onlyComments: $parserState->{onlyComments}, inClass: $parserState->{inClass}\n";
print STDERR "PART: cbsodname: $parserState->{cbsodname}\n";
print STDERR "PART: classIsObjC: $parserState->{classIsObjC}, PPSAT: $pushParserStateAfterToken, PPSAWordT: $pushParserStateAfterWordToken, PPSABrace: $pushParserStateAtBrace, occPPSOnWordTokenAfterNext: $occPushParserStateOnWordTokenAfterNext\n";
print STDERR "PART: bracecount: " . scalar(@braceStack) . " (init was $parserState->{initbsCount}).\n";
print STDERR "PART: inString: $parserState->{inString}, callbackNamePending: $parserState->{callbackNamePending}, namePending: $parserState->{namePending}, lastsymbol: $parserState->{lastsymbol}, lasttoken: $lasttoken, lastchar: $lastchar, SOL: $parserState->{startOfDec}\n" if ($localDebug);
print STDERR "PART: sodclass: $parserState->{sodclass} sodname: $parserState->{sodname}\n";
print STDERR "PART: sodtype: $parserState->{sodtype}\n";
print STDERR "PART: simpleTypedef: $parserState->{simpleTypedef}\n";
print STDERR "PART: posstypes: $parserState->{posstypes}\n";
print STDERR "PART: seenBraces: $parserState->{seenBraces} inRegexp: $inRegexp\n";
print STDERR "PART: regexpNoInterpolate: $regexpNoInterpolate\n";
print STDERR "PART: seenTilde: $parserState->{seenTilde}\n";
print STDERR "PART: CBN: $parserState->{callbackName}\n";
print STDERR "PART: regexpStack is:";
foreach my $token (@regexpStack) { print STDERR " $token"; }
print STDERR "\n";
print STDERR "PART: npplStack: ".scalar(@{$parserState->{pplStack}})." nparsedParamList: ".scalar(@{$parserState->{parsedParamList}})." nfreezeStack: ".scalar(@{$parserState->{freezeStack}})." frozen: $parserState->{stackFrozen}\n";
print STDERR "PART: inMacro: $parserState->{inMacro} treePopOnNewLine: $treePopOnNewLine\n";
print STDERR "PART: occmethod: $parserState->{occmethod} occmethodname: $parserState->{occmethodname}\n";
print STDERR "PART: returntype is $parserState->{returntype}\n";
print STDERR "length(declaration) = " . length($declaration) ."; length(curline) = " . length($curline) . "\n";
print STDERR "REQUIREDREGEXP IS \"$requiredregexp\"\n";
print STDERR "DEC: $declaration\n$curline\n";
} elsif ($tsDebug || $treeDebug) {
print STDERR "BPPART: $part\n";
}
if ($parserStackDebug) {
print STDERR "parserState: STACK CONTAINS ".scalar(@parserStack)." STATES\n";
print STDERR "parserState is $parserState\n";
}
# The ignore function returns either null, an empty string,
# or a string that gives the text equivalent of an availability
# macro. If the token is non-null and the length is non-zero,
# it's an availability macro, so blow it in as if the comment
# contained an @availability tag.
#
my $tempavail = ignore($part, $ignoreref, $perheaderignoreref);
printf("PART: $part TEMPAVAIL: $tempavail\n") if ($localDebug || $gccAttributeDebug);
if ($tempavail && ($tempavail ne "1") && ($tempavail ne "2")) {
$parserState->{availability} = $tempavail;
} elsif ($tempavail eq "2") {
# Reusing the GCC attribute handling code because that does exactly what we need.
print STDERR "Function-like availability macro detected. Collecting.\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = 1;
$parserState->{attributeParts} = ();
# Add __attribute__ as the next token.
$treeCur = $treeCur->addSibling($part, 0);
push(@treeStack, $treeCur);
my @tempAvailabilityNodesArray = ();
if ($parserState->{availabilityNodesArray}) {
@tempAvailabilityNodesArray = @{$parserState->{availabilityNodesArray}};
}
push(@tempAvailabilityNodesArray, $treeCur);
# print STDERR "ADDED $treeCur\n";
# $treeCur->dbprint();
$parserState->{availabilityNodesArray} = \@tempAvailabilityNodesArray;
# Nest all contents one level lower.
$treeCur = $treeCur->addChild("", 0);
$part = $nextpart;
next;
}
# Handle the GCC "__attribute__" extension outside the context of
# the parser because it isn't part of the language and massively
# breaks the syntax.
if ($lang eq "C" && isKeyword($part, $keywordhashref, $case_sensitive) == 2) {
print STDERR "GCC attribute detected. Collecting.\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = 1;
$parserState->{attributeParts} = ();
# Add __attribute__ as the next token.
$treeCur = $treeCur->addSibling($part, 0);
push(@treeStack, $treeCur);
# Nest all contents one level lower.
$treeCur = $treeCur->addChild("", 0);
$part = $nextpart;
next;
} elsif ($parserState->{attributeState} == 1) {
if ($part eq "(") {
print STDERR "GCC attribute open paren\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = -1;
}
$treeCur = $treeCur->addSibling($part, 0);
$part = $nextpart;
next;
} elsif ($parserState->{attributeState} < 0) {
if ($part eq "(") {
$parserState->{attributeState}--;
print STDERR "GCC attribute open paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug);
} elsif ($part eq ")") {
$parserState->{attributeState}++;
print STDERR "GCC attribute close paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug);
}
$treeCur = $treeCur->addSibling($part, 0);
if (($localDebug || $gccAttributeDebug) && !$parserState->{attributeState}) {
print STDERR "GCC attribute: done collecting.\n";
# Get back to where we started.
$treeCur = pop(@treeStack);
}
$part = $nextpart;
next;
}
# Here be the parser. Abandon all hope, ye who enter here.
$treepart = "";
if ($parserState->{inProtocol} == 1) {
print STDERR "INPROTOCOL: 1\n" if ($parseDebug || $classDebug);
if ($part =~ /\w/) {
print STDERR "INPROTOCOL: 1 -> 2\n" if ($parseDebug || $classDebug);
$parserState->{inProtocol} = 2;
}
} elsif ($parserState->{inProtocol} == 2) {
print STDERR "INPROTOCOL: 2\n" if ($parseDebug || $classDebug);
if ($part eq "<") {
print STDERR "INPROTOCOL: 2 -> 3\n" if ($parseDebug || $classDebug);
$parserState->{extendsProtocol} = "";
$parserState->{inProtocol} = 3;
} elsif ($part =~ /\S/) {
# PUSH PARSER STATE
print STDERR "parserState pushed onto stack[PROTOCOL]\n" if ($parserStackDebug);
$parserState->{inProtocol} = -1;
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterWordToken = 0;
}
} elsif ($parserState->{inProtocol} == 3) {
print STDERR "INPROTOCOL: 3\n" if ($parseDebug || $classDebug);
if ($part eq ">") {
print STDERR "INPROTOCOL: 3 -> 2\n" if ($parseDebug || $classDebug);
$parserState->{inProtocol} = 2;
} else {
$parserState->{extendsProtocol} .= $part;
}
}
if ($parserState->{inClass} == 3) {
print STDERR "INCLASS3\n" if ($parseDebug || $classDebug);
if ($part eq ")") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [1]\n" if ($classDebug);
$parserState->{categoryClass} .= $part;
print STDERR "parserState will be pushed onto stack[cparen3]\n" if ($parserStackDebug);
# $parserState->{lastTreeNode} = $treeCur;
# push(@parserStack, $parserState);
# $parserState = HeaderDoc::ParserState->new();
# $parserState->{lang} = $lang;
# $parserState->{inputCounter} = $inputCounter;
# $parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterToken = 1;
} elsif ($part eq ":") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [2]\n" if ($classDebug);
if ($parserState->{classIsObjC}) {
print STDERR "occPushParserStateOnWordTokenAfterNext -> 2\n" if ($localDebug || $parseDebug);
$occPushParserStateOnWordTokenAfterNext = 2;
} else {
$pushParserStateAfterWordToken = 1;
}
# if ($sublang eq "occ") {
# $pushParserStateAtBrace = 2;
# }
} elsif ($part =~ /</ && $parserState->{classIsObjC}) {
print STDERR "pushParserStateAfterWordToken -> 0 (Conforming)\n" if ($localDebug || $parseDebug);
print STDERR "inClassConformingToProtocol -> 1\n" if ($localDebug || $parseDebug);
$pushParserStateAfterWordToken = 0;
$parserState->{inClassConformingToProtocol} = 1;
$occPushParserStateOnWordTokenAfterNext = 0;
} elsif ($part =~ />/ && $parserState->{classIsObjC} && $parserState->{inClassConformingToProtocol}) {
print STDERR "inClassConformingToProtocol -> 0\n" if ($localDebug || $parseDebug);
$pushParserStateAfterToken = 1;
print STDERR "pushParserStateAfterWordToken -> 1 (Conforming)\n" if ($localDebug || $parseDebug);
$parserState->{inClassConformingToProtocol} = 0;
} else {
$parserState->{categoryClass} .= $part;
}
} elsif ($parserState->{inClass} == 2) {
print STDERR "INCLASS2\n" if ($parseDebug || $classDebug);
if ($part eq ")") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [3]\n" if ($classDebug);
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[cparen2]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
} elsif ($part eq ":") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [4]\n" if ($classDebug);
if ($parserState->{classIsObjC}) {
print STDERR "occPushParserStateOnWordTokenAfterNext -> 2\n" if ($localDebug || $parseDebug);
$occPushParserStateOnWordTokenAfterNext = 2;
} else {
$pushParserStateAfterWordToken = 2;
}
} elsif ($part =~ /\w/) {
# skip the class name itself.
$parserState->{inClass} = 3;
print STDERR "inClass -> 3 [5]\n" if ($classDebug);
}
} elsif ($parserState->{inClass} == 1) {
print STDERR "INCLASS1\n" if ($parseDebug || $classDebug);
# print STDERR "inclass Part is $part\n";
if ($part eq ":") {
print STDERR "INCLASS COLON\n" if ($parseDebug || $classDebug);
$parserState->{forceClassName} = $parserState->{sodname};
$parserState->{forceClassSuper} = "";
# print STDERR "XSUPER: $parserState->{forceClassSuper}\n";
} elsif ($part eq "{" || $part eq ";") {
print STDERR "INCLASS BRCSEMI\n" if ($parseDebug || $classDebug);
$parserState->{forceClassDone} = 1;
if ($parserState->{classIsObjC} && $part eq "{") {
$parserState->{ISFORWARDDECLARATION} = 0;
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[OCC-BRCSEMI]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 0;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack) + 1; # NOTE: add one here because it will change in the SWITCH to follow.
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
$pushParserStateAfterToken = 1;
} elsif ($part eq ";") {
if (!defined($parserState->{ISFORWARDDECLARATION})) {
print STDERR "FORWARD DECLARATION DETECTED\n" if ($parseDebug || $localDebug || $liteDebug);
# print STDERR "PREVIOUS FD STATE: ".$parserState->{ISFORWARDDECLARATION}."\n";
$parserState->{ISFORWARDDECLARATION} = 1;
}
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
$pushParserStateAfterToken = 0;
}
} elsif ($parserState->{forceClassName} && !$parserState->{forceClassDone}) {
print STDERR "INCLASS ADD\n" if ($parseDebug || $classDebug);
if ($part =~ /[\n\r]/) {
$parserState->{forceClassSuper} .= " ";
} else {
$parserState->{forceClassSuper} .= $part;
}
# print STDERR "SUPER IS $parserState->{forceClassSuper}\n";
} elsif ($part =~ /</ && $parserState->{classIsObjC} && $occPushParserStateOnWordTokenAfterNext) {
print STDERR "INCLASS <\n" if ($parseDebug || $classDebug);
print STDERR "pushParserStateAfterWordToken -> 0 (Conforming)\n" if ($localDebug || $parseDebug);
print STDERR "inClassConformingToProtocol -> 1\n" if ($localDebug || $parseDebug);
$pushParserStateAfterWordToken = 0;
$parserState->{inClassConformingToProtocol} = 1;
$occPushParserStateOnWordTokenAfterNext = 0;
} elsif ($part =~ />/ && $parserState->{classIsObjC} && $parserState->{inClassConformingToProtocol}) {
print STDERR "INCLASS >\n" if ($parseDebug || $classDebug);
print STDERR "inClassConformingToProtocol -> 0\n" if ($localDebug || $parseDebug);
$pushParserStateAfterToken = 1;
print STDERR "pushParserStateAfterWordToken -> 1 (Conforming)\n" if ($localDebug || $parseDebug);
$parserState->{inClassConformingToProtocol} = 0;
} elsif ($occPushParserStateOnWordTokenAfterNext && $part =~ /\w/) {
print STDERR "INCLASS OCCSUPER\n" if ($parseDebug || $classDebug);
$parserState->{occSuper} = $part;
# $occPushParserStateOnWordTokenAfterNext = 0;
# $pushParserStateAfterToken = 1;
} elsif (!$parserState->{classIsObjC}) {
print STDERR "INCLASS NOTOBJC (OTHER)\n" if ($parseDebug || $classDebug);
if ($part =~ /[*(^]/) {
print STDERR "INCLASS DROP\n" if ($parseDebug || $classDebug);
$parserState->{inClass} = 0; # We're an instance. Either a variable or a function.
print STDERR "inClass -> 0 [6]\n" if ($classDebug);
$parserState->{sodtype} = $parserState->{preclasssodtype} . $parserState->{sodtype};
}
# } else {
# print STDERR "BUG\n";
}
};
if ($parserState->{inClassConformingToProtocol} == 1) {
$parserState->{inClassConformingToProtocol} = 2;
} elsif ($parserState->{inClassConformingToProtocol}) {
$parserState->{conformsToList} .= $part;
}
if ($macroDebug) {
print STDERR "MNT: ".$parserState->{macroNoTrunc}."\n";
}
# if (($part eq $ilc || $part eq $ilc_b) && ($lang ne "perl" || $lasttoken ne "\$")) {
# print STDERR "should be ILC?\n";
# } else {
# print STDERR "NO CHANEC: PART \"$part\" ILC \"$ilc\" ILC_B: \"ilc_b\" LANG: \"$lang\" LASTTOKEN: \"$lasttoken\"\n";
# }
SWITCH: {
# Blank declaration handlers (mostly for misuse of
# OSMetaClassDeclareReservedUsed and similar)
(($part eq ";") && ($parserState->{startOfDec} == 1) && !$parserState->{inMacro} && !$parserState->{inMacroLine} && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "LEADING SEMICOLON: CASE 01\n" if ($liteDebug);
print STDERR "Dropping empty declaration\n" if ($localDebug || $parseDebug);
$part = "";
last SWITCH;
};
# Macro handlers
(($parserState->{inMacro} == 1) && ($part eq "define")) && do {
print STDERR "INMACRO/DEFINE: CASE 02\n" if ($liteDebug);
# define may be a multi-line macro
print STDERR "INMACRO AND DEFINE\n" if ($parseDebug || $localDebug);
$parserState->{inMacro} = 3;
print STDERR "inMacro -> 3\n" if ($macroDebug || $cppDebug);
$parserState->{sodname} = "";
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [1]\n"; }
$treePopOnNewLine = 2;
$pound .= $part;
$treeCur->token($pound);
}
last SWITCH;
};
# (($parserState->{inMacro} == 1 && $macrore_pound ne "" && $part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)/ && ($part ne $definename)) || ($parserState->{inMacro} == 0 && $macrore_nopound ne "" && $part =~ /$macrore_nopound/))
# (($parserState->{inMacro} == 1 && $part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)/ )) && do
(!$parserState->{inComment} && (($parserState->{inMacro} == 1 && $macrore_pound ne "" && $part =~ /^$macrore_pound$/ && ($part ne $definename)) || ($parserState->{inMacro} == 0 && $macrore_nopound ne "" && $part =~ /^$macrore_nopound$/))) && do {
print STDERR "MACRORE-v: \"$macrore_pound\"\n" if ($macroDebug);
print STDERR "MACRORE-r: \"(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)\"\n" if ($macroDebug);
print STDERR "MACRORE-n: \"$macrore_nopound\"\n" if ($macroDebug);
print STDERR "INMACRO/IF: CASE 03\n" if ($liteDebug);
print STDERR "INMACRO AND IF/IFDEF/IFNDEF/ENDIF/ELSE/PRAGMA/IMPORT/INCLUDE\n" if ($parseDebug || $localDebug);
# these are all single-line macros
$parserState->{inMacro} = 4;
print STDERR "inMacro -> 4\n" if ($macroDebug || $cppDebug);
$parserState->{sodname} = "";
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [2]\n"; }
$treePopOnNewLine = 1;
$pound .= $part;
$treeCur->token($pound);
if ($part eq "endif") {
# the rest of the line is not part of the macro
# NOTE: Do not change treeCur in the
# next line.
$treeCur->addChild("\n", 0);
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [3]\n"; }
$treePopOnNewLine = 0;
$treeSkip = 1;
}
}
last SWITCH;
};
(($parserState->{inMacroLine} == 1) && ($part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include|define)/o)) && do {
print STDERR "INMACROLINE/IF: CASE 04\n" if ($liteDebug);
print STDERR "INMACROLINE AND IF/IFDEF/IFNDEF/ENDIF/ELSE/PRAGMA/IMPORT/INCLUDE\n" if ($parseDebug || $localDebug);
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$pound .= $part;
$treeCur->token($pound);
if ($part =~ /define/o) {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [4]\n"; }
$treePopOnNewLine = 2;
} elsif ($part eq "endif") {
# the rest of the line is not part of the macro
# NOTE: Do not change treeCur in the
# next line.
$treeCur->addChild("\n", 0);
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [5]\n"; }
$treePopOnNewLine = 0;
$treeSkip = 1;
} else {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [6]\n"; }
$treePopOnNewLine = 1;
}
}
last SWITCH;
};
($parserState->{inMacro} == 1 && ($part ne $soc) && ($part ne $eoc) && $part =~ /\s/) && do {
$treepart = $part; $part = "";
last SWITCH;
};
($parserState->{inMacro} == 1 && ($part ne $soc) && ($part ne $eoc)) && do {
print STDERR "INMACRO PPTOKEN: CASE 05\n" if ($liteDebug);
print STDERR "INMACRO IS 1, CHANGING TO 2 (NO PROCESSING)\n" if ($parseDebug || $localDebug);
# error case.
$parserState->{inMacro} = 2;
print STDERR "inMacro -> 2\n" if ($macroDebug || $cppDebug);
last SWITCH;
};
($parserState->{inMacro} > 1 && $part ne "//" && $part !~ /[\n\r]/ && ($part ne $soc) && ($part ne $eoc)) && do {
print STDERR "INMACRO OTHERTOKEN: CASE 06\n" if ($liteDebug);
print STDERR "INMACRO > 1, PART NE //" if ($parseDebug || $localDebug);
if ($part eq "\\") {
$parserState->addBackslash();
} elsif ($part !~ /[ \t]/) {
$parserState->addBackslash();
}
print STDERR "PART: $part\n" if ($macroDebug);
if ($parserState->{seenMacroPart} && $HeaderDoc::truncate_inline) {
print STDERR "MACRO: SMP&TI\n" if ($macroDebug);
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
print STDERR "MACRO: NOSTACK\n" if ($macroDebug);
if ($part =~ /\s/o && $parserState->{macroNoTrunc} == 1) {
print STDERR "MACRO: ENDOFNAME\n" if ($macroDebug);
$parserState->{macroNoTrunc} = 0;
} elsif ($part =~ /[\{\(]/o) {
print STDERR "MACRO: BRACE\n" if ($macroDebug);
if (!$parserState->{macroNoTrunc}) {
# $parserState->{seenBraces} = 1;
$HeaderDoc::hidetokens = 3;
}
} else {
print STDERR "MACRO: OTHERTOKEN\n" if ($macroDebug);
$parserState->{macroNoTrunc} = 2;
}
}
}
if ($part =~ /[\{\(]/o) {
push(@braceStack, $part);
print STDERR "PUSH\n" if ($macroDebug);
} elsif ($part =~ /[\}\)]/o) {
if ($part ne peekmatch(\@braceStack, $filename, $inputCounter)) {
if ($parserState->{macroNoTrunc} == 1) {
# We haven't reached the end of the first part of the declaration, so this is an error.
warn("$filename:$inputCounter: warning: Initial braces in macro name do not match.\nWe may have a problem.\n");
}
}
pop(@braceStack);
print STDERR "POP\n" if ($macroDebug);
}
if ($part =~ /\S/o) {
$parserState->{seenMacroPart} = 1;
$parserState->{lastsymbol} = $part;
if (($parserState->{sodname} eq "") && ($parserState->{inMacro} == 3)) {
print STDERR "DEFINE NAME IS $part\n" if ($macroDebug);
$parserState->{sodname} = $part;
}
}
$lastchar = $part;
last SWITCH;
};
# Regular expression handlers
# print STDERR "IRE: $inRegexp IRT: $inRegexpTrailer IS: $parserState->{inString} ICo $parserState->{inComment} ILC: $parserState->{inInlineComment} ICh $parserState->{inChar}\n";
(length($regexppattern) && $part =~ /^($regexppattern)$/ && !($inRegexp || $inRegexpTrailer || $parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "REGEXP PATTERN: CASE 07\n" if ($liteDebug);
my $match = $1;
print STDERR "REGEXP WITH PREFIX\n" if ($regexpDebug);
$regexpNoInterpolate = 0;
if ($match =~ /^($singleregexppattern)$/) {
# e.g. perl PATTERN?
$inRegexp = 2;
} else {
$inRegexp = 4;
# print STDERR "REGEXP PART IS \"$part\"\n";
if ($part eq "tr") { $regexpNoInterpolate = 1; }
# if ($part =~ /tr/) { $regexpNoInterpolate = 1; }
}
last SWITCH;
}; # end regexppattern
(($inRegexp || $parserState->{lastsymbol} eq "~") && (length($regexpcharpattern) && $part =~ /^($regexpcharpattern)$/ && (!scalar(@regexpStack) || $part eq peekmatch(\@regexpStack, $filename, $inputCounter)))) && do {
print STDERR "REGEXP CHARACTER: CASE 08\n" if ($liteDebug);
print STDERR "REGEXP?\n" if ($regexpDebug);
if (!$inRegexp) {
$inRegexp = 2;
}
# if ($lasttoken eq "\\")
if ($parserState->isQuoted($lang. $sublang)) {
# jump to next match.
$lasttoken = $part;
$parserState->{lastsymbol} = $part;
next SWITCH;
}
print STDERR "REGEXP POINT A\n" if ($regexpDebug);
$lasttoken = $part;
$parserState->{lastsymbol} = $part;
if ($part eq "#" &&
((scalar(@regexpStack) != 1) ||
(peekmatch(\@regexpStack, $filename, $inputCounter) ne "#"))) {
if ($nextpart =~ /^\s/o) {
# it's a comment. jump to next match.
next SWITCH;
}
}
print STDERR "REGEXP POINT B\n" if ($regexpDebug);
if (!scalar(@regexpStack)) {
push(@regexpStack, $part);
$inRegexp--;
} else {
my $match = peekmatch(\@regexpStack, $filename, $inputCounter);
my $tos = pop(@regexpStack);
if (!scalar(@regexpStack) && ($match eq $part)) {
$inRegexp--;
if ($inRegexp == 2 && $tos eq "/") {
# we don't double the slash in the
# middle of a s/foo/bar/g style
# expression.
$inRegexp--;
}
if ($inRegexp) {
push(@regexpStack, $tos);
}
} elsif (scalar(@regexpStack) == 1) {
push(@regexpStack, $tos);
if ($tos =~ /['"`]/o || $regexpNoInterpolate) {
# these don't interpolate.
next SWITCH;
}
} else {
push(@regexpStack, $tos);
if ($tos =~ /['"`]/o || $regexpNoInterpolate) {
# these don't interpolate.
next SWITCH;
}
push(@regexpStack, $part);
}
}
print STDERR "REGEXP POINT C\n" if ($regexpDebug);
if (!$inRegexp) {
$inRegexpTrailer = 2;
}
last SWITCH;
}; # end regexpcharpattern
# Start of preprocessor macros
($part eq "$sopreproc") && do {
print STDERR "SOPREPROC: CASE 09\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parserState->{onlyComments}) {
print STDERR "inMacro -> 1\n" if ($macroDebug || $cppDebug);
$parserState->{inMacro} = 1;
## @@@ FIXME DAG NEXT TWO LINES NEEDED FOR IDL TO AVOID
## "warning: Declaration starts with # but is not preprocessor macro"
## ERROR MESSAGE, BUT THIS BREAKS C/C++.
## WHY !?!?!
##
## if ($$treepart = " ";
## $nextpart = $part.$nextpart;
##
## END IDL-ONLY BLOCK
# $continue = 0;
# print STDERR "continue -> 0 [1]\n" if ($localDebug || $macroDebug);
} elsif ($curline =~ /^\s*$/o) {
$parserState->{inMacroLine} = 1;
print STDERR "IML\n" if ($localDebug);
} elsif ($postPossNL) {
print STDERR "PRE-IML \"$curline\"\n" if ($localDebug || $macroDebug);
$treeCur = $treeCur->addSibling("\n", 0);
bless($treeCur, "HeaderDoc::ParseTree");
$parserState->{inMacroLine} = 1;
$postPossNL = 0;
}
}
};
# Start of token-delimited functions and procedures (e.g.
# Pascal and PHP)
($part eq "$sofunction" || $part eq "$soprocedure") && do {
print STDERR "SOFUNC: CASE 10\n" if ($liteDebug);
$parserState->{sodclass} = "function";
print STDERR "K&R C FUNCTION FOUND [1].\n" if ($localDebug);
$parserState->{kr_c_function} = 1;
$parserState->{typestring} = "function";
$parserState->{startOfDec} = 2;
$parserState->{namePending} = 1;
# if (!$parserState->{seenBraces}) { # TREEDONE
# $treeNest = 1;
# $treePopTwo++;
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
# }
print STDERR "namePending -> 1 [1]\n" if ($parseDebug);
last SWITCH;
};
# C++ destructor handler.
($part =~ /\~/o && $lang eq "C" && $sublang eq "cpp" && !!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "C++ DESTRUCTOR: CASE 11\n" if ($liteDebug);
print STDERR "TILDE\n" if ($localDebug);
$parserState->{seenTilde} = 2;
$lastchar = $part;
$parserState->{onlyComments} = 0;
# $name .= '~';
last SWITCH;
};
# Objective-C method handler.
($part =~ /[-+]/o && $parserState->{onlyComments}) && do {
print STDERR "OBJC METHOD: CASE 12\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
print STDERR "OCCMETHOD\n" if ($localDebug);
# Objective C Method.
$parserState->{occmethod} = 1;
$parserState->{occmethodtype} = $part;
$lastchar = $part;
$parserState->{onlyComments} = 0;
print STDERR "[a]onlyComments -> 0\n" if ($macroDebug);
if (!$parserState->{seenBraces}) { # TREEDONE
if (!$parserState->{hollow}) {
print STDERR "SETHOLLOW -> 1\n" if ($parserStackDebug);
$sethollow = 1;
}
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [7]\n"; }
$parserState->{treePopTwo} = 1;
}
}
last SWITCH;
};
# Newline handler.
($part =~ /[\n\r]/o) && do {
print STDERR "NEWLINE: CASE 13\n" if ($liteDebug);
# NEWLINE FOUND
$treepart = $part;
if ($inRegexp) {
warn "$filename:$inputCounter: warning: multi-line regular expression\n";
}
print STDERR "NLCR\n" if ($tsDebug || $treeDebug || $localDebug);
if ($lastchar !~ /[\,\;\{\(\)\}]/o && $nextpart !~ /[\{\}\(\)]/o) {
if ($lastchar ne "*/" && $nextpart ne "/*") {
if (!$parserState->{inMacro} && !$parserState->{inMacroLine} && !$treePopOnNewLine) {
print STDERR "NL->SPC\n" if ($localDebug);
$part = " ";
print STDERR "LC: $lastchar\n" if ($localDebug);
print STDERR "NP: $nextpart\n" if ($localDebug);
$postPossNL = 2;
} else {
$parserState->{inMacroLine} = 0;
# Don't push parsed parameter here. Just clear it.
# push(@{$parserState->{parsedParamList}}, $parsedParam);
# print STDERR "pushed $parsedParam into parsedParamList [1]\n" if ($parmDebug);
print STDERR "skipped pushing CPP directive $parsedParam into parsedParamList [1]\n" if ($parmDebug || $cppDebug || $localDebug);
$parsedParam = "";
}
}
}
if ($treePopOnNewLine < 0) {
# pop once for //, possibly again for macro
$treePopOnNewLine = 0 - $treePopOnNewLine;
$treeCur = $treeCur->addSibling($treepart, 0);
bless($treeCur, "HeaderDoc::ParseTree");
# push(@treeStack, $treeCur);
$treeSkip = 1;
$treeCur = pop(@treeStack);
if (!$treeCur) {
$treeCur = $treeTop;
warn "$filename:$inputCounter: warning: Attempted to pop off top of tree\n";
}
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [1]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($treePopOnNewLine == 1 || ($treePopOnNewLine && !$parserState->isQuoted())) {
# $parserState->{lastsymbol} ne "\\"
$treeCur = $treeCur->addSibling($treepart, 0);
bless($treeCur, "HeaderDoc::ParseTree");
# push(@treeStack, $treeCur);
$treeSkip = 1;
$treeCur = pop(@treeStack);
if (!$treeCur) {
$treeCur = $treeTop;
warn "$filename:$inputCounter: warning: Attempted to pop off top of tree\n";
}
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->addSibling("", 0); # empty token
print STDERR "TSPOP [1a]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
$treePopOnNewLine = 0;
$HeaderDoc::hidetokens = 0;
} else {
print STDERR "Not popping from tree. Probably quoted.\n" if ($localDebug || $parseDebug);
}
next SWITCH;
};
# C++ template handlers
($part eq $sotemplate && !$parserState->{seenBraces} && ($parserState->{inOperator} != 1)) && do {
print STDERR "C++ TEMPLATE: CASE 14\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($HeaderDoc::hideIDLAttributes && $lang eq "C" && $sublang eq "IDL") { $hideTokenAndMaybeContents = 3; }
print STDERR "inTemplate -> ".($parserState->{inTemplate}+1)."\n" if ($localDebug);
print STDERR "SBS: " . scalar(@braceStack) . ".\n" if ($localDebug);
$parserState->{inTemplate}++;
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
$parserState->{preTemplateSymbol} = $parserState->{lastsymbol};
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{onlyComments} = 0;
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if (!$parserState->{hollow}) { $sethollow = 1; } # IDL can have this at the start of declaration.
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [8]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
print STDERR "[b]onlyComments -> 0\n" if ($macroDebug);
}
last SWITCH;
};
($part eq $eotemplate && !$parserState->{seenBraces} && ($parserState->{inOperator} != 1)) && do {
print STDERR "C++ TEMPLATE END: CASE 15\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && (!(scalar(@braceStack)-$parserState->{initbsCount}) || $parserState->{inTemplate})) {
if ($parserState->{inTemplate}) {
print STDERR "parserState->{inTemplate} -> ".($parserState->{inTemplate}-1)."\n" if ($localDebug);
$parserState->{inTemplate}--;
$parserState->{lastsymbol} = "";
$lastchar = $part;
$curline .= " ";
$parserState->{onlyComments} = 0;
print STDERR "[c]onlyComments -> 0\n" if ($macroDebug);
}
my $top = pop(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [2]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($top ne "$sotemplate") {
warn("$filename:$inputCounter: warning: Template (angle) brackets do not match.\nWe may have a problem.\n");
}
}
last SWITCH;
};
#
# Handles C++ access control state, e.g. "public:"
#
($part eq ":") && do {
print STDERR "Access control colon: CASE 16\n" if ($liteDebug);
print STDERR "TS IS \"$parserState->{typestring}\"\n" if ($localDebug || $parseDebug);
# fall through to next colon handling case if we fail.
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (length($accessregexp) && ($lastnspart =~ /$accessregexp/)) {
# We're special.
print STDERR "PERMANENT ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$parserState->{typestring} = "";
print STDERR "RESET HOLLOW at $part\n" if ($parserStackDebug);
$parserState->{hollow} = undef;
$parserState->{onlyComments} = 1;
print STDERR "hollowskip -> 1 (ACS)\n" if ($parserStateInsertDebug);
$hollowskip = 1;
$HeaderDoc::AccessControlState = $1;
$lastACS = $1;
last SWITCH;
} elsif ($parserState->{typestring} eq "struct") {
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
if (!$parserState->{structClassName}) {
$parserState->{structClassName} = $parserState->{lastsymbol};
$parserState->{bracePending} = 2;
}
}
}
}
};
(length($accessregexp) && ($part =~ /$accessregexp/)) && do {
print STDERR "Access regexp: CASE 17\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
# We're special.
if ($part =~ /^\@(.*)$/) {
print STDERR "PERMANENT ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$parserState->{typestring} = "";
print STDERR "RESET HOLLOW at $part\n" if ($parserStackDebug);
$parserState->{hollow} = undef;
$parserState->{onlyComments} = 1;
$hollowskip = 1;
print STDERR "hollowskip -> 1 (\@ACS)\n" if ($parserStateInsertDebug);
$HeaderDoc::AccessControlState = $1;
$lastACS = $1;
last SWITCH;
} else {
print STDERR "TEMPORARY ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$lastACS = $HeaderDoc::AccessControlState;
$HeaderDoc::AccessControlState = $1;
}
} else {
next SWITCH;
}
};
(length($requiredregexp) && $part =~ /$requiredregexp/) && do {
print STDERR "REQUIRED REGEXP MATCH: \"$part\"\n" if ($localDebug || $parseDebug);
$hollowskip = 1;
print STDERR "hollowskip -> 1 (requiredregexp)\n" if ($parserStateInsertDebug);
last SWITCH;
};
#
# C++ copy constructor handler. For example:
#
# char *class(void *a, void *b) :
# class(pri_type, pri_type);
#
($part eq ":") && do {
print STDERR "Copy constructor: CASE 18\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parserState->{occmethod}) {
$parserState->{name} = $parserState->{lastsymbol};
if ($parserState->{occparmlabelfound}) {
$parserState->{occmethodname} .= "$parserState->{lastsymbol}:";
if ($occMethodNameDebug) {
print STDERR "OCC method name now ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\").\n";
}
$parserState->{occparmlabelfound} = -1; # next token is name of this parameter, followed by label for next parameter.
} else {
if ($occMethodNameDebug) {
print STDERR "OCC method name missing.\n";
print STDERR "OCC method name still ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\").\n";
}
$parserState->{occparmlabelfound} = -2; # Special case: grab the parameter name instead because parameter has no label.
}
# Start doing line splitting here.
# Also, capture the method's name.
if ($parserState->{occmethod} == 1) {
$parserState->{occmethod} = 2;
if (!$prespace) { $prespaceadjust = 4; }
$parserState->{onlyComments} = 0;
print STDERR "[d]onlyComments -> 0\n" if ($macroDebug);
}
} else {
if ($lang eq "C" && $sublang eq "cpp") {
if (!(scalar(@braceStack)-$parserState->{initbsCount}) && $parserState->{sodclass} eq "function") {
$inPrivateParamTypes = 1;
$declaration .= "$curline";
$publicDeclaration = $declaration;
$declaration = "";
} else {
next SWITCH;
}
if (!$parserState->{stackFrozen}) {
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
# print STDERR "SEOPPLS\n";
# for my $item (@{$parserState->{pplStack}}) {
# print STDERR "PPLS: $item\n";
# }
# print STDERR "OEOPPLS\n";
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
} else {
next SWITCH;
}
}
if (!$parserState->{seenBraces} && !$parserState->{occmethod}) { # TREEDONE
# $treeCur->addSibling($part, 0); $treeSkip = 1;
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [9]\n"; }
$parserState->{treePopTwo} = 1;
# $treeCur = pop(@treeStack) || $treeTop;
# bless($treeCur, "HeaderDoc::ParseTree");
}
last SWITCH;
} else {
next SWITCH;
}
};
# Non-newline, non-carriage-return whitespace handler.
($part =~ /\s/o) && do {
print STDERR "Whitespace: CASE 19\n" if ($liteDebug);
# just add white space silently.
# if ($part eq "\n") { $parserState->{lastsymbol} = ""; };
$lastchar = $part;
last SWITCH;
};
# backslash handler (largely useful for macros, strings).
($part =~ /\\/o) && do {
print STDERR "BACKSLASH: CASE 20\n" if ($liteDebug);
$parserState->{lastsymbol} = $part; $lastchar = $part;
$parserState->addBackslash();
};
# quote and bracket handlers.
($part eq "\"") && do {
print STDERR "DOUBLE QUOTE: CASE 21\n" if ($liteDebug);
print STDERR "dquo\n" if ($localDebug);
# print STDERR "QUOTEDEBUG: CURSTRING IS '$curstring'\n";
# print STDERR "QUOTEDEBUG: CURLINE IS '$curline'\n";
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{onlyComments} = 0;
print STDERR "[e]onlyComments -> 0\n" if ($macroDebug);
print STDERR "LASTTOKEN: $lasttoken\nCS: $curstring\n" if ($localDebug);
# if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o))
if (!$parserState->isQuoted($lang, $sublang)) {
if (!$parserState->{inString}) {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [10]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} else {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [3]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
$parserState->{inString} = (1-$parserState->{inString});
}
}
$lastchar = $part;
$parserState->{lastsymbol} = "";
last SWITCH;
};
($part eq "[") && do {
print STDERR "LEFT BRACKET: CASE 22\n" if ($liteDebug);
# left square bracket (square brace)
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
print STDERR "lbracket\n" if ($localDebug);
print STDERR "LBRACKET DEBUG TRACE: SODNAME: ".$parserState->{sodname}." SODTYPE: ".$parserState->{sodtype}." SIMPLETDCONTENTS: ".$parserState->{simpleTDcontents}."\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
$parserState->{onlyComments} = 0;
print STDERR "[f]onlyComments -> 0\n" if ($macroDebug);
}
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [11]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$parserState->{inBrackets} += 1;
}
$lastchar = $part;
last SWITCH;
};
($part eq "]") && do {
print STDERR "CLOSE BRACKET: CASE 23\n" if ($liteDebug);
# right square bracket (square brace)
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
print STDERR "rbracket\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
$parserState->{onlyComments} = 0;
print STDERR "[g]onlyComments -> 0\n" if ($macroDebug);
}
my $top = pop(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [4]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($top ne "[") {
warn("$filename:$inputCounter: warning: Square brackets do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
}
pbs(@braceStack);
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$parserState->{inBrackets} -= 1;
}
$lastchar = $part;
last SWITCH;
};
($part eq "'") && do {
print STDERR "SINGLE QUOTE: CASE 24\n" if ($liteDebug);
print STDERR "squo\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
# if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o))
if (!$parserState->isQuoted($lang, $sublang)) {
$parserState->{onlyComments} = 0;
print STDERR "[h]onlyComments -> 0\n" if ($macroDebug);
if (!$parserState->{inChar}) {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [12]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} else {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [5]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
$parserState->{inChar} = !$parserState->{inChar};
}
if ($lastchar =~ /\=$/o) {
$curline .= " ";
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Inline comment (two slashes in c++, hash in perl/shell)
# handler.
(($part eq $ilc || $part eq $ilc_b) && ($lang ne "perl" || $lasttoken ne "\$")) && do {
print STDERR "SINGLE LINE COMMENT: CASE 25\n" if ($liteDebug);
print STDERR "ILC\n" if ($localDebug || $ilcDebug);
if (!($parserState->{inComment} || $parserState->{inChar} || $parserState->{inString} || $inRegexp)) {
$parserState->{inInlineComment} = 4;
print STDERR "inInlineComment -> 1\n" if ($ilcDebug);
$curline = spacefix($curline, $part, $lastchar, $soc, $eoc, $ilc, $ilc_b);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [13]\n"; }
if (!$treePopOnNewLine) {
$treePopOnNewLine = 1;
} else {
$treePopOnNewLine = 0 - $treePopOnNewLine;
}
print STDERR "treePopOnNewLine -> $treePopOnNewLine\n" if ($ilcDebug);
# $treeCur->addSibling($part, 0); $treeSkip = 1;
# $treePopOnNewLine = 1;
# $treeCur = pop(@treeStack) || $treeTop;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif ($parserState->{inComment}) {
my $linenum = $inputCounter + $fileoffset;
if (!$cpp_in_argparse) {
# We've already seen these.
if ($nestedcommentwarn) {
warn("$filename:$linenum: warning: Nested comment found [1]. Ignoring.\n");
}
# This isn't really a problem.
# Don't warn to avoid bogus
# warnings for apple_ref and
# URL markup in comments.
}
# warn("XX $cpp_in_argparse XX $inputCounter XX $fileoffset XX\n");
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Standard comment handlers: soc = start of comment,
# eoc = end of comment.
($part eq $soc) && do {
print STDERR "START OF MULTILINE COMMENT: CASE 26\n" if ($liteDebug);
print STDERR "SOC\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{inComment} = 4;
$curline = spacefix($curline, $part, $lastchar);
if (!$parserState->{seenBraces}) {
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [14]\n"; }
# print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug);
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild("", 0);
# bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif ($parserState->{inComment}) {
my $linenum = $inputCounter + $fileoffset;
# Modern compilers shouldn't have trouble with this. It occurs |
# frequently in apple_ref markup (e.g. //apple_ref/C/instm/ \|/
# IOFireWireDeviceInterface/AddIsochCallbackDispatcherToRunLoop/*Add
# IsochCallbackDispatcherToRunLoopIOFireWireLibDeviceRefCFRunLoopRef)
if ($nestedcommentwarn) {
warn("$filename:$linenum: warning: Nested comment found [2]. Ignoring.\n");
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
($part eq $eoc) && do {
print STDERR "END OF MULTILINE COMMENT: CASE 27\n" if ($liteDebug);
print STDERR "EOC\n" if ($localDebug);
if ($parserState->{inComment} && !($parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{inComment} = 0;
$curline = spacefix($curline, $part, $lastchar);
$ppSkipOneToken = 1;
if (!$parserState->{seenBraces}) {
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif (!$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && !$inRegexp) {
my $linenum = $inputCounter + $fileoffset;
warn("$filename:$linenum: warning: Unmatched close comment tag found. Ignoring.\n");
} elsif ($parserState->{inInlineComment}) {
my $linenum = $inputCounter + $fileoffset;
# We'll leave this one on for now.
if ((1 || $nestedcommentwarn) && (!$HeaderDoc::test_mode)) {
warn("$filename:$linenum: warning: Nested comment found [3]. Ignoring.\n");
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Parenthesis and brace handlers.
($part eq "(") && do {
print STDERR "OPEN PAREN: CASE 28\n" if ($liteDebug);
my @tempppl = undef;
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
if (!(scalar(@braceStack)-$parserState->{initbsCount})) {
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
print STDERR "parsedParamList wiped\n" if ($parmDebug);
@tempppl = @{$parserState->{parsedParamList}};
@{$parserState->{parsedParamList}} = ();
$parsedParam = "";
}
$parserState->{onlyComments} = 0;
print STDERR "[i]onlyComments -> 0\n" if ($macroDebug);
if ($parserState->{simpleTypedef} && !(scalar(@braceStack)- $parserState->{initbsCount})) {
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "Setting typedef sodname to ".$parserState->{lastsymbol}."\n" if ($localDebug || $sodDebug);
$parserState->{sodname} = $parserState->{lastsymbol};
$parserState->{sodclass} = "function";
# DAG: changed to respect freezereturn
# and hollow, but in the unlikely event
# that we should start seeing any weird
# "missing return type info" bugs,
# this next line might need to be
# put back in rather than the lines
# that follow it.
# $parserState->{returntype} = "$declaration$curline";
if (!$parserState->{freezereturn} && $parserState->{hollow}) {
$parserState->{returntype} = "$declaration$curline";
} elsif (!$parserState->{freezereturn} && !$parserState->{hollow}) {
$parserState->{returntype} = "$curline";
$declaration = "";
}
}
$parserState->{posstypesPending} = 0;
if ($parserState->{callbackNamePending} == 2) {
$parserState->{callbackNamePending} = 3;
print STDERR "callbackNamePending -> 3\n" if ($localDebug || $cbnDebug);
}
print STDERR "lparen\n" if ($localDebug);
if ($parserState->{cbsodname} && (scalar(@braceStack)-$parserState->{initbsCount}) == 0) {
if (!$parserState->{functionReturnsCallback}) {
# At the top level, if we see a second open parenthesis after setting a callback
# name, the first token in the first set of open parentheses is the name of
# the callback, so clear cbsodname.
#
# Until this point, the value in cbsodname was a copy of the already-cleared
# sodname field, and would replace the callbackName field at the end of
# processing.
$parserState->{cbsodname} = "";
} else {
# If we are in a function that returns a callback, everything from here on
# is a list of parameters for the callback, not the function, so the
# previous parameter list should be discarded (though it is useful to
# add these parameters as valid things to comment about)
@{$parserState->{parsedParamList}} = @tempppl;
$parserState->{functionReturnsCallback}--;
print STDERR "parsedParamList restored\n" if ($parmDebug);
}
}
if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) {
if ($parserState->{callbackName}) {
$parserState->{cbsodname} = $parserState->{callbackName};
$parserState->{sodclass} = "function";
# $parserState->{callbackName} = "";
$parserState->{functionReturnsCallback}++;
print "Function returning callback. NAME: $parserState->{cbsodname}\n" if ($parmDebug || $localDebug || $parseDebug);
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
print STDERR "parsedParamList wiped\n" if ($parmDebug);
@tempppl = @{$parserState->{parsedParamList}};
@{$parserState->{parsedParamList}} = ();
$parsedParam = "";
}
}
if ($parserState->{inOperator} == 1) {
$parserState->{inOperator} = 2;
}
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [15]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
print STDERR "LASTCHARCHECK: \"$lastchar\" \"$lastnspart\" \"$curline\".\n" if ($localDebug);
if ($lastnspart eq ")") { # || $curline =~ /\)\s*$/so
print STDERR "HERE: DEC IS $declaration\nENDDEC\nCURLINE IS $curline\nENDCURLINE\n" if ($localDebug);
# print STDERR "CALLBACKMAYBE: $parserState->{callbackNamePending} $parserState->{sodclass} ".scalar(@braceStack)."\n";
print STDERR "SBS: ".scalar(@braceStack)."\n" if ($localDebug);
### if (!$parserState->{callbackNamePending} && ($parserState->{sodclass} eq "function") && ((scalar(@braceStack)-$parserState->{initbsCount}) == 1)) { # && $argparse
### # Guess it must be a callback anyway.
### my $temp = pop(@tempppl);
### $parserState->{callbackName} = $temp;
### $parserState->{name} = "";
### $parserState->{sodclass} = "";
### $parserState->{sodname} = "";
### print STDERR "CALLBACKHERE ($temp)!\n" if ($cbnDebug || $parseDebug);
### }
if ($declaration =~ /.*\n(.*?)\n$/so) {
my $lastline = $1;
print STDERR "LL: $lastline\nLLDEC: $declaration" if ($localDebug);
$declaration =~ s/(.*)\n(.*?)\n$/$1\n/so;
$curline = "$lastline $curline";
$curline =~ s/^\s*//so;
$prespace -= 4;
$prespaceadjust += 4;
$forcenobreak = 1;
print STDERR "NEWDEC: $declaration\nNEWCURLINE: $curline\n" if ($localDebug);
} elsif (length($declaration) && $callback_typedef_and_name_on_one_line) {
print STDERR "SCARYCASE\n" if ($localDebug);
$declaration =~ s/\n$//so;
$curline = "$declaration $curline";
$declaration = "";
$prespace -= 4;
$prespaceadjust += 4;
$forcenobreak = 1;
}
} else { print STDERR "OPARENLC: \"$lastchar\"\nCURLINE IS: \"$curline\"\n" if ($localDebug);}
$parserState->{lastsymbol} = "";
$lastchar = $part;
if ($parserState->{startOfDec} == 2) {
$parserState->{sodclass} = "function";
$parserState->{freezereturn} = 1;
$parserState->{returntype} =~ s/^\s*//so;
$parserState->{returntype} =~ s/\s*$//so;
}
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
print STDERR "OUTGOING CURLINE: \"$curline\"\n" if ($localDebug);
last SWITCH;
};
($part eq ")") && do {
print STDERR "CLOSE PAREN: CASE 29\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate && (peek(\@regexpStack) ne "("))) {
if ((scalar(@braceStack)-$parserState->{initbsCount} - $parserState->{functionReturnsCallback}) == 1) {
# stop parameter parsing
$parsedParamParse = 0;
print STDERR "parsedParamParse -> 0\n" if ($parmDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if ($parsedParam ne "void") {
# ignore foo(void)
push(@{$parserState->{parsedParamList}}, $parsedParam);
print STDERR "pushed $parsedParam into parsedParamList [1]\n" if ($parmDebug);
}
$parsedParam = "";
}
$parserState->{onlyComments} = 0;
print STDERR "[j]onlyComments -> 0\n" if ($macroDebug);
print STDERR "rparen\n" if ($localDebug);
my $test = pop(@braceStack); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6a]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if (!($test eq "(")) { # ) brace hack for vi
warn("$filename:$inputCounter: warning: Parentheses do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
# cluck("backtrace follows\n");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace -= 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust -= 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
(casecmp($part, $lbrace, $case_sensitive)) && do {
print STDERR "LEFT BRACE: CASE 30\n" if ($liteDebug);
if ($parserState->{onlyComments} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inChar} && !($inRegexp && $regexpNoInterpolate) && scalar(@parserStack)) {
# Somebody put in a brace in the middle of
# a class or else we're seeing ObjC private
# class bits. Either way, throw away the
# curly brace.
print STDERR "NOINSERT\n" if ($parserStackDebug);
$pushParserStateAtBrace = 1;
# $setNoInsert = 1;
$parserState->{noInsert} = 1;
}
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
$parserState->{bracePending} = 0;
print STDERR "bracePending -> 0 [brace]\n" if ($localDebug);
$parserState->{onlyComments} = 0;
print STDERR "[k]onlyComments -> 0\n" if ($macroDebug);
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
# print STDERR "statecheck: ".$parserState->{inClass}."X".$parserState->{sodclass}."X".$parserState->{inOperator}."X".$parserState->{occmethod}."\n"; # @@@ CHECKME - Do this for Obj-C methods too?
if (!$parserState->{inClass} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator} || $parserState->{occmethod})) {
# This is the opening brace of a function. Start ignoring everything
# until the matching brace is encountered.
print "seenBraces -> 1\n" if ($parseDebug);
$parserState->{seenBraces} = 1;
if (!$parserState->{stackFrozen}) {
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
@{$parserState->{pplStack}} = ();
}
$parserState->{posstypesPending} = 0;
$parserState->{namePending} = 0;
$parserState->{callbackNamePending} = -1;
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "callbackNamePending -> -1\n" if ($localDebug || $cbnDebug);
print STDERR "lbrace\n" if ($localDebug);
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [16]\n"; }
print STDERR "TN -> 1\n" if ($localDebug);
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
if ($parserState->{INMODULE} == 2) {
# Drop token on the floor.
$treepart = " ";
}
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
(casecmp($part, $rbrace, $case_sensitive)) && do {
print STDERR "RIGHT BRACE: CASE 31\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate && (peek(\@regexpStack) ne "$lbrace"))) {
my $oldOC = $parserState->{onlyComments};
print STDERR "rbrace???\n" if ($localDebug);
# $parserState->{onlyComments} = 0; # If this is all we've seen, there's either a bug or we're
# unrolling a class or similar anyway.
print STDERR "[l]onlyComments -> 0\n" if ($macroDebug);
my $bsCount = scalar(@braceStack);
if (scalar(@parserStack) && !($bsCount - $parserState->{initbsCount})) {
print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug);
if ($parserState->{noInsert} || $oldOC) {
print STDERR "parserState insertion skipped[RBRACE]\n" if ($parserStackDebug || $parserStateInsertDebug);
} elsif ($parserState->{hollow}) {
print STDERR "inserted parser state into tree [RBRACE]\n" if ($parserStateInsertDebug);
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[1].\n";
}
print STDERR "parserState popped from parserStack[rbrace]\n" if ($parserStackDebug);
# print STDERR "PREINMODULE: ".$parserState->{INMODULE}."\n";
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
# print STDERR "INMODULE: ".$parserState->{INMODULE}."\n";
if ($parserState->{INMODULE} == 2) {
# Drop token on the floor.
print STDERR "CURRENT: ".$treeCur->{TOKEN}."\n" if ($localDebug);
$part = "";
print STDERR "INMODULE -> 3\n" if ($localDebug || $moduleDebug);
$parserState->{INMODULE} = 3;
print STDERR "continue -> 0 [1a]\n" if ($localDebug || $liteDebug);
$parserState->{noInsert} = 0;
$continue = 0;
print STDERR "AT END: REALPS IS ".$parserState->{REALPS}."\n" if ($parserStackDebug || $localDebug);
print STDERR "STACK COUNT: ".scalar(@parserStack)."\n" if ($parserStackDebug || $localDebug);
}
if ($lang eq "php" || ($lang eq "C" && $sublang eq "IDL")) {
# print STDERR "PHP OUT OF BRACES?: ".scalar(@braceStack)."\n";
if (scalar(@braceStack) == 1) {
# PHP and IDL classes end at
# the brace.
print STDERR "continue -> 0 [1a]\n" if ($localDebug || $liteDebug);
$continue = 0;
}
}
if ($parserState->{noInsert} && scalar(@parserStack)) {
# This is to handle the end of
# the private vars in an
# Objective C class.
print STDERR "parserState: Hit me.\n" if ($localDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
# It's about to go down by 1.
$parserState->{initbsCount} = scalar(@braceStack) - 1;
}
# $parserState->{onlyComments} = 1;
} else {
print STDERR "NO CHANGE IN PARSER STATE STACK (nPARSERSTACK = ".scalar(@parserStack).", $bsCount != $parserState->{initbsCount})\n" if ($parseDebug || $parserStackDebug);
}
if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) {
# stop parameter parsing
$parsedParamParse = 0;
print STDERR "parsedParamParse -> 0\n" if ($parmDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) {
# ignore foo(void)
push(@{$parserState->{parsedParamList}}, $parsedParam);
print STDERR "pushed $parsedParam into parsedParamList [1b]\n" if ($parmDebug);
}
$parsedParam = "";
} else {
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
}
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
print STDERR "rbrace\n" if ($localDebug);
my $test = pop(@braceStack); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [7]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if (!($test eq "$lbrace") && (!length($structname) || (!($test eq $structname) && $structisbrace))) {
warn("$filename:$inputCounter: warning: Braces do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace -= 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust -= 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
# Typedef, struct, enum, and union handlers.
# Merge the '@' symbol onto @protocol, @property, @public, and similar.
(length($part) && length($nextpart) && ((length($propname) && $propname =~ /\@/) || length($objcdynamicname) || length($objcsynthesizename) || length($classregexp) || (length($accessregexp) && $accessregexp =~ /\@/)) && $part =~ /^\@$/ && !$parserState->{inComment} && !$parserState->{inChar} && !$parserState->{inString} && !$parserState->{inInlineComment}) && do {
print STDERR "PROPERTY PREPEND AT (\@): CASE 32\n" if ($liteDebug);
my $temp = "\@".$nextpart;
# print STDERR "TEMP IS $temp PROPNAME is $propname\n";
if ($temp =~ /$accessregexp/) {
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
$parserState->{classIsObjC} = 1;
} elsif ($temp =~ /$classregexp/) {
$nextpart = "\@".$nextpart;
$parserState->{classIsObjC} = 1;
} elsif ($temp =~ /$classclosebraceregexp/) {
$nextpart = "\@".$nextpart;
} elsif ($temp eq $propname) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif (length($requiredregexp) && $temp =~ /$requiredregexp/) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif ($temp eq $objcdynamicname) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif ($temp eq $objcsynthesizename) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
}
next SWITCH;
};
($modules_are_special && !$parserState->{inTemplate} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && length($moduleregexp) && $part =~ /$moduleregexp/) && do {
print STDERR "INMODULE -> 1\n" if ($localDebug || $moduleDebug);
$parserState->{INMODULE} = 1;
print STDERR "MODULE START TOKEN: CASE 32-M-1\n" if ($localDebug || $liteDebug);
};
(length($classclosebraceregexp) && ($part =~ /$classclosebraceregexp/) && !$parserState->{inComment} && !$parserState->{inChar} && !$parserState->{inString} && !$parserState->{inInlineComment}) && do {
print STDERR "CLASS CLOSE BRACE: CASE 33\n" if ($liteDebug);
if ($part ne peekmatch(\@braceStack, $filename, $inputCounter)) {
warn("$filename:inputCounter: warning: Class braces do not match.\nWe may have a problem.\n");
}
$parserState->{seenBraces} = 1;
pop(@braceStack);
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
$part =~ s/^\@//s;
if ( 1 || $nextpart ne ";") {
# Objective C protocol/interface declarations end at the close curly brace.
# No ';' necessary (though we'll eat it if it's there.
# No, we won't. Deal with it.
if (scalar(@parserStack) == 1) {
# Throw away current parser state, since
# it will always be empty anyway.
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
$continue = 0;
print STDERR "continue -> 0 [occend]\n" if ($localDebug);
} else {
if (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[\@end]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
print STDERR "inserted parser state into tree [\@end]\n" if ($parserStateInsertDebug);
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[2].\n";
}
print STDERR "parserState: Created parser state[1].\n" if ($parserStackDebug);
print STDERR "CURLINE CLEAR[PRS2]\n" if ($localDebug);
$curline = "";
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
}
print STDERR "parserState popped from parserStack[\@end]\n" if ($parserStackDebug);
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
}
}
# fall through to next case. WHY???
};
(!$parserState->{inTemplate} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && length($classregexp) && $part =~ /$classregexp/) && do {
print STDERR "START OF CLASS: CASE 34\n" if ($liteDebug);
### if ($parserState->{classIsObjC}) { $sublang = "occ"; }
### else { $sublang = "cpp"; }
### print STDERR "LANG $lang SUBLANG $sublang\n" if ($localDebug || $parseDebug || $classDebug);
### # Update the class regular expressions because our language has changed.
### ($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
### $soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
### $enumname,
### $typedefname, $varname, $constname, $structisbrace, $macronameref,
### $classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
### $requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
### print STDERR "PROPNAME NOW $propname\n" if ($localDebug || $parseDebug || $classDebug);
my $localclasstype = $1;
if ($part =~ /^\@/) { $part =~ s/^\@//s; }
if (!(scalar(@braceStack)-$parserState->{initbsCount})) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
print STDERR "ITISACLASS\n" if ($localDebug);
if (!length($parserState->{sodclass})) {
print STDERR "GOOD.\n" if ($localDebug);
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [7]\n" if ($classDebug);
$pushParserStateAtBrace = 1;
if ($localclasstype =~ /\@interface/) {
$parserState->{inClass} = 2;
print STDERR "inClass -> 2 [8]\n" if ($classDebug);
$pushParserStateAtBrace = 0;
} elsif ($localclasstype =~ /\@protocol/) {
$pushParserStateAtBrace = 0;
$pushParserStateAfterWordToken = 0;
$parserState->{inClass} = 0;
print STDERR "inClass -> 0 [9]\n" if ($classDebug);
$parserState->{inProtocol} = 1;
} elsif ($localclasstype =~ /\@implementation/) {
$pushParserStateAtBrace = 0;
$pushParserStateAfterWordToken = 2;
}
$parserState->{sodclass} = "class";
$parserState->{classtype} = $localclasstype;
$parserState->{preclasssodtype} = $parserState->{sodtype} . $part;
$parserState->{sodtype} = "";
$parserState->{startOfDec} = 1;
$parserState->{onlyComments} = 0;
print STDERR "[m]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
# Get the parse tokens from Utilities.pm.
if (length($classbraceregexp) && ($localclasstype =~ /$classbraceregexp/)) {
print STDERR "CLASS ($localclasstype) IS A BRACE.\n" if ($localDebug);
push(@braceStack, $localclasstype); pbs(@braceStack);
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [17]\n"; }
# } else {
# print STDERR "CBRE: \"$classbraceregexp\"\n";
}
($lang, $sublang) = getLangAndSublangFromClassType($localclasstype);
$HeaderDoc::lang = $lang;
$HeaderDoc::sublang = $sublang;
($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
$soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
$enumname,
$typedefname, $varname, $constname, $structisbrace, $macronameref,
$classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
$requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
my $macrore = macroRegexpFromList($macronameref);
# print STDERR "PROPNAME2: $propname\n";
print STDERR "ARP: $accessregexp\n" if ($localDebug);
last SWITCH;
}
}
}
};
($part eq $objcdynamicname) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $objcsynthesizename) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $propname) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $structname || $part eq $enumname || $part eq $unionname) && do {
print STDERR "STRUCT/ENUM/UNION: CASE 36\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($structisbrace) {
if ($parserState->{sodclass} eq "function") {
$parserState->{seenBraces} = 1;
if (!$parserState->{stackFrozen}) {
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
@{$parserState->{pplStack}} = ();
}
$parserState->{posstypesPending} = 0;
$parserState->{callbackNamePending} = -1;
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "callbackNamePending -> -1\n" if ($localDebug || $cbnDebug);
print STDERR "lbrace\n" if ($localDebug);
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [18]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
} else {
if (!$parserState->{simpleTypedef}) {
print STDERR "simpleTypedef -> 2\n" if ($localDebug);
$parserState->{simpleTypedef} = 2;
}
# if (!$parserState->{seenBraces}) { # TREEDONE
# $treePopTwo++;
# $treeNest = 1;
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
# }
}
$parserState->{onlyComments} = 0;
print STDERR "[n]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
# $parserState->{simpleTypedef} = 0;
if ($parserState->{basetype} eq "") { $parserState->{basetype} = $part; }
# fall through to default case when we're done.
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString} || $parserState->{inChar})) {
$parserState->{namePending} = 2;
print STDERR "namePending -> 2 [2]\n" if ($parseDebug);
if ($parserState->{posstypesPending}) { $parserState->{posstypes} .=" $part"; }
}
if ($parserState->{sodclass} eq "") {
$parserState->{startOfDec} = 0; $parserState->{sodname} = "";
print STDERR "sodname cleared (seu)\n" if ($sodDebug);
}
$lastchar = $part;
}; # end if
}; # end do
($part =~ /^$typedefname$/) && do {
print STDERR "TYPEDEF: CASE 37\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (!(scalar(@braceStack)-$parserState->{initbsCount})) { $parserState->{callbackIsTypedef} = 1; $parserState->{inTypedef} = 1; }
$parserState->{onlyComments} = 0;
print STDERR "[o]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
$parserState->{simpleTypedef} = 1; print STDERR "simpleTypedef -> 1\n" if ($localDebug);
# previous case falls through, so be explicit.
if ($part =~ /^$typedefname$/) {
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString} || $parserState->{inChar})) {
if ($pascal) {
$parserState->{namePending} = 2;
$inPType = 1;
print STDERR "namePending -> 2 [3]\n" if ($parseDebug);
}
if ($parserState->{posstypesPending}) { $parserState->{posstypes} .=" $part"; }
if (!($parserState->{callbackNamePending})) {
print STDERR "callbackNamePending -> 1\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 1;
}
}
}
if ($parserState->{sodclass} eq "") {
$parserState->{startOfDec} = 0; $parserState->{sodname} = "";
print STDERR "sodname cleared ($typedefname)\n" if ($sodDebug);
}
$lastchar = $part;
}; # end if
}; # end do
# C++ operator keyword handler
($part eq "$operator") && do {
print STDERR "OPERATOR KEYWORD: CASE 38\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{inOperator} = 1;
$parserState->{sodname} = "";
}
$parserState->{lastsymbol} = $part;
$lastchar = $part;
last SWITCH;
# next;
};
# Punctuation handlers
($part =~ /;/o) && do {
print STDERR "SEMICOLON: CASE 39\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parsedParamParse) {
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) { push(@{$parserState->{parsedParamList}}, $parsedParam); }
print STDERR "pushed $parsedParam into parsedParamList [2semi]\n" if ($parmDebug);
$parsedParam = "";
}
# skip this token
$parsedParamParse = 2;
$parserState->{freezereturn} = 1;
# $parserState->{onlyComments} = 0; # If this is all we've seen, there's either a bug or we're
# unrolling a class or similar anyway.
$parserState->{temponlyComments} = $parserState->{onlyComments};
print STDERR "[p]onlyComments -> 0\n" if ($macroDebug);
print STDERR "valuepending -> 0\n" if ($valueDebug);
$parserState->{valuepending} = 0;
$continuation = 1;
if ($parserState->{occmethod}) {
$prespaceadjust = -$prespace;
}
# previous case falls through, so be explicit.
if ($part =~ /;/o && !$parserState->{inMacroLine} && !$parserState->{inMacro}) {
my $bsCount = scalar(@braceStack)-$parserState->{initbsCount};
if (!$bsCount && !$parserState->{kr_c_function}) {
if ($parserState->{startOfDec} == 2) {
$parserState->{sodclass} = "constant";
$parserState->{startOfDec} = 1;
} elsif (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{startOfDec} = 1;
}
# $parserState->{lastsymbol} .= $part;
}
if (!$bsCount) {
$treeCur = $treeCur->addSibling(";"); $treepart = " "; # $treeSkip = 1;
if (0) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [8]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
# $parserState->{lastTreeNode} = $treeCur;
# print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n";
while ($parserState->{treePopTwo}--) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [9]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
$parserState->{treePopTwo} = 0;
}
}
$lastchar = $part;
}; # end if
}; # end do
($part eq "=" && ($parserState->{lastsymbol} ne "operator") && (!(($parserState->{inOperator} == 1) && $parserState->{lastsymbol} =~ /\W/ && $parserState->{lastsymbol} =~ /\S/)) && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "EQUALS: CASE 40\n" if ($liteDebug);
$parserState->{onlyComments} = 0;
print STDERR "[q]onlyComments -> 0\n" if ($macroDebug);
if ($part =~ /=/o && !(scalar(@braceStack)-$parserState->{initbsCount}) &&
$nextpart !~ /=/o && $lastchar !~ /=/o &&
$parserState->{sodclass} ne "function" && !$inPType) {
print STDERR "valuepending -> 1\n" if ($valueDebug);
$parserState->{valuepending} = 1;
$parserState->{preEqualsSymbol} = $parserState->{lastsymbol};
$parserState->{sodclass} = "constant";
$parserState->{startOfDec} = 0;
}; # end if
}; # end do
($part =~ /,/o) && do {
print STDERR "COMMA: CASE 41\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{onlyComments} = 0;
print STDERR "[r]onlyComments -> 0\n" if ($macroDebug);
}
if ($part =~ /,/o && $parsedParamParse && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && ((scalar(@braceStack)-$parserState->{initbsCount}-$parserState->{functionReturnsCallback}) == 1) && (peek(\@braceStack) eq '(' || peek(\@braceStack) eq '{')) {
print STDERR "$part is a comma\n" if ($localDebug || $parseDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) { push(@{$parserState->{parsedParamList}}, $parsedParam); }
print STDERR "pushed $parsedParam into parsedParamList [2]\n" if ($parmDebug);
$parsedParam = "";
# skip this token
$parsedParamParse = 2;
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
}; # end if
}; # end do
($part =~ /[*^]/) && do {
if ($lastnspart eq "(" && # ")"
!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) &&
!$parserState->{callbackNamePending} &&
((scalar(@braceStack)-$parserState->{initbsCount}) == 1)) {
# print "CBNP\n";
$parserState->{callbackNamePending} = 3;
}
# Fall through to the default case.
}; # end star/asterisk/caret case
{ # SWITCH default case
print STDERR "DEFAULT CASE: CASE 42\n" if ($liteDebug);
# Handler for all other text (data types, string contents,
# comment contents, character contents, etc.)
print STDERR "DEFAULT CASE\n" if ($localDebug || $parseDebug);
# print STDERR "TEST CURLINE IS \"$curline\".\n";
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (!ignore($part, $ignoreref, $perheaderignoreref)) {
if ($part =~ /\S/o) {
$parserState->{onlyComments} = 0;
print STDERR "[s]onlyComments -> 0\n" if ($macroDebug);
}
if (!$continuation && !$occspace) {
$curline = spacefix($curline, $part, $lastchar);
} else {
$continuation = 0;
$occspace = 0;
}
# print STDERR "BAD CURLINE IS \"$curline\".\n";
if (length($part) && !($parserState->{inComment} || $parserState->{inInlineComment})) {
if ($localDebug && $lastchar eq ")") {print STDERR "LC: $lastchar\nPART: $part\n";}
# print STDERR "XXX LC: $lastchar SC: $parserState->{sodclass} LG: $lang\n";
if ($lastchar eq ")" && $parserState->{sodclass} eq "function" && ($lang eq "C" || $lang eq "Csource") && !(scalar(@braceStack)-$parserState->{initbsCount})) {
if ($part !~ /^\s*;/o) {
# warn "K&R C FUNCTION FOUND.\n";
# warn "NAME: $parserState->{sodname}\n";
if (!isKeyword($part, $keywordhashref, $case_sensitive)) {
my $tempavail = ignore($part, $ignoreref, $perheaderignoreref);
if (!$tempavail) {
print STDERR "K&R C FUNCTION FOUND [2].\n" if ($localDebug);
print STDERR "TOKEN: \"$part\"\n" if ($localDebug);
print STDERR "TA: \"$tempavail\"\n" if ($localDebug);
$parserState->{kr_c_function} = 1;
$parserState->{kr_c_name} = $parserState->{sodname};
$parsedParamParse = 1;
print STDERR "parsedParamParse -> 1\n" if ($parmDebug);
}
}
}
}
$lastchar = $part;
if ($part =~ /\w/o || $part eq "::") {
if ($parserState->{callbackNamePending} == 1) {
if (!($part eq $structname || $part eq $enumname || $part eq $unionname || $part eq $typedefname)) {
# we've seen the initial type. The name of
# the callback is after the next open
# parenthesis.
print STDERR "callbackNamePending -> 2\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 2;
}
} elsif ($parserState->{callbackNamePending} == 3) {
print STDERR "callbackNamePending -> 4\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 4;
$parserState->{callbackName} = $part;
$parserState->{name} = "";
$parserState->{sodclass} = "";
$parserState->{cbsodname} = $parserState->{sodname};
$parserState->{sodname} = "";
} elsif ($parserState->{callbackNamePending} == 4) {
if ($part eq "::") {
print STDERR "callbackNamePending -> 5\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 5;
$parserState->{callbackName} .= $part;
} elsif ($part !~ /\s/o) {
print STDERR "callbackNamePending -> 0\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 0;
}
} elsif ($parserState->{callbackNamePending} == 5) {
if ($part !~ /\s/o) {
print STDERR "callbackNamePending -> 4\n" if ($localDebug || $cbnDebug);
if ($part !~ /\*/ && $part !~ /\^/) {
$parserState->{callbackNamePending} = 4;
}
$parserState->{callbackName} .= $part;
}
}
if ($parserState->{namePending} == 2) {
$parserState->{namePending} = 1;
print STDERR "namePending -> 1 [4]\n" if ($parseDebug);
if (!(scalar(@braceStack)-$parserState->{initbsCount}) && ($parserState->{simpleTypedef} == 2)) {
print STDERR "bracePending -> 1\n" if ($localDebug);
$parserState->{bracePending} = 1;
}
} elsif ($parserState->{namePending}) {
if ($parserState->{name} eq "") { $parserState->{name} = $part; }
$parserState->{namePending} = 0;
print STDERR "namePending -> 0 [5]\n" if ($parseDebug);
} elsif ($parserState->{bracePending} == 1) {
if ($part eq "::") {
# struct foo::bar ....
# "foo::bar" is the name of
# the struct and should not
# trigger this (though we might
# trigger it on the following
# word.
print STDERR "bracePending -> 2 [classmember]\n" if ($localDebug);
$parserState->{bracePending} = 2;
} else {
# Word token when brace pending. It's
# a variable.
print STDERR "IT'S A VARIABLE! NAME WAS \"$part\".\n" if ($localDebug);
print STDERR "Word token before brace. Setting sodname to ".$parserState->{lastsymbol}."\n" if ($localDebug || $sodDebug);
$parserState->{sodname} = $part;
# $parserState->{sodtype} = $parserState->{returntype}; # . " " . $parserState->{name};
$parserState->{sodtype} = "$declaration$curline";
$parserState->{sodclass} = "constant";
$parserState->{frozensodname} = $part;
print STDERR "bracePending -> 0 [word]\n" if ($localDebug);
$parserState->{bracePending} = 0;
}
} elsif ($parserState->{bracePending} == 2) {
$parserState->{bracePending}--;
}
} # end if ($part =~ /\w/o)
if ($part !~ /[,;\[\]]/o && !$parserState->{inBrackets}) {
my $opttilde = "";
if ($parserState->{seenTilde}) { $opttilde = "~"; }
print STDERR "CHECKPOINT: INTEMPLATE IS ".$parserState->{inTemplate}." SOD IS ".$parserState->{startOfDec}."\n" if ($localDebug || $sodDebug);
if ($parserState->{startOfDec} == 1) { # @@@ FIXME DAG. This should not set sodname, but otherwise, we're losing classes!!!
if (!$parserState->{inTemplate}) {
print STDERR "Setting sodname (maybe type) to \"$part\"\n" if ($sodDebug);
$parserState->{sodname} = $opttilde.$part;
if ($part =~ /\w/o) {
$parserState->{startOfDec}++;
}
} else {
print STDERR "Not adjusting startOfDec or sodname because in template.\n" if ($localDebug || $sodDebug);
}
} elsif ($parserState->{startOfDec} == 2) {
if ($part =~ /\w/o && !$parserState->{inTemplate}) {
$parserState->{preTemplateSymbol} = "";
}
if (!$parserState->{inTemplate}) {
if ($parserState->{inOperator} == 1) {
$parserState->{sodname} .= $part;
} else {
if (length($parserState->{sodname})) {
$parserState->{sodtype} .= " $parserState->{sodname}";
}
$parserState->{sodname} = $opttilde.$part;
}
print STDERR "sodname set to $part\n" if ($sodDebug);
} else {
print STDERR "Not adjusting startOfDec or sodname because in template.\n" if ($localDebug || $sodDebug);
}
} else {
$parserState->{startOfDec} = 0;
}
} elsif ($part eq "[") { # if ($part !~ /[;\[\]]/o)
$parserState->{inBrackets} += 1;
print STDERR "inBrackets -> $parserState->{inBrackets}\n" if ($sodDebug);
} elsif ($part eq "]") {
$parserState->{inBrackets} -= 1;
print STDERR "inBrackets -> $parserState->{inBrackets}\n" if ($sodDebug);
} # end if ($part !~ /[;\[\]]/o)
if (!($part eq $eoc)) {
print STDERR "SETTING LS ($part)\n" if ($parseDebug);
if ($parserState->{typestring} eq "") { $parserState->{typestring} = $part; }
if ($parserState->{lastsymbol} =~ /\,\s*$/o) {
$parserState->{lastsymbol} .= $part;
} elsif ($parserState->{inTypedef} && !(scalar(@braceStack)-$parserState->{initbsCount}) && $part =~ /,/) {
$parserState->{lastsymbol} .= $part;
} elsif ($part =~ /^\s*\;\s*$/o) {
$parserState->{lastsymbol} .= $part;
} elsif (length($part)) {
# warn("replacing lastsymbol with \"$part\"\n");
$parserState->{lastsymbol} = $part;
}
} # end if (!($part eq $eoc))
} # end if (length($part) && !($parserState->{inComment} || $parserState->{inInlineComment}))
}
} # end if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}))
} # end SWITCH default case
} # end SWITCH
if ($parserState->{seenBraces}) {
# print "SEENBRACES. TP: $treepart PT: $part\n";
if ($treepart) {
$parserState->{functionContents} .= $treepart;
} else {
$parserState->{functionContents} .= $part;
}
# print "SEENBRACES. FC: ".$parserState->{functionContents}."\n";
}
if ($part !~ /\\/o) {
if (!($parserState->{inMacro} || $parserState->{inMacroLine}) || $part !~ /\s/) {
$parserState->resetBackslash();
}
}
if (length($part)) { $lasttoken = $part; }
if (length($part) && $inRegexpTrailer) { --$inRegexpTrailer; }
if ($postPossNL) { --$postPossNL; }
if (($parserState->{simpleTypedef} == 1) && ($part ne $typedefname) &&
!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} ||
$inRegexp)) {
# print STDERR "NP: $parserState->{namePending} PTP: $parserState->{posstypesPending} PART: $part\n";
$parserState->{simpleTDcontents} .= $part;
}
my $ignoretoken = ignore($part, $ignoreref, $perheaderignoreref);
my $hide = ( $hideTokenAndMaybeContents ||
( $ignoretoken &&
!( $parserState->{inString} || $parserState->{inComment} ||
$parserState->{inInlineComment} || $parserState->{inChar}
)
)
);
print STDERR "TPONL: $treePopOnNewLine TPTWO: ".$parserState->{treePopTwo}."\n" if ($tsDebug);
print STDERR "TN: $treeNest TS: $treeSkip nTS: ".scalar(@treeStack)."\n" if ($tsDebug || $parserStateInsertDebug);
print STDERR "sethollow: $sethollow\n" if ($parserStateInsertDebug);
if (!$treeSkip) {
if (!$parserState->{seenBraces}) { # TREEDONE
if ($treeNest != 2) {
# If we really want to skip and nest, set treeNest to 2.
if (length($treepart)) {
if ((($parserState->{inComment} == 1) || ($parserState->{inInlineComment} == 1)) && $treepart !~ /[\r\n!]/) {
$treeCur->token($treeCur->token() . $treepart);
# print STDERR "SHORT\n";
} else {
$treeCur = $treeCur->addSibling($treepart, $hide);
}
$treepart = "";
} else {
if ((($parserState->{inComment} == 1) || ($parserState->{inInlineComment} == 1)) && $treepart !~ /[\r\n!]/) {
$treeCur->token($treeCur->token() . $part);
# print STDERR "SHORT\n";
} else {
$treeCur = $treeCur->addSibling($part, $hide);
}
}
bless($treeCur, "HeaderDoc::ParseTree");
}
# print STDERR "TC IS $treeCur\n";
# $treeCur = %{$treeCur};
if ($treeNest) {
if ($sethollow) {
print STDERR "WILL INSERT STATE $parserState (SETHOLLOW) at ".$treeCur->token()."\n" if ($parserStackDebug);
# $parserState->{hollow} = $treeCur;
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$sethollow = 0;
}
print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug);
push(@treeStack, $treeCur);
$treeCur = $treeCur->addChild("", 0);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
}
if ($parserState->{inComment} > 1) { $parserState->{inComment}--; }
if ($parserState->{inInlineComment} > 1) { $parserState->{inInlineComment}--; }
if (($parserState->{inComment} == 1) && $treepart eq "!") {
$parserState->{inComment} = 3;
}
if (($parserState->{inInlineComment} == 1) && $treepart eq "!") {
$parserState->{inInlineComment} = 3;
}
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [19]\n"; }
if (!$parserState->{freezereturn} && $parserState->{hollow}) {
# print STDERR "WARNING: RETURN TYPE CHANGE[A]".$parserState->{returntype}." CHANGED TO $declaration$curline.\n";
$parserState->{returntype} = "$declaration$curline";
} elsif (!$parserState->{freezereturn} && !$parserState->{hollow}) {
# print STDERR "WARNING: RETURN TYPE CHANGE[B]".$parserState->{returntype}." CHANGED TO $curline.\n";
$parserState->{returntype} = "$curline";
$declaration = "";
# } else {
# print STDERR "WARNING: LEAVING RETURN TYPE ALONE: ".$parserState->{returntype}." NOT CHANGED TO $curline.\n";
}
# From here down is... magic. This is where we figure out how
# to handle parsed parameters, K&R C types, and in general,
# determine whether we've received a complete declaration or not.
#
# About 90% of this is legacy code to handle proper spacing.
# Those bits got effectively replaced by the parseTree class.
# The only way you ever see this output is if you don't have
# any styles defined in your config file.
if (($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) ||
!$ignoretoken) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) &&
!$ppSkipOneToken) {
if ($parsedParamParse == 1) {
$parsedParam .= $part;
} elsif ($parsedParamParse == 2) {
$parsedParamParse = 1;
print STDERR "parsedParamParse -> 1\n" if ($parmDebug);
}
}
if ($ppSkipOneToken) {
$hollowskip = $ppSkipOneToken;
print STDERR "hollowskip -> $ppSkipOneToken (ppSkipOneToken)\n" if ($parserStateInsertDebug);
}
$ppSkipOneToken = 0;
print STDERR "MIDPOINT CL: $curline\nDEC:$declaration\nSCR: \"$scratch\"\n" if ($localDebug);
if (!$parserState->{seenBraces}) {
# Add to current line (but don't put inline function/macro
# declarations in.
if ($parserState->{inString}) {
$curstring .= $part;
} else {
if (length($curstring)) {
if (length($curline) + length($curstring) >
$HeaderDoc::maxDecLen) {
$scratch = nspaces($prespace);
# Was != /\n/ which is clearly
# wrong. Suspect the next line
# if we start losing leading spaces
# where we shouldn't (or don't where
# we should). Also was just /g.
if ($curline !~ /^\s*\n/so) { $curline =~ s/^\s*//sgo; }
# NEWLINE INSERT
print STDERR "CURLINE CLEAR [1]\n" if ($localDebug);
$declaration .= "$scratch$curline\n";
$curline = "";
$prespace += $prespaceadjust;
$prespaceadjust = 0;
$prespaceadjust -= 4;
$prespace += 4;
} else {
# no wrap, so maybe add a space.
if ($lastchar =~ /\=$/o) {
$curline .= " ";
}
}
$curline .= $curstring;
$curstring = "";
}
if ((length($curline) + length($part) > $HeaderDoc::maxDecLen)) {
$scratch = nspaces($prespace);
# Was != /\n/ which is clearly
# wrong. Suspect the next line
# if we start losing leading spaces
# where we shouldn't (or don't where
# we should). Also was /g instead of /sg.
if ($curline !~ /^\s*\n/so) { $curline =~ s/^\s*//sgo; }
# NEWLINE INSERT
$declaration .= "$scratch$curline\n";
print STDERR "CURLINE CLEAR [2]\n" if ($localDebug);
$curline = "";
$prespace += $prespaceadjust;
$prespaceadjust = 0;
$prespaceadjust -= 4;
$prespace += 4;
}
if (length($curline) || $part ne " ") {
# Add it to curline unless it's a space that
# has inadvertently been wrapped to the
# start of a line.
$curline .= $part;
}
}
if (peek(\@braceStack) ne "<") {
if ($part =~ /\n/o || ($part =~ /[\(;,]/o && $nextpart !~ /\n/o &&
!$parserState->{occmethod}) ||
($part =~ /[:;.]/o && $nextpart !~ /\n/o &&
$parserState->{occmethod})) {
if ($curline !~ /\n/o && !($parserState->{inMacro} || ($pascal && (scalar(@braceStack)-$parserState->{initbsCount})) || $parserState->{inInlineComment} || $parserState->{inComment} || $parserState->{inString})) {
# NEWLINE INSERT
$curline .= "\n";
}
# Add the current line to the declaration.
$scratch = nspaces($prespace);
if ($curline !~ /\n/o) { $curline =~ s/^\s*//go; }
if ($declaration !~ /\n\s*$/o) {
$scratch = " ";
if ($localDebug) {
my $zDec = $declaration;
$zDec = s/ /z/sg;
$zDec = s/\t/Z/sg;
print STDERR "ZEROSCRATCH\n";
print STDERR "zDec: \"$zDec\"\n";
}
}
$declaration .= "$scratch$curline";
print STDERR "CURLINE CLEAR [3]\n" if ($localDebug);
$curline = "";
# $curline = nspaces($prespace);
print STDERR "PS: $prespace -> " . $prespace + $prespaceadjust . "\n" if ($localDebug);
$prespace += $prespaceadjust;
$prespaceadjust = 0;
} elsif ($part =~ /[\(;,]/o && $nextpart !~ /\n/o &&
($parserState->{occmethod} == 1)) {
print STDERR "SPC\n" if ($localDebug);
$curline .= " "; $occspace = 1;
} else {
print STDERR "NOSPC: $part:$nextpart:$parserState->{occmethod}\n" if ($localDebug);
}
}
}
if ($parserState->{temponlyComments}) {
# print STDERR "GOT TOC: ".$parserState->{temponlyComments}."\n";
$parserState->{onlyComments} = $parserState->{temponlyComments};
$parserState->{temponlyComments} = undef;
}
print STDERR "CURLINE IS \"$curline\".\n" if ($localDebug);
my $bsCount = scalar(@braceStack);
print STDERR "ENDTEST: $bsCount \"$parserState->{lastsymbol}\"\n" if ($localDebug);
print STDERR "KRC: $parserState->{kr_c_function} SB: $parserState->{seenBraces}\n" if ($localDebug);
if (!($bsCount - $parserState->{initbsCount}) && $parserState->{lastsymbol} =~ /;\s*$/o) {
# print STDERR "DPA\n";
if ((!$parserState->{kr_c_function} || $parserState->{seenBraces}) && !$parserState->{inMacro}) {
# print STDERR "DPB\n";
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [3]\n" if ($localDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[SEMI-1]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} elsif ($parserState->{classtype} && length($parserState->{classtype})) {
warn "Couldn't insert info into parse tree[3class].\n" if ($localDebug);
} else {
warn "Couldn't insert info into parse tree[3].\n";
print STDERR "Printing tree.\n";
$parserState->print();
$treeTop->dbprint();
}
print STDERR "parserState: Created parser state[2].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "NEWRETURNTYPE: $parserState->{returntype}\n" if ($localDebug);
print STDERR "CURLINE CLEAR[PRS2]\n" if ($localDebug);
$curline = "";
}
}
} else {
print STDERR "bsCount: $bsCount - $parserState->{initbsCount}, ls: $parserState->{lastsymbol}\n" if ($localDebug);
pbs(@braceStack);
}
if (!($bsCount - $parserState->{initbsCount}) && $parserState->{seenBraces} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator}) &&
($nextpart ne ";")) {
# Function declarations end at the close curly brace.
# No ';' necessary (though we'll eat it if it's there.
if ($parserState->{treePopTwo}) {
# Fix nesting.
# print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n";
while ($parserState->{treePopTwo}--) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [13]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
$treeCur = $treeCur->addSibling(";", 0);
$parserState->{lastTreeNode} = $treeCur;
$parserState->{treePopTwo} = 0;
}
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [4]\n" if ($localDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[SEMI-2]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[4].\n";
}
print STDERR "parserState: Created parser state[3].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "CURLINE CLEAR[PRS3]\n" if ($localDebug);
$curline = "";
}
}
print STDERR "INMACRO: ".$parserState->{inMacro}."\n" if ($localDebug || $cppDebug || $cppDebug);
# $parserState->{lastsymbol} ne "\\"
print STDERR "IM: ".$parserState->{inMacro}." IQ: ".$parserState->isQuoted($lang, $sublang)."\n" if ($localDebug);
if (($parserState->{inMacro} == 3 && !$parserState->isQuoted($lang, $sublang)) || $parserState->{inMacro} == 4) {
print STDERR "CHECKPART AGAINST NEWLINE\n" if ($localDebug || $cppDebug);
if ($part =~ /[\n\r]/o && !$parserState->{inComment}) {
print STDERR "MLS: $parserState->{lastsymbol}\n" if ($macroDebug);
print STDERR "PARSER STACK CONTAINS ".scalar(@parserStack)." FRAMES\n" if ($cppDebug || $parserStackDebug);
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [5]\n" if ($localDebug || $liteDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
print STDERR "NOT setting continue to 0 for macro: parser stack nonempty\n" if ($liteDebug);
print STDERR "DONE WITH MACRO. HANDLING.\n" if ($localDebug || $parseDebug);
if ($parserState->{inMacro} == 3) {
if (!$HeaderDoc::skipNextPDefine) {
cpp_add($parserState->{hollow});
} else {
cpp_add($parserState->{hollow}, 1);
$HeaderDoc::skipNextPDefine = 0;
}
}
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[5].\n";
}
print STDERR "parserState: Created parser state[4].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "CURLINE CLEAR[PRS4]\n" if ($localDebug);
$curline = "";
}
}
} elsif ($parserState->{inMacro} == 2) {
my $linenum = $inputCounter + $fileoffset;
warn "$filename:$linenum: warning: Declaration starts with # but is not preprocessor macro\n";
warn "PART: $part\n";
} elsif ($parserState->{inMacro} == 3 && $parserState->isQuoted($lang, $sublang)) {
# $parserState->{lastsymbol} eq "\\"
print STDERR "TAIL BACKSLASH ($continue)\n" if ($localDebug || $macroDebug);
}
if ($parserState->{valuepending} == 2) {
# skip the "=" part;
$parserState->{value} .= $part;
} elsif ($parserState->{valuepending}) {
$parserState->{valuepending} = 2;
print STDERR "valuepending -> 2\n" if ($valueDebug);
}
} # end if "we're not ignoring this token"
print STDERR "OOGABOOGA\n" if ($parserStackDebug);
if ($pushParserStateAfterToken == 1) {
print STDERR "parserState pushed onto stack[token]\n" if ($parserStackDebug);
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterToken = 0;
$pushParserStateAtBrace = 0;
} elsif ($pushParserStateAfterWordToken == 1) {
if ($part =~ /\w/) {
print STDERR "parserState pushed onto stack[word]\n" if ($parserStackDebug);
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterWordToken = 0;
}
} elsif ($pushParserStateAfterWordToken) {
print STDERR "PPSAFTERWT CHANGED $pushParserStateAfterWordToken -> " if ($parserStackDebug);
$pushParserStateAfterWordToken--;
print STDERR "$pushParserStateAfterWordToken\n" if ($parserStackDebug);
} elsif ($pushParserStateAtBrace) {
print STDERR "PPSatBrace?\n" if ($parserStackDebug);
if (casecmp($part, $lbrace, $case_sensitive)) {
$parserState->{ISFORWARDDECLARATION} = 0;
print STDERR "parserState pushed onto stack[brace]\n" if ($parserStackDebug);
# if ($pushParserStateAtBrace == 2) {
# print STDERR "NOINSERT parserState: $parserState\n" if ($parserStackDebug);
# $parserState->{hollow} = undef;
# $parserState->{noInsert} = 1;
# }
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
} elsif ($pushParserStateAtBrace) {
if ($part =~ /\;/) {
# It's a class instance declaration. Whoops.
$pushParserStateAtBrace = 0;
$parserState->{inClass} = 0;
print STDERR "inClass -> 0 [10]\n" if ($classDebug);
}
# if ($part =~ /\S/) { $pushParserStateAtBrace = 0; }
}
if (!$parserState->{hollow}) {
my $tok = $part; # $treeCur->token();
print STDERR "parserState: NOT HOLLOW [1]\n" if ($parserStackDebug);
print STDERR "IS: $parserState->{inString}\nICom: $parserState->{inComment}\nISLC: $parserState->{inInlineComment}\nIChar: $parserState->{inChar}\nSkipToken: $parserState->{skiptoken}\nHollowSkip: $hollowskip\n" if ($parserStackDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
print STDERR "parserState: NOT STRING/CHAR/COMMENT\n" if ($parserStackDebug);
if ($tok =~ /\S/) {
print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug);
print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug);
if (!casecmp($tok, $rbrace, $case_sensitive) && $part !~ /\)/) {
# $parserState->{hollow} = $treeCur;
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$HeaderDoc::curParserState = $parserState;
print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-1) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug);
}
}
}
$hollowskip = 0;
print STDERR "hollowskip -> 0 (NOTHOLLOW - 1)\n" if ($parserStateInsertDebug);
$parserState->{skiptoken} = 0;
}
} else {
if (!$parserState->{hollow}) {
my $tok = $part; # $treeCur->token();
print STDERR "parserState: NOT HOLLOW [2]\n" if ($parserStackDebug);
print STDERR "IS: $parserState->{inString}\nICom: $parserState->{inComment}\nISLC: $parserState->{inInlineComment}\nIChar: $parserState->{inChar}\nSkipToken: $parserState->{skiptoken}\nHollowSkip: $hollowskip\n" if ($parserStackDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
print STDERR "parserState: NOT STRING/CHAR/COMMENT\n" if ($parserStackDebug);
if ($tok =~ /\S/) {
print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug);
print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug);
if (!casecmp($tok, $rbrace, $case_sensitive) && $part !~ /\)/) {
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$HeaderDoc::curParserState = $parserState;
print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-2) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug);
}
}
}
$hollowskip = 0;
print STDERR "hollowskip -> 0 (NOTHOLLOW - 2)\n" if ($parserStateInsertDebug);
$parserState->{skiptoken} = 0;
}
}
if ($part =~ /\w+/) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
if ($parserState->{occparmlabelfound} == -2) {
if (!($parserState->{initbsCount} - scalar(@braceStack) )) { # Skip types
$parserState->{occparmlabelfound} = 0; # Next token is the label for the next parameter.
if ($HeaderDoc::useParmNameForUnlabeledParms) {
$parserState->{occmethodname} .= "$part:";
} else {
$parserState->{occmethodname} .= ":";
}
if ($occMethodNameDebug) {
print STDERR "OCC parameter name substituted; OCC method name now ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\", part was \"".$part."\").\n";
}
}
} else {
if (!($parserState->{initbsCount} - scalar(@braceStack) )) { # Skip types
$parserState->{occparmlabelfound}++;
if ($occMethodNameDebug && ($parserState->{occparmlabelfound} > 0)) {
print STDERR "OCC possible label: \"$part\".\n";
}
}
}
}
}
if (length($part) && $part =~ /\S/o) { $lastnspart = $part; }
if ($parserState->{seenTilde} && length($part) && $part !~ /\s/o) { $parserState->{seenTilde}--; }
$part = $nextpart;
} # end foreach (parts of the current line)
} # end while (continue && ...)
print STDERR "RETURNING DECLARATION\n" if ($localDebug);
# Format and insert curline into the declaration. This handles the
# trailing line. (Deprecated.)
if ($curline !~ /\n/) { $curline =~ s/^\s*//go; }
if ($curline =~ /\S/o) {
$scratch = nspaces($prespace);
$declaration .= "$scratch$curline\n";
}
print STDERR "($parserState->{typestring}, $parserState->{basetype})\n" if ($localDebug || $listDebug);
print STDERR "LS: $parserState->{lastsymbol}\n" if ($localDebug);
$parserState->{lastTreeNode} = $treeCur;
$parserState->{inputCounter} = $inputCounter;
print STDERR "PARSERSTATE: $parserState\n" if ($localDebug);
if ($parserState->{inMacro} == 3) {
if (!$HeaderDoc::skipNextPDefine) {
cpp_add($treeTop);
} else {
cpp_add($treeTop, 1);
$HeaderDoc::skipNextPDefine = 0;
}
}
print STDERR "LEFTBPMAIN\n" if ($localDebug || $hangDebug);
if ($argparse && $apwarn) {
print STDERR "end argparse\n";
}
# Return the top parser context even if we got interrupted.
my $tempParserState = pop(@parserStack);
while ($tempParserState) {
$parserState = $tempParserState;
$tempParserState = pop(@parserStack);
}
$HeaderDoc::module = $parserState->{MODULE};
if ($localDebug || $apDebug || $liteDebug || $parseDebug) {
print STDERR "LEAVING BLOCKPARSE\n";
}
if (0) {
print STDERR "Returning the following parse tree:\n";
$treeTop->dbprint();
print STDERR "End of parse tree.\n";
}
# print "FC: ".$parserState->{functionContents}."\n";
return blockParseReturnState($parserState, $treeTop, $argparse, $declaration, $inPrivateParamTypes, $publicDeclaration, $lastACS, $retDebug, $fileoffset, 0, $definename, $inputCounter);
}
$parserState->{functionReturnsCallback} => 0
$parserState->{hollow} => HeaderDoc::ParseTree=HASH(OBJID)
$parserState->{inBrackets} => 0
$parserState->{inChar} =>
$parserState->{inClass} => 0
$parserState->{inComment} => 0
$parserState->{inInlineComment} => 0
$parserState->{inMacro} => 0
$parserState->{inMacroLine} => 0
$parserState->{inOperator} => 0
$parserState->{inPrivateParamTypes} => 0
$parserState->{inString} => 0
$parserState->{inTemplate} => 0
$parserState->{initbsCount} => 0
$parserState->{inputCounter} => 3647
$parserState->{kr_c_function} => 0
$parserState->{kr_c_name} =>
$parserState->{lang} => perl
$parserState->{lastTreeNode} => HeaderDoc::ParseTree=HASH(OBJID)
$parserState->{lastsymbol} =>
$parserState->{macroNoTrunc} => 1
$parserState->{name} => blockParse
$parserState->{namePending} => 0
$parserState->{noInsert} => 0
$parserState->{occmethod} => 0
$parserState->{occmethodname} =>
$parserState->{occparmlabelfound} => 2
$parserState->{onlyComments} => 0
$parserState->{parsedParamAtBrace} => ARRAY(OBJID)
$parserState->{parsedParamList} => ARRAY(OBJID)
$parserState->{parsedParamParse} => 0
$parserState->{parsedParamStateAtBrace} => ARRAY(OBJID)
$parserState->{posstypes} =>
$parserState->{posstypesPending} => 0
$parserState->{pplStack} => ARRAY(OBJID)
$parserState->{preEqualsSymbol} =>
$parserState->{preTemplateSymbol} =>
$parserState->{prekeywordsodname} =>
$parserState->{prekeywordsodtype} =>
$parserState->{returntype} => sub blockParse
$parserState->{seenBraces} => 1
$parserState->{seenMacroPart} => 0
$parserState->{seenTilde} => 0
$parserState->{simpleTDcontents} =>
$parserState->{simpleTypedef} => 0
$parserState->{sodclass} => function
$parserState->{sodname} => blockParse
$parserState->{sodtype} =>
$parserState->{stackFrozen} => 1
$parserState->{startOfDec} => 0
$parserState->{sublang} => perl
$parserState->{temponlyComments} => 0
$parserState->{typestring} => function
$parserState->{value} =>
$parserState->{valuepending} => 0
-=: BLOCKPARSE RETURN VALUES :=-
newcount: 3647
typelist: function
namelist: blockParse
posstypes: function method
value:
returntype:
pridec:
simpleTDcontents:
bpavail:
blockOffset: 0
conformsToList:
functionContents: {
my $filename = shift;
my $fileoffset = shift;
my $inputLinesRef = shift;
my $inputCounter = shift;
my $argparse = shift;
my $ignoreref = shift;
my $perheaderignoreref = shift;
my $perheaderignorefuncmacrosref = shift;
my $keywordhashref = shift;
my $case_sensitive = shift;
my $apwarn = 0;
if ($argparse && $apwarn) {
print STDERR "argparse\n";
}
# Initialize stuff
my @inputLines = @{$inputLinesRef};
my $declaration = "";
my $publicDeclaration = "";
# $HeaderDoc::fileDebug = 1;
# Debugging switches
my $retDebug = 0;
my $localDebug = 0 || $HeaderDoc::fileDebug;
my $operatorDebug = 0;
my $listDebug = 0;
my $parseDebug = 0 || $HeaderDoc::fileDebug;
my $sodDebug = 0 || $HeaderDoc::fileDebug;
my $valueDebug = 0;
my $parmDebug = 0;
my $cbnDebug = 0;
my $macroDebug = 0;
my $apDebug = 0;
my $tsDebug = 0;
my $treeDebug = 0;
my $ilcDebug = 0;
my $regexpDebug = 0;
my $parserStackDebug = 0 || $HeaderDoc::fileDebug;
my $hangDebug = 0;
my $offsetDebug = 0;
my $classDebug = 0; # prints changes to inClass, etc.
my $gccAttributeDebug = 0; # also for availability macro argument handling.
my $occMethodNameDebug = 0;
my $moduleDebug = 0; # prints changes to INMODULE
my $liteDebug = 0 || $HeaderDoc::fileDebug; # Just prints the tokens.
my $parserStateInsertDebug = 0;
$cppDebug = $cppDebugDefault || $HeaderDoc::fileDebug;
# State variables (part 1 of 3)
# my $typestring = "";
my $continue = 1; # set low when we're done.
my $parsedParamParse = 0; # set high when current token is part of param.
# my @parsedParamList = (); # currently active parsed parameter list.
# my @pplStack = (); # stack of parsed parameter lists. Used to handle
# fields and parameters in nested callbacks/structs.
# my @freezeStack = (); # copy of pplStack when frozen.
# my $frozensodname = "";
# my $stackFrozen = 0; # set to prevent fake parsed params with inline funcs
my $lang = $HeaderDoc::lang;
my $perl_or_shell = 0;
my $sublang = $HeaderDoc::sublang;
my $callback_typedef_and_name_on_one_line = 1; # deprecated
# my $returntype = "";
# my $freezereturn = 0; # set to prevent fake return types with inline funcs
my $treeNest = 0; # 1: nest future content under this node.
# 2: used if you want to nest, but have already
# inserted the contents of the node.
my $sethollow = 0;
my $setNoInsert = 0;
my $treepart = ""; # There are some cases where you want to drop a token
# for formatting, but keep it in the parse tree.
# In that case, treepart contains the original token,
# while part generally contains a space.
# my $availability = ""; # holds availability string if we find an av macro.
# my $seenTilde = 0; # set to 1 for C++ destructor.
if ($argparse && $tsDebug) { $tsDebug = 0; }
# Configure the parse tree output.
my $treeTop = HeaderDoc::ParseTree->new(); # top of parse tree.
my $treeCur = $treeTop; # current position in parse tree
my $treeSkip = 0; # set to 1 if "part" should be dropped in tree.
# my $treePopTwo = 0; # set to 1 for tokens that nest, but have no
# explicit ending token ([+-:]).
my $treePopOnNewLine = 0; # set to 1 for single-line comments, macros.
my @treeStack = (); # stack of parse trees. Used for popping
# our way up the tree to simplify tree structure.
# Leak a node here so that every real node has a parent.
$treeCur = $treeCur->addChild("");
$treeTop = $treeCur;
my $lastACS = "";
# The argparse switch is a trigger....
if ($argparse && $apDebug) {
$localDebug = 1;
$retDebug = 1;
$listDebug = 1;
$parseDebug = 1;
$sodDebug = 1;
$valueDebug = 1;
$parmDebug = 1;
$cbnDebug = 1;
$macroDebug = 1;
# $apDebug = 1;
$tsDebug = 1;
$treeDebug = 1;
$ilcDebug = 1;
$regexpDebug = 1;
}
my $spaceDebug = 0;
if ($localDebug || $apDebug || $liteDebug || $parseDebug) {
print STDERR "ENTERED BLOCKPARSE\n";
}
my $disable_cpp = 0;
if ($argparse && ($localDebug || $apDebug || $liteDebug)) {
print STDERR "ARGPARSE MODE!\n";
print STDERR "IPC: $inputCounter\nNLINES: ".$#inputLines."\n";
cluck("Call backtrace\n");
}
print STDERR "INBP\n" if ($localDebug);
if ($argparse) {
# Avoid double-processing macro inclusions.
$disable_cpp = 1;
}
if ($lang ne "C" || $sublang eq "PHP") { # || $sublang eq "IDL")
$disable_cpp = 1;
}
print STDERR "INITIAL LANG: $lang INITIAL SUBLANG: $sublang\n" if ($localDebug);
# warn("in BlockParse\n");
# State variables (part 2 of 3)
my $parserState = HeaderDoc::ParserState->new();
# $parserState->{hollow} = $treeTop;
setHollowWithLineNumbers(\$parserState, $treeTop, $fileoffset, $inputCounter);
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = 0; # included for consistency....
my @parserStack = ();
# print STDERR "TEST: ";
# if (defined($parserState->{parsedParamList})) {
# print STDERR "defined\n"
# } else { print STDERR "undefined.\n"; }
# print STDERR "\n";
# my $inComment = 0;
# my $inInlineComment = 0;
# my $inString = 0;
# my $inChar = 0;
# my $inTemplate = 0;
my @braceStack = ();
# my $inOperator = 0;
my $inPrivateParamTypes = 0; # after a colon in a C++ function declaration.
# my $onlyComments = 1; # set to 0 to avoid switching to macro parse.
# mode after we have seen a code token.
# my $inMacro = 0;
# my $inMacroLine = 0; # for handling macros in middle of data types.
# my $seenMacroPart = 0; # used to control dropping of macro body.
# my $macroNoTrunc = 1; # used to avoid truncating body of macros
# that don't begin with parenthesis or brace.
# my $inBrackets = 0; # square brackets ([]).
my $inPType = 0; # in pascal types.
my $inRegexp = 0; # in perl regexp.
my $regexpNoInterpolate = 0; # Don't interpolate (e.g. tr)
my $inRegexpTrailer = 0; # in the cruft at the end of a regexp.
my $hollowskip = 0;
my $ppSkipOneToken = 0; # Comments are always dropped from parsed
# parameter lists. However, inComment goes
# to 0 on the end-of-comment character.
# This prevents the end-of-comment character
# itself from being added....
my $regexppattern = ""; # optional characters at start of regexp
my $singleregexppattern = ""; # members of regexppattern that take only
# one argument instead of two.
my $regexpcharpattern = ""; # legal chars to start a regexp.
my @regexpStack = (); # stack of RE tokens (since some can nest).
# Get the parse tokens from Utilities.pm.
my ($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
$soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
$enumname,
$typedefname, $varname, $constname, $structisbrace, $macronameref,
$classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
$requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
my $macrore_pound = macroRegexpFromList($macronameref, 1);
my $macrore_nopound = macroRegexpFromList($macronameref, 2);
# print STDERR "LANG: $lang SUBLANG: $sublang";
print STDERR "MACRORE_POUND: \"$macrore_pound\"\n" if ($localDebug || $parseDebug);
print STDERR "MACRORE_NOPOUND: \"$macrore_nopound\"\n" if ($localDebug || $parseDebug);
# print STDERR "INITIAL PROPNAME $propname\n";
if ($parseDebug) {
print STDERR "SOT: $sotemplate EOF: $eotemplate OP: $operator SOC: $soc EOC: $eoc ILC: $ilc ILC_B: $ilc_b\n";
print STDERR "SOFUNC: $sofunction SOPROC: $soprocedure SOPREPROC: $sopreproc LBRACE: $lbrace RBRACE: $rbrace\n";
print STDERR "UNION: $unionname STRUCT: $structname TYPEDEF: $typedefname VAR: $varname CONST: $constname\n";
print STDERR "STRUCTISBRACE: $structisbrace MACRONAMEREF: $macronameref CLASSRE: $classregexp\n";
print STDERR "CLASSBRACERE: $classbraceregexp CLASSCLOSEBRACERE: $classclosebraceregexp ACCESSRE: $accessregexp\n";
print STDERR "MODULERE: $moduleregexp\n";
}
# Set up regexp patterns for perl, variable for perl or shell.
if ($lang eq "perl" || $lang eq "shell") {
$perl_or_shell = 1;
if ($lang eq "perl") {
$regexpcharpattern = '\\{|\\#\\(|\\/|\\\'|\\"|\\<|\\[|\\`';
# } vi bug workaround for previous line
$regexppattern = "qq|qr|qx|qw|q|m|s|tr|y";
$singleregexppattern = "qq|qr|qx|qw|q|m";
}
}
my $pascal = 0;
if ($lang eq "pascal") { $pascal = 1; }
# State variables (part 3 of 3)
# my $lastsymbol = ""; # Name of the last token, wiped by braces,
# parens, etc. This is not what you are
# looking for. It is used mostly for
# handling names of typedefs.
# my $name = ""; # Name of a basic data type.
# my $callbackNamePending = 0; # 1 if callback name could be here. This is
# only used for typedef'ed callbacks. All
# other callbacks get handled by the parameter
# parsing code. (If we get a second set of
# parsed parameters for a function, the first
# one becomes the callback name.)
# my $callbackName = ""; # Name of this callback.
# my $callbackIsTypedef = 0; # 1 if the callback is wrapped in a typedef---
# sets priority order of type matching (up
# one level in headerdoc2HTML.pl).
# my $namePending = 0; # 1 if name of func/variable is coming up.
# my $basetype = ""; # The main name for this data type.
# my $posstypes = ""; # List of type names for this data type.
# my $posstypesPending = 1; # If this token could be one of the
# type names of a typedef/struct/union/*
# declaration, this should be 1.
# my $sodtype = ""; # 'start of declaration' type.
# my $sodname = ""; # 'start of declaration' name.
# my $sodclass = ""; # 'start of declaration' "class". These
# bits allow us keep track of functions and
# callbacks, mostly, but not the name of a
# callback.
# my $simpleTypedef = 0; # High if it's a typedef w/o braces.
# my $simpleTDcontents = ""; # Guts of a one-line typedef. Don't ask.
# my $seenBraces = 0; # Goes high after initial brace for inline
# functions and macros -only-. We
# essentially stop parsing at this point.
# my $kr_c_function = 0; # Goes high if we see a K&R C declaration.
# my $kr_c_name = ""; # The name of a K&R function (which would
# otherwise get lost).
my $lastchar = ""; # Ends with the last token, but may be longer.
my $lastnspart = ""; # The last non-whitespace token.
my $lasttoken = ""; # The last token seen (though [\n\r] may be
# replaced by a space in some cases.
# my $startOfDec = 1; # Are we at the start of a declaration?
my $prespace = 0; # Used for indentation (deprecated).
my $prespaceadjust = 0; # Indentation is now handled by the parse
# tree (colorizer) code.
my $scratch = ""; # Scratch space.
my $curline = ""; # The current line. This is pushed onto
# the declaration at a newline and when we
# enter/leave certain constructs. This is
# deprecated in favor of the parse tree.
my $curstring = ""; # The string we're currently processing.
my $continuation = 0; # An obscure spacing workaround. Deprecated.
my $forcenobreak = 0; # An obscure spacing workaround. Deprecated.
# my $occmethod = 0; # 1 if we're in an ObjC method.
my $occspace = 0; # An obscure spacing workaround. Deprecated.
# my $occmethodname = ""; # The name of an objective C method (which
# gets augmented to be this:that:theother).
# my $preTemplateSymbol = ""; # The last symbol prior to the start of a
# C++ template. Used to determine whether
# the type returned should be a function or
# a function template.
# my $preEqualsSymbol = ""; # Used to get the name of a variable that
# is followed by an equals sign.
# my $valuepending = 0; # True if a value is pending, used to
# return the right value.
# my $value = ""; # The current value.
my $parsedParam = ""; # The current parameter being parsed.
my $postPossNL = 0; # Used to force certain newlines to be added
# to the parse tree (to end macros, etc.)
# my $categoryClass = "";
# my $classtype = "";
# my $inClass = 0;
my $pushParserStateAfterToken = 0;
my $pushParserStateAfterWordToken = 0;
my $pushParserStateAtBrace = 0;
my $occPushParserStateOnWordTokenAfterNext = 0;
$HeaderDoc::hidetokens = 0;
# Loop unti the end of file or until we've found a declaration,
# processing one line at a time.
my $nlines = $#inputLines;
my $incrementoffsetatnewline = 0;
print "INCOMING INPUTCOUNTER: $inputCounter\n" if ($HeaderDoc::inputCounterDebug);
while ($continue && ($inputCounter <= $nlines)) {
$HeaderDoc::CurLine = $inputCounter + $fileoffset;
my $line = $inputLines[$inputCounter++];
print STDERR "GOT LINE: $line\n" if (($localDebug && $apDebug) || $HeaderDoc::inputCounterDebug);
print STDERR "INCREMENTED INPUTCOUNTER [1]\n" if ($HeaderDoc::inputCounterDebug);
my @parts = ();
# $line =~ s/^\s*//go; # Don't strip leading spaces, please.
$line =~ s/\s*$//go;
# $scratch = nspaces($prespace);
# $line = "$scratch$line\n";
# $curline .= $scratch;
$line .= "\n";
if ($lang eq "C" && $sublang eq "IDL") {
if ($line =~ /cpp_quote\s*\(\s*\"(.*)\"\s*\)\s*$/) {
print "CHANGED LINE FROM \"$line\" to \"$1\"\n" if ($localDebug || $liteDebug);
$line = $1."\n";
}
}
print STDERR "LINE[$inputCounter] : $line\n" if ($offsetDebug);
# The tokenizer
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\^|\W)/, $line);
}
# See note about similar block below. This block is for fixing the
# "missing newline" problem, which otherwise would cause line numbers
# to sometimes be wrong.
push(@parts, "BOGUSBOGUSBOGUSBOGUSBOGUS");
my $xpart = "";
foreach my $nextxpart (@parts) {
if (!length($nextxpart)) { next; }
if (!length($xpart)) { $xpart = $nextxpart; next; }
if ($xpart eq "\n" && $nextxpart ne "BOGUSBOGUSBOGUSBOGUSBOGUS") {
print STDERR "FOUND EXTRA NEWLINE\n" if ($offsetDebug);
# $fileoffset++;
$incrementoffsetatnewline++;
}
$xpart = $nextxpart;
}
pop(@parts);
$parserState->{inInlineComment} = 0;
print STDERR "inInlineComment -> 0\n" if ($ilcDebug);
# warn("line $inputCounter\n");
if ($localDebug || $cppDebug || $spaceDebug) {foreach my $partlist (@parts) {print STDERR "PARTLIST: \"$partlist\"\n"; }}
# We have to do the C preprocessing work up front because token substitution
# must occur prior to actual parsing in order to do any good. This block does
# the work.
my $cpp_in_argparse = 0;
if (!$disable_cpp && (1 || $HeaderDoc::enable_cpp)) {
my $newrawline = "";
my $incppargs = 0;
my $cppstring = "";
my $cppname = "";
my $lastcpppart = "";
my @cppargs = ();
my $inChar = 0; my $inString = 0; my $inComment = $parserState->{inComment}; my $inSLC = $parserState->{inInlineComment};
my $inParen = 0;
my $inMacro = $parserState->{inMacro};
my $inCPPSpecial = $parserState->{inMacro} || $parserState->{inMacroLine};
my $inMacroTail = 0;
if ($parserState->{sodname} && ($parserState->{sodname} ne "")) {
$inMacroTail = 1;
}
print STDERR "INMACROTAIL: $inMacroTail\n" if ($cppDebug);
my @cpptrees;
my $cpptreecur = HeaderDoc::ParseTree->new();
my $cpptreetop = $cpptreecur;
# print STDERR "CHECK LINE $line\n";
if ($line =~ /^\s*#include (.*)$/) {
my $rest = $1;
$rest =~ s/^\s*//s;
$rest =~ s/\s*$//s;
if ($rest !~ s/^\<(.*)\>$/$1/s) {
$rest =~ s/^\"(.*)\"$/$1/s;
}
my $filename = basename($rest);
if ($HeaderDoc::HeaderFileCPPHashHash{$filename}) {
my $includehash = HeaderDoc::IncludeHash->new();
$includehash->{FILENAME} = $filename;
$includehash->{LINENUM} = $inputCounter + $fileoffset;
$includehash->{HASHREF} = $HeaderDoc::HeaderFileCPPHashHash{$filename};
push(@HeaderDoc::cppHashList, $includehash);
# print STDERR "PUSH HASH\n";
push(@HeaderDoc::cppArgHashList, $HeaderDoc::HeaderFileCPPArgHashHash{$filename});
}
} elsif ($line =~ /^\s*$definename\s+/) {
# print STDERR "inMacro -> 1\n";
# print STDERR "inMacro -> 1\n" if ($macroDebug || $cppDebug);
# This is a throwaway line.
$inMacro = 1;
}
if ($macrore_pound ne "" && $line =~ /^\s*\#\s*$macrore_pound\s+/) {
print STDERR "CPPSPECIAL -> 1\n" if ($macroDebug || $cppDebug);
$inCPPSpecial = 1;
}
my $cppleaddebug = 0;
do {
my $pos = 0;
my $dropargs = 0;
while ($pos < scalar(@parts)) {
my $part = $parts[$pos];
my $noCPPThisToken = 0;
if (length($part)) {
if (!$inChar && !$inString && !$inComment && !$inSLC) {
if ($parserState->{NEXTTOKENNOCPP} == 1) {
# We're in an "if" block.
if ($part eq "defined") {
$parserState->{NEXTTOKENNOCPP} = 3;
}
} elsif ($parserState->{NEXTTOKENNOCPP} == 2) {
# We're in an "ifdef"/"ifndef" block, so first word token
# ends this mode completely.
if ($part !~ /(\s|\()/) {
$parserState->{NEXTTOKENNOCPP} = 0;
$noCPPThisToken = 1;
}
} elsif ($parserState->{NEXTTOKENNOCPP} == 3) {
# We're in an "if" block, so first word token
# drops us back to default "if" block state.
if ($part !~ /(\s|\()/) {
$parserState->{NEXTTOKENNOCPP} = 1;
$noCPPThisToken = 1;
}
}
if ($inCPPSpecial && $part =~ /(ifdef|ifndef)/) {
$parserState->{NEXTTOKENNOCPP} = 2;
} elsif ($inCPPSpecial && $part =~ /if/) {
$parserState->{NEXTTOKENNOCPP} = 1;
}
}
print STDERR "TOKEN: $part NEXTTOKENNOCPP: ".$parserState->{NEXTTOKENNOCPP}." INMACRO: $inMacro INCPPSPECIAL: $inCPPSpecial\n" if ($cppleaddebug || $macroDebug || $cppDebug);
print STDERR "CPPLEADPART: $part\n"if ($cppleaddebug);
if (!$inString && !$inChar) {
if ($inComment && $part eq $eoc) {
print STDERR "EOC\n"if ($cppleaddebug);
$inComment = 0;
} elsif ($inSLC && $part =~ /[\r\n]/) {
# Handle newline in single-line comments.
print STDERR "EOSLC\n"if ($cppleaddebug);
$inSLC = 0;
} elsif (!$inSLC && $part eq $soc) {
print STDERR "SOC\n"if ($cppleaddebug);
$inComment = 1;
} elsif (!$inComment && ($part eq $ilc || $part eq $ilc_b)) {
print STDERR "INSLC\n"if ($cppleaddebug);
$inSLC = 1;
}
}
my $skip = 0;
if (!$incppargs) {
my $newpart = $part;
my $hasargs = 0;
if (!$inComment && !$inSLC && !$noCPPThisToken) {
($newpart, $hasargs) = cpp_preprocess($part, $HeaderDoc::CurLine);
# Don't drop tokens in macros.
if ($hasargs == 2 && $inMacro) {
$newpart = $part;
$hasargs = 0;
}
# Don't change the macro name. (If a
# macro gets redefined, ignore it.)
if ($inMacro && !$inMacroTail) {
$newpart = $part;
$hasargs = 0;
}
}
if ($hasargs) {
$incppargs = 1;
$cppname = $part;
if ($hasargs == 2) {
$dropargs = 1;
print STDERR "Dropping arguments for ignored macro \"$part\"\n" if ($cppDebug);
}
} else {
my $newpartnl = $newpart;
my $newpartnlcount = ($newpartnl =~ tr/\n//);
my $partnl = $part;
my $partnlcount = ($partnl =~ tr/\n//);
my $nlchange = ($newpartnlcount - $partnlcount);
print STDERR "NLCHANGE: $nlchange (FILEOFFSET = $fileoffset)\n" if ($offsetDebug);
$fileoffset -= $nlchange;
if ($inMacro) {
if ($newpart ne $part) {
print STDERR "CHANGING NEWPART FROM \"$newpart\" TO " if ($cppDebug);
$newpart =~ s/^\s*/ /s;
$newpart =~ s/\s*$//s;
$newpart =~ s/(.)\n/$1 \\\n/sg;
$newpart =~ s/\\$/ /s;
print STDERR "$newpart\n" if ($cppDebug);
}
}
$newrawline .= $newpart;
}
} elsif ($incppargs == 1) {
if ($part eq "(") {
# Don't do anything until leading parenthesis.
$incppargs = 3;
$inParen++;
}
} elsif ($incppargs == 3) {
if ($part eq '\\') {
if (!$inMacro && ($lastcpppart eq '\\')) { $lastcpppart = ""; } # @@@ CHECKME. inMacro test may not be needed.
# else {
# $lastcpppart = $part;
# if ($inMacro) {
# print STDERR "IMTEST\n" if ($cppDebug > 1);
# my $npos = $pos + 1;
# while ($npos < scalar(@parts)) {
# my $npart = $parts[$npos];
# if (length($npart)) {
# print STDERR "NEXTPART: \"".$parts[$npos]."\"\n" if ($cppDebug > 1);
# if ($npart =~ /\s/) {
# if ($npart =~ /[\n\r]/) {
# print STDERR "SKIP1\n" if ($cppDebug > 1);
# $skip = 1; last;
# } else {
# print STDERR "SPC\n" if ($cppDebug > 1);
# }
# } else {
# print STDERR "LAST\n" if ($cppDebug > 1);
# last;
# }
# }
# $npos++;
# }
# }
# }
} elsif ($part eq '"') {
if ($lastcpppart ne '\\') {
if (!$inChar && !$inComment && !$inSLC) {
$inString = !$inString;
}
}
$lastcpppart = $part;
} elsif ($part eq "'") {
if ($lastcpppart ne '\\') {
if (!$inString && !$inComment && !$inSLC) {
$inChar = !$inChar;
}
}
$lastcpppart = $part;
} elsif (!$inChar && !$inString && !$inComment && !$inSLC) {
if ($part eq "(") {
# Put in the token first, then nest.
$cpptreecur = $cpptreecur->next(HeaderDoc::ParseTree->new());
$cpptreecur->token($part);
$skip = 1;
$inParen++;
push(@cpptrees, $cpptreecur);
$cpptreecur = $cpptreecur->firstchild(HeaderDoc::ParseTree->new());
} elsif ($part eq ")") {
$inParen--;
# Go out one nesting level, then
# insert the token.
if (scalar(@cpptrees)) {
$cpptreecur = pop(@cpptrees);
while ($cpptreecur && $cpptreecur->next()) {
$cpptreecur = $cpptreecur->next();
}
}
if (!$inParen) {
push(@cppargs, $cpptreetop);
$cppstring = "";
$cpptreetop = HeaderDoc::ParseTree->new();
$cpptreecur = $cpptreetop;
$skip = 1;
$incppargs = 0;
if (!$dropargs) {
print STDERR "CALLING ARGPARSE FROM blockParse() [1].\n" if ($cppDebug);
my $addon = cpp_argparse($cppname, $HeaderDoc::CurLine, \@cppargs);
if ($inMacro) {
print STDERR "CHANGING ADDON FROM \"$addon\" TO " if ($cppDebug);
$addon =~ s/^\s*/ /s;
$addon =~ s/\s*$//s;
$addon =~ s/(.)\n/$1 \\\n/sg;
$addon =~ s/\\$/ /s;
print STDERR "$addon\n" if ($cppDebug);
}
$newrawline .= $addon;
}
$dropargs = 0;
}
} elsif (($inParen == 1) && (!$inChar && !$inString && !$inComment && !$inSLC) && ($part eq ",")) {
push(@cppargs, $cpptreetop);
$cpptreetop = HeaderDoc::ParseTree->new();
$cpptreecur = $cpptreetop;
$cppstring = "";
$skip = 1;
} elsif (($part =~ /\s/) && (!$inParen)) {
$incppargs = 0;
if (!$dropargs) {
print STDERR "CALLING ARGPARSE FROM blockParse() [2].\n" if ($cppDebug);
my $addon = cpp_argparse($cppname, $HeaderDoc::CurLine, \@cppargs);
if ($inMacro) {
print STDERR "CHANGING ADDON FROM \"$addon\" TO " if ($cppDebug);
$addon =~ s/^\s*/ /s;
$addon =~ s/\s*$//s;
$addon =~ s/(.)\n/$1 \\\n/sg;
$addon =~ s/\\$/ /s;
print STDERR "$addon\n" if ($cppDebug);
}
$newrawline .= $addon;
}
$dropargs = 0;
}
$lastcpppart = $part;
}
if ($skip) { $skip = 0; }
else {
my $xpart = $part;
# Strip newline in CPP argument list.
if ($part =~ /[\r\n]/) { $xpart = " "; }
$cpptreecur = $cpptreecur->next(HeaderDoc::ParseTree->new());
$cpptreecur->token($xpart);
}
$cppstring .= $part;
}
if ($inMacro && $part ne "define" &&
$part =~ /\w/ && !$inParen) {
$inMacroTail = 1;
}
}
$pos++;
}
if ($incppargs) {
# print STDERR "YO\n";
if ($parserState->{inMacro} || $inMacro) {
# print STDERR "YOYO\n";
if ($cppstring !~ s/\\\s*$//s) {
print STDERR "CPPS: \"$cppstring\"\n";
warn "Non-terminated macro.\n";
$incppargs = 0;
}
}
}
if ($incppargs || $inComment) {
print STDERR "Fetching new line ($incppargs, $inComment)\n" if ($cppleaddebug);
$HeaderDoc::CurLine = $inputCounter + $fileoffset;
$line = $inputLines[$inputCounter++];
if ($lang eq "C" && $sublang eq "IDL") {
if ($line =~ /cpp_quote\s*\(\s*\"(.*)\"\s*\)\s*$/) {
print "CHANGED LINE FROM \"$line\" to \"$1\"\n" if ($localDebug || $liteDebug);
$line = $1."\n";
}
}
print STDERR "INCREMENTED INPUTCOUNTER [2]\n" if ($HeaderDoc::inputCounterDebug);
# @parts = split(/(\W)/, $line);
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
}
}
} until (!$incppargs && !$inComment);
# The tokenizer
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $newrawline);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\W)/, $newrawline);
}
while (scalar(@cpptrees)) {
my $temptree = pop(@cpptrees);
if ($temptree != $cpptreetop) {
$temptree->dispose();
}
}
$cpptreetop->dispose();
}
if (!$parserState->{inMacro}) {
$parserState->{NEXTTOKENNOCPP} = 0;
}
# Throw away any empty entries caused by Perl seeing two
# adjacent tokens that match the split regexp. We don't
# want them or care about them, and they break things
# rather badly if we don't....
my @stripparts = @parts;
@parts = ();
print STDERR "BEGIN PARTLIST 2:\n" if ($spaceDebug);
foreach my $strippart (@stripparts) {
if (length($strippart)) {
print STDERR "MYPART: \"$strippart\"\n" if ($spaceDebug);
push(@parts, $strippart);
}
}
print STDERR "END PARTLIST 2.\n" if ($spaceDebug);
# This bit of code needs a bit of explanation, I think.
# We need to be able to see the token that follows the one we
# are currently processing. To do this, we actually keep track
# of the current token, and the previous token, but name then
# $nextpart and $part. We do processing on $part, which gets
# assigned the value from $nextpart at the end of the loop.
#
# To avoid losing the last part of the declaration (or needing
# to unroll an extra copy of the entire loop code) we push a
# bogus entry onto the end of the stack, which never gets
# used (other than as a bogus "next part") because we only
# process the value in $part.
#
# To avoid problems, make sure that you don't ever have a regexp
# that would match against this bogus token.
#
my $part = "";
push(@parts, "BOGUSBOGUSBOGUSBOGUSBOGUS");
if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POSTCPPPARTLIST: \"$partlist\"\n"; }}
foreach my $nextpart (@parts) {
my $hideTokenAndMaybeContents = 0;
$treeSkip = 0;
# $treePopTwo = 0;
# $treePopOnNewLine = 0;
# The current token is now in "part", and the literal next
# token in "nextpart". We can't just work with this as-is,
# though, because you can have multiple spaces, null
# tokens when two of the tokens in the split list occur
# consecutively, etc.
print STDERR "MYPART: \"$part\"\n" if ($localDebug || $spaceDebug);
$forcenobreak = 0;
if ($nextpart eq "\r") { $nextpart = "\n"; }
if ($localDebug && $nextpart eq "\n") { print STDERR "NEXTPART IS NEWLINE!\n"; }
if ($localDebug && $part eq "\n") { print STDERR "PART IS NEWLINE!\n"; }
### if ($nextpart ne "\n" && $nextpart =~ /\s/o) {
### # Replace tabs with spaces.
### $nextpart = " ";
### }
# Replace tabs with spaces.
$part =~ s/\t/ /g;
$nextpart =~ s/\t/ /g;
if ($part ne "\n" && $part =~ /\s/o && $nextpart ne "\n" &&
$nextpart =~ /\s/o) {
# we're a space followed by a space. Join the tokens.
print STDERR "MERGED \"$part\" and \"$nextpart\" into " if ($spaceDebug);
$nextpart = $part.$nextpart;
print STDERR "\"$nextpart\".\n" if ($spaceDebug);
$part = $nextpart;
next;
}
print STDERR "PART IS \"$part\"\n" if ($localDebug || $parserStackDebug || $parseDebug || $liteDebug || $spaceDebug);
print STDERR "CURLINE IS \"$curline\"\n" if ($localDebug || $hangDebug);
print STDERR "INOP: ".$parserState->{inOperator}."\n" if ($operatorDebug);
if (!length($nextpart)) {
print STDERR "SKIP NP\n" if ($localDebug);
next;
}
if (!length($part)) {
print STDERR "SKIP PART\n" if ($localDebug);
$part = $nextpart;
next;
}
if ($occPushParserStateOnWordTokenAfterNext > 1) {
if ($part =~ /\w/) {
$occPushParserStateOnWordTokenAfterNext--;
print STDERR "occPushParserStateOnWordTokenAfterNext -> $occPushParserStateOnWordTokenAfterNext (--)\n" if ($localDebug || $parseDebug);
}
} elsif ($occPushParserStateOnWordTokenAfterNext) {
# if ($part !~ /(\s|<)/)
if ($part =~ /(\/\/|\/\*|\-|\+|\w|\@)/) {
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[occPushParserStateOnWordTokenAfterNext]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 0;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
}
}
# If we get here, we aren't skipping a null or whitespace token.
# Let's print a bunch of noise if debugging is enabled.
# if ($part eq "\n" && $nextpart ne "BOGUSBOGUSBOGUSBOGUSBOGUS") {
# $fileoffset++;
# }
if ($part eq "\n" && $incrementoffsetatnewline) {
$incrementoffsetatnewline--;
$fileoffset++;
}
print STDERR "IN LOOP LANG: $lang INITIAL SUBLANG: $sublang\n" if ($localDebug || $parseDebug);
if ($parseDebug) {
print STDERR "PART: $part, type: $parserState->{typestring}, inComment: $parserState->{inComment}, inInlineComment: $parserState->{inInlineComment}, inChar: $parserState->{inChar}.\n" if ($localDebug);
print STDERR "PART: inBrackets: $parserState->{inBrackets}\n" if ($localDebug);
print STDERR "PART: onlyComments: $parserState->{onlyComments}, inClass: $parserState->{inClass}\n";
print STDERR "PART: cbsodname: $parserState->{cbsodname}\n";
print STDERR "PART: classIsObjC: $parserState->{classIsObjC}, PPSAT: $pushParserStateAfterToken, PPSAWordT: $pushParserStateAfterWordToken, PPSABrace: $pushParserStateAtBrace, occPPSOnWordTokenAfterNext: $occPushParserStateOnWordTokenAfterNext\n";
print STDERR "PART: bracecount: " . scalar(@braceStack) . " (init was $parserState->{initbsCount}).\n";
print STDERR "PART: inString: $parserState->{inString}, callbackNamePending: $parserState->{callbackNamePending}, namePending: $parserState->{namePending}, lastsymbol: $parserState->{lastsymbol}, lasttoken: $lasttoken, lastchar: $lastchar, SOL: $parserState->{startOfDec}\n" if ($localDebug);
print STDERR "PART: sodclass: $parserState->{sodclass} sodname: $parserState->{sodname}\n";
print STDERR "PART: sodtype: $parserState->{sodtype}\n";
print STDERR "PART: simpleTypedef: $parserState->{simpleTypedef}\n";
print STDERR "PART: posstypes: $parserState->{posstypes}\n";
print STDERR "PART: seenBraces: $parserState->{seenBraces} inRegexp: $inRegexp\n";
print STDERR "PART: regexpNoInterpolate: $regexpNoInterpolate\n";
print STDERR "PART: seenTilde: $parserState->{seenTilde}\n";
print STDERR "PART: CBN: $parserState->{callbackName}\n";
print STDERR "PART: regexpStack is:";
foreach my $token (@regexpStack) { print STDERR " $token"; }
print STDERR "\n";
print STDERR "PART: npplStack: ".scalar(@{$parserState->{pplStack}})." nparsedParamList: ".scalar(@{$parserState->{parsedParamList}})." nfreezeStack: ".scalar(@{$parserState->{freezeStack}})." frozen: $parserState->{stackFrozen}\n";
print STDERR "PART: inMacro: $parserState->{inMacro} treePopOnNewLine: $treePopOnNewLine\n";
print STDERR "PART: occmethod: $parserState->{occmethod} occmethodname: $parserState->{occmethodname}\n";
print STDERR "PART: returntype is $parserState->{returntype}\n";
print STDERR "length(declaration) = " . length($declaration) ."; length(curline) = " . length($curline) . "\n";
print STDERR "REQUIREDREGEXP IS \"$requiredregexp\"\n";
print STDERR "DEC: $declaration\n$curline\n";
} elsif ($tsDebug || $treeDebug) {
print STDERR "BPPART: $part\n";
}
if ($parserStackDebug) {
print STDERR "parserState: STACK CONTAINS ".scalar(@parserStack)." STATES\n";
print STDERR "parserState is $parserState\n";
}
# The ignore function returns either null, an empty string,
# or a string that gives the text equivalent of an availability
# macro. If the token is non-null and the length is non-zero,
# it's an availability macro, so blow it in as if the comment
# contained an @availability tag.
#
my $tempavail = ignore($part, $ignoreref, $perheaderignoreref);
printf("PART: $part TEMPAVAIL: $tempavail\n") if ($localDebug || $gccAttributeDebug);
if ($tempavail && ($tempavail ne "1") && ($tempavail ne "2")) {
$parserState->{availability} = $tempavail;
} elsif ($tempavail eq "2") {
# Reusing the GCC attribute handling code because that does exactly what we need.
print STDERR "Function-like availability macro detected. Collecting.\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = 1;
$parserState->{attributeParts} = ();
# Add __attribute__ as the next token.
$treeCur = $treeCur->addSibling($part, 0);
push(@treeStack, $treeCur);
my @tempAvailabilityNodesArray = ();
if ($parserState->{availabilityNodesArray}) {
@tempAvailabilityNodesArray = @{$parserState->{availabilityNodesArray}};
}
push(@tempAvailabilityNodesArray, $treeCur);
# print STDERR "ADDED $treeCur\n";
# $treeCur->dbprint();
$parserState->{availabilityNodesArray} = \@tempAvailabilityNodesArray;
# Nest all contents one level lower.
$treeCur = $treeCur->addChild("", 0);
$part = $nextpart;
next;
}
# Handle the GCC "__attribute__" extension outside the context of
# the parser because it isn't part of the language and massively
# breaks the syntax.
if ($lang eq "C" && isKeyword($part, $keywordhashref, $case_sensitive) == 2) {
print STDERR "GCC attribute detected. Collecting.\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = 1;
$parserState->{attributeParts} = ();
# Add __attribute__ as the next token.
$treeCur = $treeCur->addSibling($part, 0);
push(@treeStack, $treeCur);
# Nest all contents one level lower.
$treeCur = $treeCur->addChild("", 0);
$part = $nextpart;
next;
} elsif ($parserState->{attributeState} == 1) {
if ($part eq "(") {
print STDERR "GCC attribute open paren\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = -1;
}
$treeCur = $treeCur->addSibling($part, 0);
$part = $nextpart;
next;
} elsif ($parserState->{attributeState} < 0) {
if ($part eq "(") {
$parserState->{attributeState}--;
print STDERR "GCC attribute open paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug);
} elsif ($part eq ")") {
$parserState->{attributeState}++;
print STDERR "GCC attribute close paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug);
}
$treeCur = $treeCur->addSibling($part, 0);
if (($localDebug || $gccAttributeDebug) && !$parserState->{attributeState}) {
print STDERR "GCC attribute: done collecting.\n";
# Get back to where we started.
$treeCur = pop(@treeStack);
}
$part = $nextpart;
next;
}
# Here be the parser. Abandon all hope, ye who enter here.
$treepart = "";
if ($parserState->{inProtocol} == 1) {
print STDERR "INPROTOCOL: 1\n" if ($parseDebug || $classDebug);
if ($part =~ /\w/) {
print STDERR "INPROTOCOL: 1 -> 2\n" if ($parseDebug || $classDebug);
$parserState->{inProtocol} = 2;
}
} elsif ($parserState->{inProtocol} == 2) {
print STDERR "INPROTOCOL: 2\n" if ($parseDebug || $classDebug);
if ($part eq "<") {
print STDERR "INPROTOCOL: 2 -> 3\n" if ($parseDebug || $classDebug);
$parserState->{extendsProtocol} = "";
$parserState->{inProtocol} = 3;
} elsif ($part =~ /\S/) {
# PUSH PARSER STATE
print STDERR "parserState pushed onto stack[PROTOCOL]\n" if ($parserStackDebug);
$parserState->{inProtocol} = -1;
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterWordToken = 0;
}
} elsif ($parserState->{inProtocol} == 3) {
print STDERR "INPROTOCOL: 3\n" if ($parseDebug || $classDebug);
if ($part eq ">") {
print STDERR "INPROTOCOL: 3 -> 2\n" if ($parseDebug || $classDebug);
$parserState->{inProtocol} = 2;
} else {
$parserState->{extendsProtocol} .= $part;
}
}
if ($parserState->{inClass} == 3) {
print STDERR "INCLASS3\n" if ($parseDebug || $classDebug);
if ($part eq ")") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [1]\n" if ($classDebug);
$parserState->{categoryClass} .= $part;
print STDERR "parserState will be pushed onto stack[cparen3]\n" if ($parserStackDebug);
# $parserState->{lastTreeNode} = $treeCur;
# push(@parserStack, $parserState);
# $parserState = HeaderDoc::ParserState->new();
# $parserState->{lang} = $lang;
# $parserState->{inputCounter} = $inputCounter;
# $parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterToken = 1;
} elsif ($part eq ":") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [2]\n" if ($classDebug);
if ($parserState->{classIsObjC}) {
print STDERR "occPushParserStateOnWordTokenAfterNext -> 2\n" if ($localDebug || $parseDebug);
$occPushParserStateOnWordTokenAfterNext = 2;
} else {
$pushParserStateAfterWordToken = 1;
}
# if ($sublang eq "occ") {
# $pushParserStateAtBrace = 2;
# }
} elsif ($part =~ /</ && $parserState->{classIsObjC}) {
print STDERR "pushParserStateAfterWordToken -> 0 (Conforming)\n" if ($localDebug || $parseDebug);
print STDERR "inClassConformingToProtocol -> 1\n" if ($localDebug || $parseDebug);
$pushParserStateAfterWordToken = 0;
$parserState->{inClassConformingToProtocol} = 1;
$occPushParserStateOnWordTokenAfterNext = 0;
} elsif ($part =~ />/ && $parserState->{classIsObjC} && $parserState->{inClassConformingToProtocol}) {
print STDERR "inClassConformingToProtocol -> 0\n" if ($localDebug || $parseDebug);
$pushParserStateAfterToken = 1;
print STDERR "pushParserStateAfterWordToken -> 1 (Conforming)\n" if ($localDebug || $parseDebug);
$parserState->{inClassConformingToProtocol} = 0;
} else {
$parserState->{categoryClass} .= $part;
}
} elsif ($parserState->{inClass} == 2) {
print STDERR "INCLASS2\n" if ($parseDebug || $classDebug);
if ($part eq ")") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [3]\n" if ($classDebug);
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[cparen2]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
} elsif ($part eq ":") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [4]\n" if ($classDebug);
if ($parserState->{classIsObjC}) {
print STDERR "occPushParserStateOnWordTokenAfterNext -> 2\n" if ($localDebug || $parseDebug);
$occPushParserStateOnWordTokenAfterNext = 2;
} else {
$pushParserStateAfterWordToken = 2;
}
} elsif ($part =~ /\w/) {
# skip the class name itself.
$parserState->{inClass} = 3;
print STDERR "inClass -> 3 [5]\n" if ($classDebug);
}
} elsif ($parserState->{inClass} == 1) {
print STDERR "INCLASS1\n" if ($parseDebug || $classDebug);
# print STDERR "inclass Part is $part\n";
if ($part eq ":") {
print STDERR "INCLASS COLON\n" if ($parseDebug || $classDebug);
$parserState->{forceClassName} = $parserState->{sodname};
$parserState->{forceClassSuper} = "";
# print STDERR "XSUPER: $parserState->{forceClassSuper}\n";
} elsif ($part eq "{" || $part eq ";") {
print STDERR "INCLASS BRCSEMI\n" if ($parseDebug || $classDebug);
$parserState->{forceClassDone} = 1;
if ($parserState->{classIsObjC} && $part eq "{") {
$parserState->{ISFORWARDDECLARATION} = 0;
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[OCC-BRCSEMI]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 0;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack) + 1; # NOTE: add one here because it will change in the SWITCH to follow.
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
$pushParserStateAfterToken = 1;
} elsif ($part eq ";") {
if (!defined($parserState->{ISFORWARDDECLARATION})) {
print STDERR "FORWARD DECLARATION DETECTED\n" if ($parseDebug || $localDebug || $liteDebug);
# print STDERR "PREVIOUS FD STATE: ".$parserState->{ISFORWARDDECLARATION}."\n";
$parserState->{ISFORWARDDECLARATION} = 1;
}
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
$pushParserStateAfterToken = 0;
}
} elsif ($parserState->{forceClassName} && !$parserState->{forceClassDone}) {
print STDERR "INCLASS ADD\n" if ($parseDebug || $classDebug);
if ($part =~ /[\n\r]/) {
$parserState->{forceClassSuper} .= " ";
} else {
$parserState->{forceClassSuper} .= $part;
}
# print STDERR "SUPER IS $parserState->{forceClassSuper}\n";
} elsif ($part =~ /</ && $parserState->{classIsObjC} && $occPushParserStateOnWordTokenAfterNext) {
print STDERR "INCLASS <\n" if ($parseDebug || $classDebug);
print STDERR "pushParserStateAfterWordToken -> 0 (Conforming)\n" if ($localDebug || $parseDebug);
print STDERR "inClassConformingToProtocol -> 1\n" if ($localDebug || $parseDebug);
$pushParserStateAfterWordToken = 0;
$parserState->{inClassConformingToProtocol} = 1;
$occPushParserStateOnWordTokenAfterNext = 0;
} elsif ($part =~ />/ && $parserState->{classIsObjC} && $parserState->{inClassConformingToProtocol}) {
print STDERR "INCLASS >\n" if ($parseDebug || $classDebug);
print STDERR "inClassConformingToProtocol -> 0\n" if ($localDebug || $parseDebug);
$pushParserStateAfterToken = 1;
print STDERR "pushParserStateAfterWordToken -> 1 (Conforming)\n" if ($localDebug || $parseDebug);
$parserState->{inClassConformingToProtocol} = 0;
} elsif ($occPushParserStateOnWordTokenAfterNext && $part =~ /\w/) {
print STDERR "INCLASS OCCSUPER\n" if ($parseDebug || $classDebug);
$parserState->{occSuper} = $part;
# $occPushParserStateOnWordTokenAfterNext = 0;
# $pushParserStateAfterToken = 1;
} elsif (!$parserState->{classIsObjC}) {
print STDERR "INCLASS NOTOBJC (OTHER)\n" if ($parseDebug || $classDebug);
if ($part =~ /[*(^]/) {
print STDERR "INCLASS DROP\n" if ($parseDebug || $classDebug);
$parserState->{inClass} = 0; # We're an instance. Either a variable or a function.
print STDERR "inClass -> 0 [6]\n" if ($classDebug);
$parserState->{sodtype} = $parserState->{preclasssodtype} . $parserState->{sodtype};
}
# } else {
# print STDERR "BUG\n";
}
};
if ($parserState->{inClassConformingToProtocol} == 1) {
$parserState->{inClassConformingToProtocol} = 2;
} elsif ($parserState->{inClassConformingToProtocol}) {
$parserState->{conformsToList} .= $part;
}
if ($macroDebug) {
print STDERR "MNT: ".$parserState->{macroNoTrunc}."\n";
}
# if (($part eq $ilc || $part eq $ilc_b) && ($lang ne "perl" || $lasttoken ne "\$")) {
# print STDERR "should be ILC?\n";
# } else {
# print STDERR "NO CHANEC: PART \"$part\" ILC \"$ilc\" ILC_B: \"ilc_b\" LANG: \"$lang\" LASTTOKEN: \"$lasttoken\"\n";
# }
SWITCH: {
# Blank declaration handlers (mostly for misuse of
# OSMetaClassDeclareReservedUsed and similar)
(($part eq ";") && ($parserState->{startOfDec} == 1) && !$parserState->{inMacro} && !$parserState->{inMacroLine} && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "LEADING SEMICOLON: CASE 01\n" if ($liteDebug);
print STDERR "Dropping empty declaration\n" if ($localDebug || $parseDebug);
$part = "";
last SWITCH;
};
# Macro handlers
(($parserState->{inMacro} == 1) && ($part eq "define")) && do {
print STDERR "INMACRO/DEFINE: CASE 02\n" if ($liteDebug);
# define may be a multi-line macro
print STDERR "INMACRO AND DEFINE\n" if ($parseDebug || $localDebug);
$parserState->{inMacro} = 3;
print STDERR "inMacro -> 3\n" if ($macroDebug || $cppDebug);
$parserState->{sodname} = "";
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [1]\n"; }
$treePopOnNewLine = 2;
$pound .= $part;
$treeCur->token($pound);
}
last SWITCH;
};
# (($parserState->{inMacro} == 1 && $macrore_pound ne "" && $part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)/ && ($part ne $definename)) || ($parserState->{inMacro} == 0 && $macrore_nopound ne "" && $part =~ /$macrore_nopound/))
# (($parserState->{inMacro} == 1 && $part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)/ )) && do
(!$parserState->{inComment} && (($parserState->{inMacro} == 1 && $macrore_pound ne "" && $part =~ /^$macrore_pound$/ && ($part ne $definename)) || ($parserState->{inMacro} == 0 && $macrore_nopound ne "" && $part =~ /^$macrore_nopound$/))) && do {
print STDERR "MACRORE-v: \"$macrore_pound\"\n" if ($macroDebug);
print STDERR "MACRORE-r: \"(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)\"\n" if ($macroDebug);
print STDERR "MACRORE-n: \"$macrore_nopound\"\n" if ($macroDebug);
print STDERR "INMACRO/IF: CASE 03\n" if ($liteDebug);
print STDERR "INMACRO AND IF/IFDEF/IFNDEF/ENDIF/ELSE/PRAGMA/IMPORT/INCLUDE\n" if ($parseDebug || $localDebug);
# these are all single-line macros
$parserState->{inMacro} = 4;
print STDERR "inMacro -> 4\n" if ($macroDebug || $cppDebug);
$parserState->{sodname} = "";
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [2]\n"; }
$treePopOnNewLine = 1;
$pound .= $part;
$treeCur->token($pound);
if ($part eq "endif") {
# the rest of the line is not part of the macro
# NOTE: Do not change treeCur in the
# next line.
$treeCur->addChild("\n", 0);
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [3]\n"; }
$treePopOnNewLine = 0;
$treeSkip = 1;
}
}
last SWITCH;
};
(($parserState->{inMacroLine} == 1) && ($part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include|define)/o)) && do {
print STDERR "INMACROLINE/IF: CASE 04\n" if ($liteDebug);
print STDERR "INMACROLINE AND IF/IFDEF/IFNDEF/ENDIF/ELSE/PRAGMA/IMPORT/INCLUDE\n" if ($parseDebug || $localDebug);
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$pound .= $part;
$treeCur->token($pound);
if ($part =~ /define/o) {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [4]\n"; }
$treePopOnNewLine = 2;
} elsif ($part eq "endif") {
# the rest of the line is not part of the macro
# NOTE: Do not change treeCur in the
# next line.
$treeCur->addChild("\n", 0);
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [5]\n"; }
$treePopOnNewLine = 0;
$treeSkip = 1;
} else {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [6]\n"; }
$treePopOnNewLine = 1;
}
}
last SWITCH;
};
($parserState->{inMacro} == 1 && ($part ne $soc) && ($part ne $eoc) && $part =~ /\s/) && do {
$treepart = $part; $part = "";
last SWITCH;
};
($parserState->{inMacro} == 1 && ($part ne $soc) && ($part ne $eoc)) && do {
print STDERR "INMACRO PPTOKEN: CASE 05\n" if ($liteDebug);
print STDERR "INMACRO IS 1, CHANGING TO 2 (NO PROCESSING)\n" if ($parseDebug || $localDebug);
# error case.
$parserState->{inMacro} = 2;
print STDERR "inMacro -> 2\n" if ($macroDebug || $cppDebug);
last SWITCH;
};
($parserState->{inMacro} > 1 && $part ne "//" && $part !~ /[\n\r]/ && ($part ne $soc) && ($part ne $eoc)) && do {
print STDERR "INMACRO OTHERTOKEN: CASE 06\n" if ($liteDebug);
print STDERR "INMACRO > 1, PART NE //" if ($parseDebug || $localDebug);
if ($part eq "\\") {
$parserState->addBackslash();
} elsif ($part !~ /[ \t]/) {
$parserState->addBackslash();
}
print STDERR "PART: $part\n" if ($macroDebug);
if ($parserState->{seenMacroPart} && $HeaderDoc::truncate_inline) {
print STDERR "MACRO: SMP&TI\n" if ($macroDebug);
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
print STDERR "MACRO: NOSTACK\n" if ($macroDebug);
if ($part =~ /\s/o && $parserState->{macroNoTrunc} == 1) {
print STDERR "MACRO: ENDOFNAME\n" if ($macroDebug);
$parserState->{macroNoTrunc} = 0;
} elsif ($part =~ /[\{\(]/o) {
print STDERR "MACRO: BRACE\n" if ($macroDebug);
if (!$parserState->{macroNoTrunc}) {
# $parserState->{seenBraces} = 1;
$HeaderDoc::hidetokens = 3;
}
} else {
print STDERR "MACRO: OTHERTOKEN\n" if ($macroDebug);
$parserState->{macroNoTrunc} = 2;
}
}
}
if ($part =~ /[\{\(]/o) {
push(@braceStack, $part);
print STDERR "PUSH\n" if ($macroDebug);
} elsif ($part =~ /[\}\)]/o) {
if ($part ne peekmatch(\@braceStack, $filename, $inputCounter)) {
if ($parserState->{macroNoTrunc} == 1) {
# We haven't reached the end of the first part of the declaration, so this is an error.
warn("$filename:$inputCounter: warning: Initial braces in macro name do not match.\nWe may have a problem.\n");
}
}
pop(@braceStack);
print STDERR "POP\n" if ($macroDebug);
}
if ($part =~ /\S/o) {
$parserState->{seenMacroPart} = 1;
$parserState->{lastsymbol} = $part;
if (($parserState->{sodname} eq "") && ($parserState->{inMacro} == 3)) {
print STDERR "DEFINE NAME IS $part\n" if ($macroDebug);
$parserState->{sodname} = $part;
}
}
$lastchar = $part;
last SWITCH;
};
# Regular expression handlers
# print STDERR "IRE: $inRegexp IRT: $inRegexpTrailer IS: $parserState->{inString} ICo $parserState->{inComment} ILC: $parserState->{inInlineComment} ICh $parserState->{inChar}\n";
(length($regexppattern) && $part =~ /^($regexppattern)$/ && !($inRegexp || $inRegexpTrailer || $parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "REGEXP PATTERN: CASE 07\n" if ($liteDebug);
my $match = $1;
print STDERR "REGEXP WITH PREFIX\n" if ($regexpDebug);
$regexpNoInterpolate = 0;
if ($match =~ /^($singleregexppattern)$/) {
# e.g. perl PATTERN?
$inRegexp = 2;
} else {
$inRegexp = 4;
# print STDERR "REGEXP PART IS \"$part\"\n";
if ($part eq "tr") { $regexpNoInterpolate = 1; }
# if ($part =~ /tr/) { $regexpNoInterpolate = 1; }
}
last SWITCH;
}; # end regexppattern
(($inRegexp || $parserState->{lastsymbol} eq "~") && (length($regexpcharpattern) && $part =~ /^($regexpcharpattern)$/ && (!scalar(@regexpStack) || $part eq peekmatch(\@regexpStack, $filename, $inputCounter)))) && do {
print STDERR "REGEXP CHARACTER: CASE 08\n" if ($liteDebug);
print STDERR "REGEXP?\n" if ($regexpDebug);
if (!$inRegexp) {
$inRegexp = 2;
}
# if ($lasttoken eq "\\")
if ($parserState->isQuoted($lang. $sublang)) {
# jump to next match.
$lasttoken = $part;
$parserState->{lastsymbol} = $part;
next SWITCH;
}
print STDERR "REGEXP POINT A\n" if ($regexpDebug);
$lasttoken = $part;
$parserState->{lastsymbol} = $part;
if ($part eq "#" &&
((scalar(@regexpStack) != 1) ||
(peekmatch(\@regexpStack, $filename, $inputCounter) ne "#"))) {
if ($nextpart =~ /^\s/o) {
# it's a comment. jump to next match.
next SWITCH;
}
}
print STDERR "REGEXP POINT B\n" if ($regexpDebug);
if (!scalar(@regexpStack)) {
push(@regexpStack, $part);
$inRegexp--;
} else {
my $match = peekmatch(\@regexpStack, $filename, $inputCounter);
my $tos = pop(@regexpStack);
if (!scalar(@regexpStack) && ($match eq $part)) {
$inRegexp--;
if ($inRegexp == 2 && $tos eq "/") {
# we don't double the slash in the
# middle of a s/foo/bar/g style
# expression.
$inRegexp--;
}
if ($inRegexp) {
push(@regexpStack, $tos);
}
} elsif (scalar(@regexpStack) == 1) {
push(@regexpStack, $tos);
if ($tos =~ /['"`]/o || $regexpNoInterpolate) {
# these don't interpolate.
next SWITCH;
}
} else {
push(@regexpStack, $tos);
if ($tos =~ /['"`]/o || $regexpNoInterpolate) {
# these don't interpolate.
next SWITCH;
}
push(@regexpStack, $part);
}
}
print STDERR "REGEXP POINT C\n" if ($regexpDebug);
if (!$inRegexp) {
$inRegexpTrailer = 2;
}
last SWITCH;
}; # end regexpcharpattern
# Start of preprocessor macros
($part eq "$sopreproc") && do {
print STDERR "SOPREPROC: CASE 09\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parserState->{onlyComments}) {
print STDERR "inMacro -> 1\n" if ($macroDebug || $cppDebug);
$parserState->{inMacro} = 1;
## @@@ FIXME DAG NEXT TWO LINES NEEDED FOR IDL TO AVOID
## "warning: Declaration starts with # but is not preprocessor macro"
## ERROR MESSAGE, BUT THIS BREAKS C/C++.
## WHY !?!?!
##
## if ($$treepart = " ";
## $nextpart = $part.$nextpart;
##
## END IDL-ONLY BLOCK
# $continue = 0;
# print STDERR "continue -> 0 [1]\n" if ($localDebug || $macroDebug);
} elsif ($curline =~ /^\s*$/o) {
$parserState->{inMacroLine} = 1;
print STDERR "IML\n" if ($localDebug);
} elsif ($postPossNL) {
print STDERR "PRE-IML \"$curline\"\n" if ($localDebug || $macroDebug);
$treeCur = $treeCur->addSibling("\n", 0);
bless($treeCur, "HeaderDoc::ParseTree");
$parserState->{inMacroLine} = 1;
$postPossNL = 0;
}
}
};
# Start of token-delimited functions and procedures (e.g.
# Pascal and PHP)
($part eq "$sofunction" || $part eq "$soprocedure") && do {
print STDERR "SOFUNC: CASE 10\n" if ($liteDebug);
$parserState->{sodclass} = "function";
print STDERR "K&R C FUNCTION FOUND [1].\n" if ($localDebug);
$parserState->{kr_c_function} = 1;
$parserState->{typestring} = "function";
$parserState->{startOfDec} = 2;
$parserState->{namePending} = 1;
# if (!$parserState->{seenBraces}) { # TREEDONE
# $treeNest = 1;
# $treePopTwo++;
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
# }
print STDERR "namePending -> 1 [1]\n" if ($parseDebug);
last SWITCH;
};
# C++ destructor handler.
($part =~ /\~/o && $lang eq "C" && $sublang eq "cpp" && !!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "C++ DESTRUCTOR: CASE 11\n" if ($liteDebug);
print STDERR "TILDE\n" if ($localDebug);
$parserState->{seenTilde} = 2;
$lastchar = $part;
$parserState->{onlyComments} = 0;
# $name .= '~';
last SWITCH;
};
# Objective-C method handler.
($part =~ /[-+]/o && $parserState->{onlyComments}) && do {
print STDERR "OBJC METHOD: CASE 12\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
print STDERR "OCCMETHOD\n" if ($localDebug);
# Objective C Method.
$parserState->{occmethod} = 1;
$parserState->{occmethodtype} = $part;
$lastchar = $part;
$parserState->{onlyComments} = 0;
print STDERR "[a]onlyComments -> 0\n" if ($macroDebug);
if (!$parserState->{seenBraces}) { # TREEDONE
if (!$parserState->{hollow}) {
print STDERR "SETHOLLOW -> 1\n" if ($parserStackDebug);
$sethollow = 1;
}
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [7]\n"; }
$parserState->{treePopTwo} = 1;
}
}
last SWITCH;
};
# Newline handler.
($part =~ /[\n\r]/o) && do {
print STDERR "NEWLINE: CASE 13\n" if ($liteDebug);
# NEWLINE FOUND
$treepart = $part;
if ($inRegexp) {
warn "$filename:$inputCounter: warning: multi-line regular expression\n";
}
print STDERR "NLCR\n" if ($tsDebug || $treeDebug || $localDebug);
if ($lastchar !~ /[\,\;\{\(\)\}]/o && $nextpart !~ /[\{\}\(\)]/o) {
if ($lastchar ne "*/" && $nextpart ne "/*") {
if (!$parserState->{inMacro} && !$parserState->{inMacroLine} && !$treePopOnNewLine) {
print STDERR "NL->SPC\n" if ($localDebug);
$part = " ";
print STDERR "LC: $lastchar\n" if ($localDebug);
print STDERR "NP: $nextpart\n" if ($localDebug);
$postPossNL = 2;
} else {
$parserState->{inMacroLine} = 0;
# Don't push parsed parameter here. Just clear it.
# push(@{$parserState->{parsedParamList}}, $parsedParam);
# print STDERR "pushed $parsedParam into parsedParamList [1]\n" if ($parmDebug);
print STDERR "skipped pushing CPP directive $parsedParam into parsedParamList [1]\n" if ($parmDebug || $cppDebug || $localDebug);
$parsedParam = "";
}
}
}
if ($treePopOnNewLine < 0) {
# pop once for //, possibly again for macro
$treePopOnNewLine = 0 - $treePopOnNewLine;
$treeCur = $treeCur->addSibling($treepart, 0);
bless($treeCur, "HeaderDoc::ParseTree");
# push(@treeStack, $treeCur);
$treeSkip = 1;
$treeCur = pop(@treeStack);
if (!$treeCur) {
$treeCur = $treeTop;
warn "$filename:$inputCounter: warning: Attempted to pop off top of tree\n";
}
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [1]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($treePopOnNewLine == 1 || ($treePopOnNewLine && !$parserState->isQuoted())) {
# $parserState->{lastsymbol} ne "\\"
$treeCur = $treeCur->addSibling($treepart, 0);
bless($treeCur, "HeaderDoc::ParseTree");
# push(@treeStack, $treeCur);
$treeSkip = 1;
$treeCur = pop(@treeStack);
if (!$treeCur) {
$treeCur = $treeTop;
warn "$filename:$inputCounter: warning: Attempted to pop off top of tree\n";
}
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->addSibling("", 0); # empty token
print STDERR "TSPOP [1a]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
$treePopOnNewLine = 0;
$HeaderDoc::hidetokens = 0;
} else {
print STDERR "Not popping from tree. Probably quoted.\n" if ($localDebug || $parseDebug);
}
next SWITCH;
};
# C++ template handlers
($part eq $sotemplate && !$parserState->{seenBraces} && ($parserState->{inOperator} != 1)) && do {
print STDERR "C++ TEMPLATE: CASE 14\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($HeaderDoc::hideIDLAttributes && $lang eq "C" && $sublang eq "IDL") { $hideTokenAndMaybeContents = 3; }
print STDERR "inTemplate -> ".($parserState->{inTemplate}+1)."\n" if ($localDebug);
print STDERR "SBS: " . scalar(@braceStack) . ".\n" if ($localDebug);
$parserState->{inTemplate}++;
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
$parserState->{preTemplateSymbol} = $parserState->{lastsymbol};
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{onlyComments} = 0;
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if (!$parserState->{hollow}) { $sethollow = 1; } # IDL can have this at the start of declaration.
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [8]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
print STDERR "[b]onlyComments -> 0\n" if ($macroDebug);
}
last SWITCH;
};
($part eq $eotemplate && !$parserState->{seenBraces} && ($parserState->{inOperator} != 1)) && do {
print STDERR "C++ TEMPLATE END: CASE 15\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && (!(scalar(@braceStack)-$parserState->{initbsCount}) || $parserState->{inTemplate})) {
if ($parserState->{inTemplate}) {
print STDERR "parserState->{inTemplate} -> ".($parserState->{inTemplate}-1)."\n" if ($localDebug);
$parserState->{inTemplate}--;
$parserState->{lastsymbol} = "";
$lastchar = $part;
$curline .= " ";
$parserState->{onlyComments} = 0;
print STDERR "[c]onlyComments -> 0\n" if ($macroDebug);
}
my $top = pop(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [2]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($top ne "$sotemplate") {
warn("$filename:$inputCounter: warning: Template (angle) brackets do not match.\nWe may have a problem.\n");
}
}
last SWITCH;
};
#
# Handles C++ access control state, e.g. "public:"
#
($part eq ":") && do {
print STDERR "Access control colon: CASE 16\n" if ($liteDebug);
print STDERR "TS IS \"$parserState->{typestring}\"\n" if ($localDebug || $parseDebug);
# fall through to next colon handling case if we fail.
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (length($accessregexp) && ($lastnspart =~ /$accessregexp/)) {
# We're special.
print STDERR "PERMANENT ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$parserState->{typestring} = "";
print STDERR "RESET HOLLOW at $part\n" if ($parserStackDebug);
$parserState->{hollow} = undef;
$parserState->{onlyComments} = 1;
print STDERR "hollowskip -> 1 (ACS)\n" if ($parserStateInsertDebug);
$hollowskip = 1;
$HeaderDoc::AccessControlState = $1;
$lastACS = $1;
last SWITCH;
} elsif ($parserState->{typestring} eq "struct") {
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
if (!$parserState->{structClassName}) {
$parserState->{structClassName} = $parserState->{lastsymbol};
$parserState->{bracePending} = 2;
}
}
}
}
};
(length($accessregexp) && ($part =~ /$accessregexp/)) && do {
print STDERR "Access regexp: CASE 17\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
# We're special.
if ($part =~ /^\@(.*)$/) {
print STDERR "PERMANENT ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$parserState->{typestring} = "";
print STDERR "RESET HOLLOW at $part\n" if ($parserStackDebug);
$parserState->{hollow} = undef;
$parserState->{onlyComments} = 1;
$hollowskip = 1;
print STDERR "hollowskip -> 1 (\@ACS)\n" if ($parserStateInsertDebug);
$HeaderDoc::AccessControlState = $1;
$lastACS = $1;
last SWITCH;
} else {
print STDERR "TEMPORARY ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$lastACS = $HeaderDoc::AccessControlState;
$HeaderDoc::AccessControlState = $1;
}
} else {
next SWITCH;
}
};
(length($requiredregexp) && $part =~ /$requiredregexp/) && do {
print STDERR "REQUIRED REGEXP MATCH: \"$part\"\n" if ($localDebug || $parseDebug);
$hollowskip = 1;
print STDERR "hollowskip -> 1 (requiredregexp)\n" if ($parserStateInsertDebug);
last SWITCH;
};
#
# C++ copy constructor handler. For example:
#
# char *class(void *a, void *b) :
# class(pri_type, pri_type);
#
($part eq ":") && do {
print STDERR "Copy constructor: CASE 18\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parserState->{occmethod}) {
$parserState->{name} = $parserState->{lastsymbol};
if ($parserState->{occparmlabelfound}) {
$parserState->{occmethodname} .= "$parserState->{lastsymbol}:";
if ($occMethodNameDebug) {
print STDERR "OCC method name now ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\").\n";
}
$parserState->{occparmlabelfound} = -1; # next token is name of this parameter, followed by label for next parameter.
} else {
if ($occMethodNameDebug) {
print STDERR "OCC method name missing.\n";
print STDERR "OCC method name still ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\").\n";
}
$parserState->{occparmlabelfound} = -2; # Special case: grab the parameter name instead because parameter has no label.
}
# Start doing line splitting here.
# Also, capture the method's name.
if ($parserState->{occmethod} == 1) {
$parserState->{occmethod} = 2;
if (!$prespace) { $prespaceadjust = 4; }
$parserState->{onlyComments} = 0;
print STDERR "[d]onlyComments -> 0\n" if ($macroDebug);
}
} else {
if ($lang eq "C" && $sublang eq "cpp") {
if (!(scalar(@braceStack)-$parserState->{initbsCount}) && $parserState->{sodclass} eq "function") {
$inPrivateParamTypes = 1;
$declaration .= "$curline";
$publicDeclaration = $declaration;
$declaration = "";
} else {
next SWITCH;
}
if (!$parserState->{stackFrozen}) {
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
# print STDERR "SEOPPLS\n";
# for my $item (@{$parserState->{pplStack}}) {
# print STDERR "PPLS: $item\n";
# }
# print STDERR "OEOPPLS\n";
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
} else {
next SWITCH;
}
}
if (!$parserState->{seenBraces} && !$parserState->{occmethod}) { # TREEDONE
# $treeCur->addSibling($part, 0); $treeSkip = 1;
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [9]\n"; }
$parserState->{treePopTwo} = 1;
# $treeCur = pop(@treeStack) || $treeTop;
# bless($treeCur, "HeaderDoc::ParseTree");
}
last SWITCH;
} else {
next SWITCH;
}
};
# Non-newline, non-carriage-return whitespace handler.
($part =~ /\s/o) && do {
print STDERR "Whitespace: CASE 19\n" if ($liteDebug);
# just add white space silently.
# if ($part eq "\n") { $parserState->{lastsymbol} = ""; };
$lastchar = $part;
last SWITCH;
};
# backslash handler (largely useful for macros, strings).
($part =~ /\\/o) && do {
print STDERR "BACKSLASH: CASE 20\n" if ($liteDebug);
$parserState->{lastsymbol} = $part; $lastchar = $part;
$parserState->addBackslash();
};
# quote and bracket handlers.
($part eq "\"") && do {
print STDERR "DOUBLE QUOTE: CASE 21\n" if ($liteDebug);
print STDERR "dquo\n" if ($localDebug);
# print STDERR "QUOTEDEBUG: CURSTRING IS '$curstring'\n";
# print STDERR "QUOTEDEBUG: CURLINE IS '$curline'\n";
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{onlyComments} = 0;
print STDERR "[e]onlyComments -> 0\n" if ($macroDebug);
print STDERR "LASTTOKEN: $lasttoken\nCS: $curstring\n" if ($localDebug);
# if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o))
if (!$parserState->isQuoted($lang, $sublang)) {
if (!$parserState->{inString}) {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [10]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} else {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [3]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
$parserState->{inString} = (1-$parserState->{inString});
}
}
$lastchar = $part;
$parserState->{lastsymbol} = "";
last SWITCH;
};
($part eq "[") && do {
print STDERR "LEFT BRACKET: CASE 22\n" if ($liteDebug);
# left square bracket (square brace)
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
print STDERR "lbracket\n" if ($localDebug);
print STDERR "LBRACKET DEBUG TRACE: SODNAME: ".$parserState->{sodname}." SODTYPE: ".$parserState->{sodtype}." SIMPLETDCONTENTS: ".$parserState->{simpleTDcontents}."\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
$parserState->{onlyComments} = 0;
print STDERR "[f]onlyComments -> 0\n" if ($macroDebug);
}
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [11]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$parserState->{inBrackets} += 1;
}
$lastchar = $part;
last SWITCH;
};
($part eq "]") && do {
print STDERR "CLOSE BRACKET: CASE 23\n" if ($liteDebug);
# right square bracket (square brace)
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
print STDERR "rbracket\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
$parserState->{onlyComments} = 0;
print STDERR "[g]onlyComments -> 0\n" if ($macroDebug);
}
my $top = pop(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [4]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($top ne "[") {
warn("$filename:$inputCounter: warning: Square brackets do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
}
pbs(@braceStack);
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$parserState->{inBrackets} -= 1;
}
$lastchar = $part;
last SWITCH;
};
($part eq "'") && do {
print STDERR "SINGLE QUOTE: CASE 24\n" if ($liteDebug);
print STDERR "squo\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
# if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o))
if (!$parserState->isQuoted($lang, $sublang)) {
$parserState->{onlyComments} = 0;
print STDERR "[h]onlyComments -> 0\n" if ($macroDebug);
if (!$parserState->{inChar}) {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [12]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} else {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [5]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
$parserState->{inChar} = !$parserState->{inChar};
}
if ($lastchar =~ /\=$/o) {
$curline .= " ";
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Inline comment (two slashes in c++, hash in perl/shell)
# handler.
(($part eq $ilc || $part eq $ilc_b) && ($lang ne "perl" || $lasttoken ne "\$")) && do {
print STDERR "SINGLE LINE COMMENT: CASE 25\n" if ($liteDebug);
print STDERR "ILC\n" if ($localDebug || $ilcDebug);
if (!($parserState->{inComment} || $parserState->{inChar} || $parserState->{inString} || $inRegexp)) {
$parserState->{inInlineComment} = 4;
print STDERR "inInlineComment -> 1\n" if ($ilcDebug);
$curline = spacefix($curline, $part, $lastchar, $soc, $eoc, $ilc, $ilc_b);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [13]\n"; }
if (!$treePopOnNewLine) {
$treePopOnNewLine = 1;
} else {
$treePopOnNewLine = 0 - $treePopOnNewLine;
}
print STDERR "treePopOnNewLine -> $treePopOnNewLine\n" if ($ilcDebug);
# $treeCur->addSibling($part, 0); $treeSkip = 1;
# $treePopOnNewLine = 1;
# $treeCur = pop(@treeStack) || $treeTop;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif ($parserState->{inComment}) {
my $linenum = $inputCounter + $fileoffset;
if (!$cpp_in_argparse) {
# We've already seen these.
if ($nestedcommentwarn) {
warn("$filename:$linenum: warning: Nested comment found [1]. Ignoring.\n");
}
# This isn't really a problem.
# Don't warn to avoid bogus
# warnings for apple_ref and
# URL markup in comments.
}
# warn("XX $cpp_in_argparse XX $inputCounter XX $fileoffset XX\n");
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Standard comment handlers: soc = start of comment,
# eoc = end of comment.
($part eq $soc) && do {
print STDERR "START OF MULTILINE COMMENT: CASE 26\n" if ($liteDebug);
print STDERR "SOC\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{inComment} = 4;
$curline = spacefix($curline, $part, $lastchar);
if (!$parserState->{seenBraces}) {
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [14]\n"; }
# print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug);
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild("", 0);
# bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif ($parserState->{inComment}) {
my $linenum = $inputCounter + $fileoffset;
# Modern compilers shouldn't have trouble with this. It occurs |
# frequently in apple_ref markup (e.g. //apple_ref/C/instm/ \|/
# IOFireWireDeviceInterface/AddIsochCallbackDispatcherToRunLoop/*Add
# IsochCallbackDispatcherToRunLoopIOFireWireLibDeviceRefCFRunLoopRef)
if ($nestedcommentwarn) {
warn("$filename:$linenum: warning: Nested comment found [2]. Ignoring.\n");
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
($part eq $eoc) && do {
print STDERR "END OF MULTILINE COMMENT: CASE 27\n" if ($liteDebug);
print STDERR "EOC\n" if ($localDebug);
if ($parserState->{inComment} && !($parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{inComment} = 0;
$curline = spacefix($curline, $part, $lastchar);
$ppSkipOneToken = 1;
if (!$parserState->{seenBraces}) {
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif (!$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && !$inRegexp) {
my $linenum = $inputCounter + $fileoffset;
warn("$filename:$linenum: warning: Unmatched close comment tag found. Ignoring.\n");
} elsif ($parserState->{inInlineComment}) {
my $linenum = $inputCounter + $fileoffset;
# We'll leave this one on for now.
if ((1 || $nestedcommentwarn) && (!$HeaderDoc::test_mode)) {
warn("$filename:$linenum: warning: Nested comment found [3]. Ignoring.\n");
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Parenthesis and brace handlers.
($part eq "(") && do {
print STDERR "OPEN PAREN: CASE 28\n" if ($liteDebug);
my @tempppl = undef;
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
if (!(scalar(@braceStack)-$parserState->{initbsCount})) {
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
print STDERR "parsedParamList wiped\n" if ($parmDebug);
@tempppl = @{$parserState->{parsedParamList}};
@{$parserState->{parsedParamList}} = ();
$parsedParam = "";
}
$parserState->{onlyComments} = 0;
print STDERR "[i]onlyComments -> 0\n" if ($macroDebug);
if ($parserState->{simpleTypedef} && !(scalar(@braceStack)- $parserState->{initbsCount})) {
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "Setting typedef sodname to ".$parserState->{lastsymbol}."\n" if ($localDebug || $sodDebug);
$parserState->{sodname} = $parserState->{lastsymbol};
$parserState->{sodclass} = "function";
# DAG: changed to respect freezereturn
# and hollow, but in the unlikely event
# that we should start seeing any weird
# "missing return type info" bugs,
# this next line might need to be
# put back in rather than the lines
# that follow it.
# $parserState->{returntype} = "$declaration$curline";
if (!$parserState->{freezereturn} && $parserState->{hollow}) {
$parserState->{returntype} = "$declaration$curline";
} elsif (!$parserState->{freezereturn} && !$parserState->{hollow}) {
$parserState->{returntype} = "$curline";
$declaration = "";
}
}
$parserState->{posstypesPending} = 0;
if ($parserState->{callbackNamePending} == 2) {
$parserState->{callbackNamePending} = 3;
print STDERR "callbackNamePending -> 3\n" if ($localDebug || $cbnDebug);
}
print STDERR "lparen\n" if ($localDebug);
if ($parserState->{cbsodname} && (scalar(@braceStack)-$parserState->{initbsCount}) == 0) {
if (!$parserState->{functionReturnsCallback}) {
# At the top level, if we see a second open parenthesis after setting a callback
# name, the first token in the first set of open parentheses is the name of
# the callback, so clear cbsodname.
#
# Until this point, the value in cbsodname was a copy of the already-cleared
# sodname field, and would replace the callbackName field at the end of
# processing.
$parserState->{cbsodname} = "";
} else {
# If we are in a function that returns a callback, everything from here on
# is a list of parameters for the callback, not the function, so the
# previous parameter list should be discarded (though it is useful to
# add these parameters as valid things to comment about)
@{$parserState->{parsedParamList}} = @tempppl;
$parserState->{functionReturnsCallback}--;
print STDERR "parsedParamList restored\n" if ($parmDebug);
}
}
if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) {
if ($parserState->{callbackName}) {
$parserState->{cbsodname} = $parserState->{callbackName};
$parserState->{sodclass} = "function";
# $parserState->{callbackName} = "";
$parserState->{functionReturnsCallback}++;
print "Function returning callback. NAME: $parserState->{cbsodname}\n" if ($parmDebug || $localDebug || $parseDebug);
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
print STDERR "parsedParamList wiped\n" if ($parmDebug);
@tempppl = @{$parserState->{parsedParamList}};
@{$parserState->{parsedParamList}} = ();
$parsedParam = "";
}
}
if ($parserState->{inOperator} == 1) {
$parserState->{inOperator} = 2;
}
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [15]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
print STDERR "LASTCHARCHECK: \"$lastchar\" \"$lastnspart\" \"$curline\".\n" if ($localDebug);
if ($lastnspart eq ")") { # || $curline =~ /\)\s*$/so
print STDERR "HERE: DEC IS $declaration\nENDDEC\nCURLINE IS $curline\nENDCURLINE\n" if ($localDebug);
# print STDERR "CALLBACKMAYBE: $parserState->{callbackNamePending} $parserState->{sodclass} ".scalar(@braceStack)."\n";
print STDERR "SBS: ".scalar(@braceStack)."\n" if ($localDebug);
### if (!$parserState->{callbackNamePending} && ($parserState->{sodclass} eq "function") && ((scalar(@braceStack)-$parserState->{initbsCount}) == 1)) { # && $argparse
### # Guess it must be a callback anyway.
### my $temp = pop(@tempppl);
### $parserState->{callbackName} = $temp;
### $parserState->{name} = "";
### $parserState->{sodclass} = "";
### $parserState->{sodname} = "";
### print STDERR "CALLBACKHERE ($temp)!\n" if ($cbnDebug || $parseDebug);
### }
if ($declaration =~ /.*\n(.*?)\n$/so) {
my $lastline = $1;
print STDERR "LL: $lastline\nLLDEC: $declaration" if ($localDebug);
$declaration =~ s/(.*)\n(.*?)\n$/$1\n/so;
$curline = "$lastline $curline";
$curline =~ s/^\s*//so;
$prespace -= 4;
$prespaceadjust += 4;
$forcenobreak = 1;
print STDERR "NEWDEC: $declaration\nNEWCURLINE: $curline\n" if ($localDebug);
} elsif (length($declaration) && $callback_typedef_and_name_on_one_line) {
print STDERR "SCARYCASE\n" if ($localDebug);
$declaration =~ s/\n$//so;
$curline = "$declaration $curline";
$declaration = "";
$prespace -= 4;
$prespaceadjust += 4;
$forcenobreak = 1;
}
} else { print STDERR "OPARENLC: \"$lastchar\"\nCURLINE IS: \"$curline\"\n" if ($localDebug);}
$parserState->{lastsymbol} = "";
$lastchar = $part;
if ($parserState->{startOfDec} == 2) {
$parserState->{sodclass} = "function";
$parserState->{freezereturn} = 1;
$parserState->{returntype} =~ s/^\s*//so;
$parserState->{returntype} =~ s/\s*$//so;
}
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
print STDERR "OUTGOING CURLINE: \"$curline\"\n" if ($localDebug);
last SWITCH;
};
($part eq ")") && do {
print STDERR "CLOSE PAREN: CASE 29\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate && (peek(\@regexpStack) ne "("))) {
if ((scalar(@braceStack)-$parserState->{initbsCount} - $parserState->{functionReturnsCallback}) == 1) {
# stop parameter parsing
$parsedParamParse = 0;
print STDERR "parsedParamParse -> 0\n" if ($parmDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if ($parsedParam ne "void") {
# ignore foo(void)
push(@{$parserState->{parsedParamList}}, $parsedParam);
print STDERR "pushed $parsedParam into parsedParamList [1]\n" if ($parmDebug);
}
$parsedParam = "";
}
$parserState->{onlyComments} = 0;
print STDERR "[j]onlyComments -> 0\n" if ($macroDebug);
print STDERR "rparen\n" if ($localDebug);
my $test = pop(@braceStack); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6a]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if (!($test eq "(")) { # ) brace hack for vi
warn("$filename:$inputCounter: warning: Parentheses do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
# cluck("backtrace follows\n");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace -= 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust -= 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
(casecmp($part, $lbrace, $case_sensitive)) && do {
print STDERR "LEFT BRACE: CASE 30\n" if ($liteDebug);
if ($parserState->{onlyComments} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inChar} && !($inRegexp && $regexpNoInterpolate) && scalar(@parserStack)) {
# Somebody put in a brace in the middle of
# a class or else we're seeing ObjC private
# class bits. Either way, throw away the
# curly brace.
print STDERR "NOINSERT\n" if ($parserStackDebug);
$pushParserStateAtBrace = 1;
# $setNoInsert = 1;
$parserState->{noInsert} = 1;
}
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
$parserState->{bracePending} = 0;
print STDERR "bracePending -> 0 [brace]\n" if ($localDebug);
$parserState->{onlyComments} = 0;
print STDERR "[k]onlyComments -> 0\n" if ($macroDebug);
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
# print STDERR "statecheck: ".$parserState->{inClass}."X".$parserState->{sodclass}."X".$parserState->{inOperator}."X".$parserState->{occmethod}."\n"; # @@@ CHECKME - Do this for Obj-C methods too?
if (!$parserState->{inClass} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator} || $parserState->{occmethod})) {
# This is the opening brace of a function. Start ignoring everything
# until the matching brace is encountered.
print "seenBraces -> 1\n" if ($parseDebug);
$parserState->{seenBraces} = 1;
if (!$parserState->{stackFrozen}) {
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
@{$parserState->{pplStack}} = ();
}
$parserState->{posstypesPending} = 0;
$parserState->{namePending} = 0;
$parserState->{callbackNamePending} = -1;
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "callbackNamePending -> -1\n" if ($localDebug || $cbnDebug);
print STDERR "lbrace\n" if ($localDebug);
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [16]\n"; }
print STDERR "TN -> 1\n" if ($localDebug);
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
if ($parserState->{INMODULE} == 2) {
# Drop token on the floor.
$treepart = " ";
}
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
(casecmp($part, $rbrace, $case_sensitive)) && do {
print STDERR "RIGHT BRACE: CASE 31\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate && (peek(\@regexpStack) ne "$lbrace"))) {
my $oldOC = $parserState->{onlyComments};
print STDERR "rbrace???\n" if ($localDebug);
# $parserState->{onlyComments} = 0; # If this is all we've seen, there's either a bug or we're
# unrolling a class or similar anyway.
print STDERR "[l]onlyComments -> 0\n" if ($macroDebug);
my $bsCount = scalar(@braceStack);
if (scalar(@parserStack) && !($bsCount - $parserState->{initbsCount})) {
print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug);
if ($parserState->{noInsert} || $oldOC) {
print STDERR "parserState insertion skipped[RBRACE]\n" if ($parserStackDebug || $parserStateInsertDebug);
} elsif ($parserState->{hollow}) {
print STDERR "inserted parser state into tree [RBRACE]\n" if ($parserStateInsertDebug);
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[1].\n";
}
print STDERR "parserState popped from parserStack[rbrace]\n" if ($parserStackDebug);
# print STDERR "PREINMODULE: ".$parserState->{INMODULE}."\n";
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
# print STDERR "INMODULE: ".$parserState->{INMODULE}."\n";
if ($parserState->{INMODULE} == 2) {
# Drop token on the floor.
print STDERR "CURRENT: ".$treeCur->{TOKEN}."\n" if ($localDebug);
$part = "";
print STDERR "INMODULE -> 3\n" if ($localDebug || $moduleDebug);
$parserState->{INMODULE} = 3;
print STDERR "continue -> 0 [1a]\n" if ($localDebug || $liteDebug);
$parserState->{noInsert} = 0;
$continue = 0;
print STDERR "AT END: REALPS IS ".$parserState->{REALPS}."\n" if ($parserStackDebug || $localDebug);
print STDERR "STACK COUNT: ".scalar(@parserStack)."\n" if ($parserStackDebug || $localDebug);
}
if ($lang eq "php" || ($lang eq "C" && $sublang eq "IDL")) {
# print STDERR "PHP OUT OF BRACES?: ".scalar(@braceStack)."\n";
if (scalar(@braceStack) == 1) {
# PHP and IDL classes end at
# the brace.
print STDERR "continue -> 0 [1a]\n" if ($localDebug || $liteDebug);
$continue = 0;
}
}
if ($parserState->{noInsert} && scalar(@parserStack)) {
# This is to handle the end of
# the private vars in an
# Objective C class.
print STDERR "parserState: Hit me.\n" if ($localDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
# It's about to go down by 1.
$parserState->{initbsCount} = scalar(@braceStack) - 1;
}
# $parserState->{onlyComments} = 1;
} else {
print STDERR "NO CHANGE IN PARSER STATE STACK (nPARSERSTACK = ".scalar(@parserStack).", $bsCount != $parserState->{initbsCount})\n" if ($parseDebug || $parserStackDebug);
}
if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) {
# stop parameter parsing
$parsedParamParse = 0;
print STDERR "parsedParamParse -> 0\n" if ($parmDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) {
# ignore foo(void)
push(@{$parserState->{parsedParamList}}, $parsedParam);
print STDERR "pushed $parsedParam into parsedParamList [1b]\n" if ($parmDebug);
}
$parsedParam = "";
} else {
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
}
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
print STDERR "rbrace\n" if ($localDebug);
my $test = pop(@braceStack); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [7]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if (!($test eq "$lbrace") && (!length($structname) || (!($test eq $structname) && $structisbrace))) {
warn("$filename:$inputCounter: warning: Braces do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace -= 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust -= 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
# Typedef, struct, enum, and union handlers.
# Merge the '@' symbol onto @protocol, @property, @public, and similar.
(length($part) && length($nextpart) && ((length($propname) && $propname =~ /\@/) || length($objcdynamicname) || length($objcsynthesizename) || length($classregexp) || (length($accessregexp) && $accessregexp =~ /\@/)) && $part =~ /^\@$/ && !$parserState->{inComment} && !$parserState->{inChar} && !$parserState->{inString} && !$parserState->{inInlineComment}) && do {
print STDERR "PROPERTY PREPEND AT (\@): CASE 32\n" if ($liteDebug);
my $temp = "\@".$nextpart;
# print STDERR "TEMP IS $temp PROPNAME is $propname\n";
if ($temp =~ /$accessregexp/) {
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
$parserState->{classIsObjC} = 1;
} elsif ($temp =~ /$classregexp/) {
$nextpart = "\@".$nextpart;
$parserState->{classIsObjC} = 1;
} elsif ($temp =~ /$classclosebraceregexp/) {
$nextpart = "\@".$nextpart;
} elsif ($temp eq $propname) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif (length($requiredregexp) && $temp =~ /$requiredregexp/) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif ($temp eq $objcdynamicname) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif ($temp eq $objcsynthesizename) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
}
next SWITCH;
};
($modules_are_special && !$parserState->{inTemplate} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && length($moduleregexp) && $part =~ /$moduleregexp/) && do {
print STDERR "INMODULE -> 1\n" if ($localDebug || $moduleDebug);
$parserState->{INMODULE} = 1;
print STDERR "MODULE START TOKEN: CASE 32-M-1\n" if ($localDebug || $liteDebug);
};
(length($classclosebraceregexp) && ($part =~ /$classclosebraceregexp/) && !$parserState->{inComment} && !$parserState->{inChar} && !$parserState->{inString} && !$parserState->{inInlineComment}) && do {
print STDERR "CLASS CLOSE BRACE: CASE 33\n" if ($liteDebug);
if ($part ne peekmatch(\@braceStack, $filename, $inputCounter)) {
warn("$filename:inputCounter: warning: Class braces do not match.\nWe may have a problem.\n");
}
$parserState->{seenBraces} = 1;
pop(@braceStack);
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
$part =~ s/^\@//s;
if ( 1 || $nextpart ne ";") {
# Objective C protocol/interface declarations end at the close curly brace.
# No ';' necessary (though we'll eat it if it's there.
# No, we won't. Deal with it.
if (scalar(@parserStack) == 1) {
# Throw away current parser state, since
# it will always be empty anyway.
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
$continue = 0;
print STDERR "continue -> 0 [occend]\n" if ($localDebug);
} else {
if (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[\@end]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
print STDERR "inserted parser state into tree [\@end]\n" if ($parserStateInsertDebug);
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[2].\n";
}
print STDERR "parserState: Created parser state[1].\n" if ($parserStackDebug);
print STDERR "CURLINE CLEAR[PRS2]\n" if ($localDebug);
$curline = "";
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
}
print STDERR "parserState popped from parserStack[\@end]\n" if ($parserStackDebug);
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
}
}
# fall through to next case. WHY???
};
(!$parserState->{inTemplate} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && length($classregexp) && $part =~ /$classregexp/) && do {
print STDERR "START OF CLASS: CASE 34\n" if ($liteDebug);
### if ($parserState->{classIsObjC}) { $sublang = "occ"; }
### else { $sublang = "cpp"; }
### print STDERR "LANG $lang SUBLANG $sublang\n" if ($localDebug || $parseDebug || $classDebug);
### # Update the class regular expressions because our language has changed.
### ($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
### $soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
### $enumname,
### $typedefname, $varname, $constname, $structisbrace, $macronameref,
### $classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
### $requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
### print STDERR "PROPNAME NOW $propname\n" if ($localDebug || $parseDebug || $classDebug);
my $localclasstype = $1;
if ($part =~ /^\@/) { $part =~ s/^\@//s; }
if (!(scalar(@braceStack)-$parserState->{initbsCount})) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
print STDERR "ITISACLASS\n" if ($localDebug);
if (!length($parserState->{sodclass})) {
print STDERR "GOOD.\n" if ($localDebug);
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [7]\n" if ($classDebug);
$pushParserStateAtBrace = 1;
if ($localclasstype =~ /\@interface/) {
$parserState->{inClass} = 2;
print STDERR "inClass -> 2 [8]\n" if ($classDebug);
$pushParserStateAtBrace = 0;
} elsif ($localclasstype =~ /\@protocol/) {
$pushParserStateAtBrace = 0;
$pushParserStateAfterWordToken = 0;
$parserState->{inClass} = 0;
print STDERR "inClass -> 0 [9]\n" if ($classDebug);
$parserState->{inProtocol} = 1;
} elsif ($localclasstype =~ /\@implementation/) {
$pushParserStateAtBrace = 0;
$pushParserStateAfterWordToken = 2;
}
$parserState->{sodclass} = "class";
$parserState->{classtype} = $localclasstype;
$parserState->{preclasssodtype} = $parserState->{sodtype} . $part;
$parserState->{sodtype} = "";
$parserState->{startOfDec} = 1;
$parserState->{onlyComments} = 0;
print STDERR "[m]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
# Get the parse tokens from Utilities.pm.
if (length($classbraceregexp) && ($localclasstype =~ /$classbraceregexp/)) {
print STDERR "CLASS ($localclasstype) IS A BRACE.\n" if ($localDebug);
push(@braceStack, $localclasstype); pbs(@braceStack);
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [17]\n"; }
# } else {
# print STDERR "CBRE: \"$classbraceregexp\"\n";
}
($lang, $sublang) = getLangAndSublangFromClassType($localclasstype);
$HeaderDoc::lang = $lang;
$HeaderDoc::sublang = $sublang;
($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
$soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
$enumname,
$typedefname, $varname, $constname, $structisbrace, $macronameref,
$classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
$requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
my $macrore = macroRegexpFromList($macronameref);
# print STDERR "PROPNAME2: $propname\n";
print STDERR "ARP: $accessregexp\n" if ($localDebug);
last SWITCH;
}
}
}
};
($part eq $objcdynamicname) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $objcsynthesizename) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $propname) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $structname || $part eq $enumname || $part eq $unionname) && do {
print STDERR "STRUCT/ENUM/UNION: CASE 36\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($structisbrace) {
if ($parserState->{sodclass} eq "function") {
$parserState->{seenBraces} = 1;
if (!$parserState->{stackFrozen}) {
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
@{$parserState->{pplStack}} = ();
}
$parserState->{posstypesPending} = 0;
$parserState->{callbackNamePending} = -1;
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "callbackNamePending -> -1\n" if ($localDebug || $cbnDebug);
print STDERR "lbrace\n" if ($localDebug);
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [18]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
} else {
if (!$parserState->{simpleTypedef}) {
print STDERR "simpleTypedef -> 2\n" if ($localDebug);
$parserState->{simpleTypedef} = 2;
}
# if (!$parserState->{seenBraces}) { # TREEDONE
# $treePopTwo++;
# $treeNest = 1;
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
# }
}
$parserState->{onlyComments} = 0;
print STDERR "[n]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
# $parserState->{simpleTypedef} = 0;
if ($parserState->{basetype} eq "") { $parserState->{basetype} = $part; }
# fall through to default case when we're done.
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString} || $parserState->{inChar})) {
$parserState->{namePending} = 2;
print STDERR "namePending -> 2 [2]\n" if ($parseDebug);
if ($parserState->{posstypesPending}) { $parserState->{posstypes} .=" $part"; }
}
if ($parserState->{sodclass} eq "") {
$parserState->{startOfDec} = 0; $parserState->{sodname} = "";
print STDERR "sodname cleared (seu)\n" if ($sodDebug);
}
$lastchar = $part;
}; # end if
}; # end do
($part =~ /^$typedefname$/) && do {
print STDERR "TYPEDEF: CASE 37\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (!(scalar(@braceStack)-$parserState->{initbsCount})) { $parserState->{callbackIsTypedef} = 1; $parserState->{inTypedef} = 1; }
$parserState->{onlyComments} = 0;
print STDERR "[o]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
$parserState->{simpleTypedef} = 1; print STDERR "simpleTypedef -> 1\n" if ($localDebug);
# previous case falls through, so be explicit.
if ($part =~ /^$typedefname$/) {
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString} || $parserState->{inChar})) {
if ($pascal) {
$parserState->{namePending} = 2;
$inPType = 1;
print STDERR "namePending -> 2 [3]\n" if ($parseDebug);
}
if ($parserState->{posstypesPending}) { $parserState->{posstypes} .=" $part"; }
if (!($parserState->{callbackNamePending})) {
print STDERR "callbackNamePending -> 1\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 1;
}
}
}
if ($parserState->{sodclass} eq "") {
$parserState->{startOfDec} = 0; $parserState->{sodname} = "";
print STDERR "sodname cleared ($typedefname)\n" if ($sodDebug);
}
$lastchar = $part;
}; # end if
}; # end do
# C++ operator keyword handler
($part eq "$operator") && do {
print STDERR "OPERATOR KEYWORD: CASE 38\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{inOperator} = 1;
$parserState->{sodname} = "";
}
$parserState->{lastsymbol} = $part;
$lastchar = $part;
last SWITCH;
# next;
};
# Punctuation handlers
($part =~ /;/o) && do {
print STDERR "SEMICOLON: CASE 39\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parsedParamParse) {
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) { push(@{$parserState->{parsedParamList}}, $parsedParam); }
print STDERR "pushed $parsedParam into parsedParamList [2semi]\n" if ($parmDebug);
$parsedParam = "";
}
# skip this token
$parsedParamParse = 2;
$parserState->{freezereturn} = 1;
# $parserState->{onlyComments} = 0; # If this is all we've seen, there's either a bug or we're
# unrolling a class or similar anyway.
$parserState->{temponlyComments} = $parserState->{onlyComments};
print STDERR "[p]onlyComments -> 0\n" if ($macroDebug);
print STDERR "valuepending -> 0\n" if ($valueDebug);
$parserState->{valuepending} = 0;
$continuation = 1;
if ($parserState->{occmethod}) {
$prespaceadjust = -$prespace;
}
# previous case falls through, so be explicit.
if ($part =~ /;/o && !$parserState->{inMacroLine} && !$parserState->{inMacro}) {
my $bsCount = scalar(@braceStack)-$parserState->{initbsCount};
if (!$bsCount && !$parserState->{kr_c_function}) {
if ($parserState->{startOfDec} == 2) {
$parserState->{sodclass} = "constant";
$parserState->{startOfDec} = 1;
} elsif (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{startOfDec} = 1;
}
# $parserState->{lastsymbol} .= $part;
}
if (!$bsCount) {
$treeCur = $treeCur->addSibling(";"); $treepart = " "; # $treeSkip = 1;
if (0) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [8]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
# $parserState->{lastTreeNode} = $treeCur;
# print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n";
while ($parserState->{treePopTwo}--) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [9]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
$parserState->{treePopTwo} = 0;
}
}
$lastchar = $part;
}; # end if
}; # end do
($part eq "=" && ($parserState->{lastsymbol} ne "operator") && (!(($parserState->{inOperator} == 1) && $parserState->{lastsymbol} =~ /\W/ && $parserState->{lastsymbol} =~ /\S/)) && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "EQUALS: CASE 40\n" if ($liteDebug);
$parserState->{onlyComments} = 0;
print STDERR "[q]onlyComments -> 0\n" if ($macroDebug);
if ($part =~ /=/o && !(scalar(@braceStack)-$parserState->{initbsCount}) &&
$nextpart !~ /=/o && $lastchar !~ /=/o &&
$parserState->{sodclass} ne "function" && !$inPType) {
print STDERR "valuepending -> 1\n" if ($valueDebug);
$parserState->{valuepending} = 1;
$parserState->{preEqualsSymbol} = $parserState->{lastsymbol};
$parserState->{sodclass} = "constant";
$parserState->{startOfDec} = 0;
}; # end if
}; # end do
($part =~ /,/o) && do {
print STDERR "COMMA: CASE 41\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{onlyComments} = 0;
print STDERR "[r]onlyComments -> 0\n" if ($macroDebug);
}
if ($part =~ /,/o && $parsedParamParse && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && ((scalar(@braceStack)-$parserState->{initbsCount}-$parserState->{functionReturnsCallback}) == 1) && (peek(\@braceStack) eq '(' || peek(\@braceStack) eq '{')) {
print STDERR "$part is a comma\n" if ($localDebug || $parseDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) { push(@{$parserState->{parsedParamList}}, $parsedParam); }
print STDERR "pushed $parsedParam into parsedParamList [2]\n" if ($parmDebug);
$parsedParam = "";
# skip this token
$parsedParamParse = 2;
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
}; # end if
}; # end do
($part =~ /[*^]/) && do {
if ($lastnspart eq "(" && # ")"
!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) &&
!$parserState->{callbackNamePending} &&
((scalar(@braceStack)-$parserState->{initbsCount}) == 1)) {
# print "CBNP\n";
$parserState->{callbackNamePending} = 3;
}
# Fall through to the default case.
}; # end star/asterisk/caret case
{ # SWITCH default case
print STDERR "DEFAULT CASE: CASE 42\n" if ($liteDebug);
# Handler for all other text (data types, string contents,
# comment contents, character contents, etc.)
print STDERR "DEFAULT CASE\n" if ($localDebug || $parseDebug);
# print STDERR "TEST CURLINE IS \"$curline\".\n";
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (!ignore($part, $ignoreref, $perheaderignoreref)) {
if ($part =~ /\S/o) {
$parserState->{onlyComments} = 0;
print STDERR "[s]onlyComments -> 0\n" if ($macroDebug);
}
if (!$continuation && !$occspace) {
$curline = spacefix($curline, $part, $lastchar);
} else {
$continuation = 0;
$occspace = 0;
}
# print STDERR "BAD CURLINE IS \"$curline\".\n";
if (length($part) && !($parserState->{inComment} || $parserState->{inInlineComment})) {
if ($localDebug && $lastchar eq ")") {print STDERR "LC: $lastchar\nPART: $part\n";}
# print STDERR "XXX LC: $lastchar SC: $parserState->{sodclass} LG: $lang\n";
if ($lastchar eq ")" && $parserState->{sodclass} eq "function" && ($lang eq "C" || $lang eq "Csource") && !(scalar(@braceStack)-$parserState->{initbsCount})) {
if ($part !~ /^\s*;/o) {
# warn "K&R C FUNCTION FOUND.\n";
# warn "NAME: $parserState->{sodname}\n";
if (!isKeyword($part, $keywordhashref, $case_sensitive)) {
my $tempavail = ignore($part, $ignoreref, $perheaderignoreref);
if (!$tempavail) {
print STDERR "K&R C FUNCTION FOUND [2].\n" if ($localDebug);
print STDERR "TOKEN: \"$part\"\n" if ($localDebug);
print STDERR "TA: \"$tempavail\"\n" if ($localDebug);
$parserState->{kr_c_function} = 1;
$parserState->{kr_c_name} = $parserState->{sodname};
$parsedParamParse = 1;
print STDERR "parsedParamParse -> 1\n" if ($parmDebug);
}
}
}
}
$lastchar = $part;
if ($part =~ /\w/o || $part eq "::") {
if ($parserState->{callbackNamePending} == 1) {
if (!($part eq $structname || $part eq $enumname || $part eq $unionname || $part eq $typedefname)) {
# we've seen the initial type. The name of
# the callback is after the next open
# parenthesis.
print STDERR "callbackNamePending -> 2\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 2;
}
} elsif ($parserState->{callbackNamePending} == 3) {
print STDERR "callbackNamePending -> 4\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 4;
$parserState->{callbackName} = $part;
$parserState->{name} = "";
$parserState->{sodclass} = "";
$parserState->{cbsodname} = $parserState->{sodname};
$parserState->{sodname} = "";
} elsif ($parserState->{callbackNamePending} == 4) {
if ($part eq "::") {
print STDERR "callbackNamePending -> 5\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 5;
$parserState->{callbackName} .= $part;
} elsif ($part !~ /\s/o) {
print STDERR "callbackNamePending -> 0\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 0;
}
} elsif ($parserState->{callbackNamePending} == 5) {
if ($part !~ /\s/o) {
print STDERR "callbackNamePending -> 4\n" if ($localDebug || $cbnDebug);
if ($part !~ /\*/ && $part !~ /\^/) {
$parserState->{callbackNamePending} = 4;
}
$parserState->{callbackName} .= $part;
}
}
if ($parserState->{namePending} == 2) {
$parserState->{namePending} = 1;
print STDERR "namePending -> 1 [4]\n" if ($parseDebug);
if (!(scalar(@braceStack)-$parserState->{initbsCount}) && ($parserState->{simpleTypedef} == 2)) {
print STDERR "bracePending -> 1\n" if ($localDebug);
$parserState->{bracePending} = 1;
}
} elsif ($parserState->{namePending}) {
if ($parserState->{name} eq "") { $parserState->{name} = $part; }
$parserState->{namePending} = 0;
print STDERR "namePending -> 0 [5]\n" if ($parseDebug);
} elsif ($parserState->{bracePending} == 1) {
if ($part eq "::") {
# struct foo::bar ....
# "foo::bar" is the name of
# the struct and should not
# trigger this (though we might
# trigger it on the following
# word.
print STDERR "bracePending -> 2 [classmember]\n" if ($localDebug);
$parserState->{bracePending} = 2;
} else {
# Word token when brace pending. It's
# a variable.
print STDERR "IT'S A VARIABLE! NAME WAS \"$part\".\n" if ($localDebug);
print STDERR "Word token before brace. Setting sodname to ".$parserState->{lastsymbol}."\n" if ($localDebug || $sodDebug);
$parserState->{sodname} = $part;
# $parserState->{sodtype} = $parserState->{returntype}; # . " " . $parserState->{name};
$parserState->{sodtype} = "$declaration$curline";
$parserState->{sodclass} = "constant";
$parserState->{frozensodname} = $part;
print STDERR "bracePending -> 0 [word]\n" if ($localDebug);
$parserState->{bracePending} = 0;
}
} elsif ($parserState->{bracePending} == 2) {
$parserState->{bracePending}--;
}
} # end if ($part =~ /\w/o)
if ($part !~ /[,;\[\]]/o && !$parserState->{inBrackets}) {
my $opttilde = "";
if ($parserState->{seenTilde}) { $opttilde = "~"; }
print STDERR "CHECKPOINT: INTEMPLATE IS ".$parserState->{inTemplate}." SOD IS ".$parserState->{startOfDec}."\n" if ($localDebug || $sodDebug);
if ($parserState->{startOfDec} == 1) { # @@@ FIXME DAG. This should not set sodname, but otherwise, we're losing classes!!!
if (!$parserState->{inTemplate}) {
print STDERR "Setting sodname (maybe type) to \"$part\"\n" if ($sodDebug);
$parserState->{sodname} = $opttilde.$part;
if ($part =~ /\w/o) {
$parserState->{startOfDec}++;
}
} else {
print STDERR "Not adjusting startOfDec or sodname because in template.\n" if ($localDebug || $sodDebug);
}
} elsif ($parserState->{startOfDec} == 2) {
if ($part =~ /\w/o && !$parserState->{inTemplate}) {
$parserState->{preTemplateSymbol} = "";
}
if (!$parserState->{inTemplate}) {
if ($parserState->{inOperator} == 1) {
$parserState->{sodname} .= $part;
} else {
if (length($parserState->{sodname})) {
$parserState->{sodtype} .= " $parserState->{sodname}";
}
$parserState->{sodname} = $opttilde.$part;
}
print STDERR "sodname set to $part\n" if ($sodDebug);
} else {
print STDERR "Not adjusting startOfDec or sodname because in template.\n" if ($localDebug || $sodDebug);
}
} else {
$parserState->{startOfDec} = 0;
}
} elsif ($part eq "[") { # if ($part !~ /[;\[\]]/o)
$parserState->{inBrackets} += 1;
print STDERR "inBrackets -> $parserState->{inBrackets}\n" if ($sodDebug);
} elsif ($part eq "]") {
$parserState->{inBrackets} -= 1;
print STDERR "inBrackets -> $parserState->{inBrackets}\n" if ($sodDebug);
} # end if ($part !~ /[;\[\]]/o)
if (!($part eq $eoc)) {
print STDERR "SETTING LS ($part)\n" if ($parseDebug);
if ($parserState->{typestring} eq "") { $parserState->{typestring} = $part; }
if ($parserState->{lastsymbol} =~ /\,\s*$/o) {
$parserState->{lastsymbol} .= $part;
} elsif ($parserState->{inTypedef} && !(scalar(@braceStack)-$parserState->{initbsCount}) && $part =~ /,/) {
$parserState->{lastsymbol} .= $part;
} elsif ($part =~ /^\s*\;\s*$/o) {
$parserState->{lastsymbol} .= $part;
} elsif (length($part)) {
# warn("replacing lastsymbol with \"$part\"\n");
$parserState->{lastsymbol} = $part;
}
} # end if (!($part eq $eoc))
} # end if (length($part) && !($parserState->{inComment} || $parserState->{inInlineComment}))
}
} # end if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}))
} # end SWITCH default case
} # end SWITCH
if ($parserState->{seenBraces}) {
# print "SEENBRACES. TP: $treepart PT: $part\n";
if ($treepart) {
$parserState->{functionContents} .= $treepart;
} else {
$parserState->{functionContents} .= $part;
}
# print "SEENBRACES. FC: ".$parserState->{functionContents}."\n";
}
if ($part !~ /\\/o) {
if (!($parserState->{inMacro} || $parserState->{inMacroLine}) || $part !~ /\s/) {
$parserState->resetBackslash();
}
}
if (length($part)) { $lasttoken = $part; }
if (length($part) && $inRegexpTrailer) { --$inRegexpTrailer; }
if ($postPossNL) { --$postPossNL; }
if (($parserState->{simpleTypedef} == 1) && ($part ne $typedefname) &&
!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} ||
$inRegexp)) {
# print STDERR "NP: $parserState->{namePending} PTP: $parserState->{posstypesPending} PART: $part\n";
$parserState->{simpleTDcontents} .= $part;
}
my $ignoretoken = ignore($part, $ignoreref, $perheaderignoreref);
my $hide = ( $hideTokenAndMaybeContents ||
( $ignoretoken &&
!( $parserState->{inString} || $parserState->{inComment} ||
$parserState->{inInlineComment} || $parserState->{inChar}
)
)
);
print STDERR "TPONL: $treePopOnNewLine TPTWO: ".$parserState->{treePopTwo}."\n" if ($tsDebug);
print STDERR "TN: $treeNest TS: $treeSkip nTS: ".scalar(@treeStack)."\n" if ($tsDebug || $parserStateInsertDebug);
print STDERR "sethollow: $sethollow\n" if ($parserStateInsertDebug);
if (!$treeSkip) {
if (!$parserState->{seenBraces}) { # TREEDONE
if ($treeNest != 2) {
# If we really want to skip and nest, set treeNest to 2.
if (length($treepart)) {
if ((($parserState->{inComment} == 1) || ($parserState->{inInlineComment} == 1)) && $treepart !~ /[\r\n!]/) {
$treeCur->token($treeCur->token() . $treepart);
# print STDERR "SHORT\n";
} else {
$treeCur = $treeCur->addSibling($treepart, $hide);
}
$treepart = "";
} else {
if ((($parserState->{inComment} == 1) || ($parserState->{inInlineComment} == 1)) && $treepart !~ /[\r\n!]/) {
$treeCur->token($treeCur->token() . $part);
# print STDERR "SHORT\n";
} else {
$treeCur = $treeCur->addSibling($part, $hide);
}
}
bless($treeCur, "HeaderDoc::ParseTree");
}
# print STDERR "TC IS $treeCur\n";
# $treeCur = %{$treeCur};
if ($treeNest) {
if ($sethollow) {
print STDERR "WILL INSERT STATE $parserState (SETHOLLOW) at ".$treeCur->token()."\n" if ($parserStackDebug);
# $parserState->{hollow} = $treeCur;
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$sethollow = 0;
}
print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug);
push(@treeStack, $treeCur);
$treeCur = $treeCur->addChild("", 0);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
}
if ($parserState->{inComment} > 1) { $parserState->{inComment}--; }
if ($parserState->{inInlineComment} > 1) { $parserState->{inInlineComment}--; }
if (($parserState->{inComment} == 1) && $treepart eq "!") {
$parserState->{inComment} = 3;
}
if (($parserState->{inInlineComment} == 1) && $treepart eq "!") {
$parserState->{inInlineComment} = 3;
}
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [19]\n"; }
if (!$parserState->{freezereturn} && $parserState->{hollow}) {
# print STDERR "WARNING: RETURN TYPE CHANGE[A]".$parserState->{returntype}." CHANGED TO $declaration$curline.\n";
$parserState->{returntype} = "$declaration$curline";
} elsif (!$parserState->{freezereturn} && !$parserState->{hollow}) {
# print STDERR "WARNING: RETURN TYPE CHANGE[B]".$parserState->{returntype}." CHANGED TO $curline.\n";
$parserState->{returntype} = "$curline";
$declaration = "";
# } else {
# print STDERR "WARNING: LEAVING RETURN TYPE ALONE: ".$parserState->{returntype}." NOT CHANGED TO $curline.\n";
}
# From here down is... magic. This is where we figure out how
# to handle parsed parameters, K&R C types, and in general,
# determine whether we've received a complete declaration or not.
#
# About 90% of this is legacy code to handle proper spacing.
# Those bits got effectively replaced by the parseTree class.
# The only way you ever see this output is if you don't have
# any styles defined in your config file.
if (($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) ||
!$ignoretoken) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) &&
!$ppSkipOneToken) {
if ($parsedParamParse == 1) {
$parsedParam .= $part;
} elsif ($parsedParamParse == 2) {
$parsedParamParse = 1;
print STDERR "parsedParamParse -> 1\n" if ($parmDebug);
}
}
if ($ppSkipOneToken) {
$hollowskip = $ppSkipOneToken;
print STDERR "hollowskip -> $ppSkipOneToken (ppSkipOneToken)\n" if ($parserStateInsertDebug);
}
$ppSkipOneToken = 0;
print STDERR "MIDPOINT CL: $curline\nDEC:$declaration\nSCR: \"$scratch\"\n" if ($localDebug);
if (!$parserState->{seenBraces}) {
# Add to current line (but don't put inline function/macro
# declarations in.
if ($parserState->{inString}) {
$curstring .= $part;
} else {
if (length($curstring)) {
if (length($curline) + length($curstring) >
$HeaderDoc::maxDecLen) {
$scratch = nspaces($prespace);
# Was != /\n/ which is clearly
# wrong. Suspect the next line
# if we start losing leading spaces
# where we shouldn't (or don't where
# we should). Also was just /g.
if ($curline !~ /^\s*\n/so) { $curline =~ s/^\s*//sgo; }
# NEWLINE INSERT
print STDERR "CURLINE CLEAR [1]\n" if ($localDebug);
$declaration .= "$scratch$curline\n";
$curline = "";
$prespace += $prespaceadjust;
$prespaceadjust = 0;
$prespaceadjust -= 4;
$prespace += 4;
} else {
# no wrap, so maybe add a space.
if ($lastchar =~ /\=$/o) {
$curline .= " ";
}
}
$curline .= $curstring;
$curstring = "";
}
if ((length($curline) + length($part) > $HeaderDoc::maxDecLen)) {
$scratch = nspaces($prespace);
# Was != /\n/ which is clearly
# wrong. Suspect the next line
# if we start losing leading spaces
# where we shouldn't (or don't where
# we should). Also was /g instead of /sg.
if ($curline !~ /^\s*\n/so) { $curline =~ s/^\s*//sgo; }
# NEWLINE INSERT
$declaration .= "$scratch$curline\n";
print STDERR "CURLINE CLEAR [2]\n" if ($localDebug);
$curline = "";
$prespace += $prespaceadjust;
$prespaceadjust = 0;
$prespaceadjust -= 4;
$prespace += 4;
}
if (length($curline) || $part ne " ") {
# Add it to curline unless it's a space that
# has inadvertently been wrapped to the
# start of a line.
$curline .= $part;
}
}
if (peek(\@braceStack) ne "<") {
if ($part =~ /\n/o || ($part =~ /[\(;,]/o && $nextpart !~ /\n/o &&
!$parserState->{occmethod}) ||
($part =~ /[:;.]/o && $nextpart !~ /\n/o &&
$parserState->{occmethod})) {
if ($curline !~ /\n/o && !($parserState->{inMacro} || ($pascal && (scalar(@braceStack)-$parserState->{initbsCount})) || $parserState->{inInlineComment} || $parserState->{inComment} || $parserState->{inString})) {
# NEWLINE INSERT
$curline .= "\n";
}
# Add the current line to the declaration.
$scratch = nspaces($prespace);
if ($curline !~ /\n/o) { $curline =~ s/^\s*//go; }
if ($declaration !~ /\n\s*$/o) {
$scratch = " ";
if ($localDebug) {
my $zDec = $declaration;
$zDec = s/ /z/sg;
$zDec = s/\t/Z/sg;
print STDERR "ZEROSCRATCH\n";
print STDERR "zDec: \"$zDec\"\n";
}
}
$declaration .= "$scratch$curline";
print STDERR "CURLINE CLEAR [3]\n" if ($localDebug);
$curline = "";
# $curline = nspaces($prespace);
print STDERR "PS: $prespace -> " . $prespace + $prespaceadjust . "\n" if ($localDebug);
$prespace += $prespaceadjust;
$prespaceadjust = 0;
} elsif ($part =~ /[\(;,]/o && $nextpart !~ /\n/o &&
($parserState->{occmethod} == 1)) {
print STDERR "SPC\n" if ($localDebug);
$curline .= " "; $occspace = 1;
} else {
print STDERR "NOSPC: $part:$nextpart:$parserState->{occmethod}\n" if ($localDebug);
}
}
}
if ($parserState->{temponlyComments}) {
# print STDERR "GOT TOC: ".$parserState->{temponlyComments}."\n";
$parserState->{onlyComments} = $parserState->{temponlyComments};
$parserState->{temponlyComments} = undef;
}
print STDERR "CURLINE IS \"$curline\".\n" if ($localDebug);
my $bsCount = scalar(@braceStack);
print STDERR "ENDTEST: $bsCount \"$parserState->{lastsymbol}\"\n" if ($localDebug);
print STDERR "KRC: $parserState->{kr_c_function} SB: $parserState->{seenBraces}\n" if ($localDebug);
if (!($bsCount - $parserState->{initbsCount}) && $parserState->{lastsymbol} =~ /;\s*$/o) {
# print STDERR "DPA\n";
if ((!$parserState->{kr_c_function} || $parserState->{seenBraces}) && !$parserState->{inMacro}) {
# print STDERR "DPB\n";
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [3]\n" if ($localDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[SEMI-1]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} elsif ($parserState->{classtype} && length($parserState->{classtype})) {
warn "Couldn't insert info into parse tree[3class].\n" if ($localDebug);
} else {
warn "Couldn't insert info into parse tree[3].\n";
print STDERR "Printing tree.\n";
$parserState->print();
$treeTop->dbprint();
}
print STDERR "parserState: Created parser state[2].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "NEWRETURNTYPE: $parserState->{returntype}\n" if ($localDebug);
print STDERR "CURLINE CLEAR[PRS2]\n" if ($localDebug);
$curline = "";
}
}
} else {
print STDERR "bsCount: $bsCount - $parserState->{initbsCount}, ls: $parserState->{lastsymbol}\n" if ($localDebug);
pbs(@braceStack);
}
if (!($bsCount - $parserState->{initbsCount}) && $parserState->{seenBraces} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator}) &&
($nextpart ne ";")) {
# Function declarations end at the close curly brace.
# No ';' necessary (though we'll eat it if it's there.
if ($parserState->{treePopTwo}) {
# Fix nesting.
# print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n";
while ($parserState->{treePopTwo}--) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [13]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
$treeCur = $treeCur->addSibling(";", 0);
$parserState->{lastTreeNode} = $treeCur;
$parserState->{treePopTwo} = 0;
}
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [4]\n" if ($localDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[SEMI-2]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[4].\n";
}
print STDERR "parserState: Created parser state[3].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "CURLINE CLEAR[PRS3]\n" if ($localDebug);
$curline = "";
}
}
print STDERR "INMACRO: ".$parserState->{inMacro}."\n" if ($localDebug || $cppDebug || $cppDebug);
# $parserState->{lastsymbol} ne "\\"
print STDERR "IM: ".$parserState->{inMacro}." IQ: ".$parserState->isQuoted($lang, $sublang)."\n" if ($localDebug);
if (($parserState->{inMacro} == 3 && !$parserState->isQuoted($lang, $sublang)) || $parserState->{inMacro} == 4) {
print STDERR "CHECKPART AGAINST NEWLINE\n" if ($localDebug || $cppDebug);
if ($part =~ /[\n\r]/o && !$parserState->{inComment}) {
print STDERR "MLS: $parserState->{lastsymbol}\n" if ($macroDebug);
print STDERR "PARSER STACK CONTAINS ".scalar(@parserStack)." FRAMES\n" if ($cppDebug || $parserStackDebug);
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [5]\n" if ($localDebug || $liteDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
print STDERR "NOT setting continue to 0 for macro: parser stack nonempty\n" if ($liteDebug);
print STDERR "DONE WITH MACRO. HANDLING.\n" if ($localDebug || $parseDebug);
if ($parserState->{inMacro} == 3) {
if (!$HeaderDoc::skipNextPDefine) {
cpp_add($parserState->{hollow});
} else {
cpp_add($parserState->{hollow}, 1);
$HeaderDoc::skipNextPDefine = 0;
}
}
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[5].\n";
}
print STDERR "parserState: Created parser state[4].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "CURLINE CLEAR[PRS4]\n" if ($localDebug);
$curline = "";
}
}
} elsif ($parserState->{inMacro} == 2) {
my $linenum = $inputCounter + $fileoffset;
warn "$filename:$linenum: warning: Declaration starts with # but is not preprocessor macro\n";
warn "PART: $part\n";
} elsif ($parserState->{inMacro} == 3 && $parserState->isQuoted($lang, $sublang)) {
# $parserState->{lastsymbol} eq "\\"
print STDERR "TAIL BACKSLASH ($continue)\n" if ($localDebug || $macroDebug);
}
if ($parserState->{valuepending} == 2) {
# skip the "=" part;
$parserState->{value} .= $part;
} elsif ($parserState->{valuepending}) {
$parserState->{valuepending} = 2;
print STDERR "valuepending -> 2\n" if ($valueDebug);
}
} # end if "we're not ignoring this token"
print STDERR "OOGABOOGA\n" if ($parserStackDebug);
if ($pushParserStateAfterToken == 1) {
print STDERR "parserState pushed onto stack[token]\n" if ($parserStackDebug);
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterToken = 0;
$pushParserStateAtBrace = 0;
} elsif ($pushParserStateAfterWordToken == 1) {
if ($part =~ /\w/) {
print STDERR "parserState pushed onto stack[word]\n" if ($parserStackDebug);
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterWordToken = 0;
}
} elsif ($pushParserStateAfterWordToken) {
print STDERR "PPSAFTERWT CHANGED $pushParserStateAfterWordToken -> " if ($parserStackDebug);
$pushParserStateAfterWordToken--;
print STDERR "$pushParserStateAfterWordToken\n" if ($parserStackDebug);
} elsif ($pushParserStateAtBrace) {
print STDERR "PPSatBrace?\n" if ($parserStackDebug);
if (casecmp($part, $lbrace, $case_sensitive)) {
$parserState->{ISFORWARDDECLARATION} = 0;
print STDERR "parserState pushed onto stack[brace]\n" if ($parserStackDebug);
# if ($pushParserStateAtBrace == 2) {
# print STDERR "NOINSERT parserState: $parserState\n" if ($parserStackDebug);
# $parserState->{hollow} = undef;
# $parserState->{noInsert} = 1;
# }
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
} elsif ($pushParserStateAtBrace) {
if ($part =~ /\;/) {
# It's a class instance declaration. Whoops.
$pushParserStateAtBrace = 0;
$parserState->{inClass} = 0;
print STDERR "inClass -> 0 [10]\n" if ($classDebug);
}
# if ($part =~ /\S/) { $pushParserStateAtBrace = 0; }
}
if (!$parserState->{hollow}) {
my $tok = $part; # $treeCur->token();
print STDERR "parserState: NOT HOLLOW [1]\n" if ($parserStackDebug);
print STDERR "IS: $parserState->{inString}\nICom: $parserState->{inComment}\nISLC: $parserState->{inInlineComment}\nIChar: $parserState->{inChar}\nSkipToken: $parserState->{skiptoken}\nHollowSkip: $hollowskip\n" if ($parserStackDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
print STDERR "parserState: NOT STRING/CHAR/COMMENT\n" if ($parserStackDebug);
if ($tok =~ /\S/) {
print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug);
print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug);
if (!casecmp($tok, $rbrace, $case_sensitive) && $part !~ /\)/) {
# $parserState->{hollow} = $treeCur;
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$HeaderDoc::curParserState = $parserState;
print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-1) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug);
}
}
}
$hollowskip = 0;
print STDERR "hollowskip -> 0 (NOTHOLLOW - 1)\n" if ($parserStateInsertDebug);
$parserState->{skiptoken} = 0;
}
} else {
if (!$parserState->{hollow}) {
my $tok = $part; # $treeCur->token();
print STDERR "parserState: NOT HOLLOW [2]\n" if ($parserStackDebug);
print STDERR "IS: $parserState->{inString}\nICom: $parserState->{inComment}\nISLC: $parserState->{inInlineComment}\nIChar: $parserState->{inChar}\nSkipToken: $parserState->{skiptoken}\nHollowSkip: $hollowskip\n" if ($parserStackDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
print STDERR "parserState: NOT STRING/CHAR/COMMENT\n" if ($parserStackDebug);
if ($tok =~ /\S/) {
print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug);
print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug);
if (!casecmp($tok, $rbrace, $case_sensitive) && $part !~ /\)/) {
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$HeaderDoc::curParserState = $parserState;
print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-2) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug);
}
}
}
$hollowskip = 0;
print STDERR "hollowskip -> 0 (NOTHOLLOW - 2)\n" if ($parserStateInsertDebug);
$parserState->{skiptoken} = 0;
}
}
if ($part =~ /\w+/) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
if ($parserState->{occparmlabelfound} == -2) {
if (!($parserState->{initbsCount} - scalar(@braceStack) )) { # Skip types
$parserState->{occparmlabelfound} = 0; # Next token is the label for the next parameter.
if ($HeaderDoc::useParmNameForUnlabeledParms) {
$parserState->{occmethodname} .= "$part:";
} else {
$parserState->{occmethodname} .= ":";
}
if ($occMethodNameDebug) {
print STDERR "OCC parameter name substituted; OCC method name now ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\", part was \"".$part."\").\n";
}
}
} else {
if (!($parserState->{initbsCount} - scalar(@braceStack) )) { # Skip types
$parserState->{occparmlabelfound}++;
if ($occMethodNameDebug && ($parserState->{occparmlabelfound} > 0)) {
print STDERR "OCC possible label: \"$part\".\n";
}
}
}
}
}
if (length($part) && $part =~ /\S/o) { $lastnspart = $part; }
if ($parserState->{seenTilde} && length($part) && $part !~ /\s/o) { $parserState->{seenTilde}--; }
$part = $nextpart;
} # end foreach (parts of the current line)
} # end while (continue && ...)
print STDERR "RETURNING DECLARATION\n" if ($localDebug);
# Format and insert curline into the declaration. This handles the
# trailing line. (Deprecated.)
if ($curline !~ /\n/) { $curline =~ s/^\s*//go; }
if ($curline =~ /\S/o) {
$scratch = nspaces($prespace);
$declaration .= "$scratch$curline\n";
}
print STDERR "($parserState->{typestring}, $parserState->{basetype})\n" if ($localDebug || $listDebug);
print STDERR "LS: $parserState->{lastsymbol}\n" if ($localDebug);
$parserState->{lastTreeNode} = $treeCur;
$parserState->{inputCounter} = $inputCounter;
print STDERR "PARSERSTATE: $parserState\n" if ($localDebug);
if ($parserState->{inMacro} == 3) {
if (!$HeaderDoc::skipNextPDefine) {
cpp_add($treeTop);
} else {
cpp_add($treeTop, 1);
$HeaderDoc::skipNextPDefine = 0;
}
}
print STDERR "LEFTBPMAIN\n" if ($localDebug || $hangDebug);
if ($argparse && $apwarn) {
print STDERR "end argparse\n";
}
# Return the top parser context even if we got interrupted.
my $tempParserState = pop(@parserStack);
while ($tempParserState) {
$parserState = $tempParserState;
$tempParserState = pop(@parserStack);
}
$HeaderDoc::module = $parserState->{MODULE};
if ($localDebug || $apDebug || $liteDebug || $parseDebug) {
print STDERR "LEAVING BLOCKPARSE\n";
}
if (0) {
print STDERR "Returning the following parse tree:\n";
$treeTop->dbprint();
print STDERR "End of parse tree.\n";
}
# print "FC: ".$parserState->{functionContents}."\n";
return blockParseReturnState($parserState, $treeTop, $argparse, $declaration, $inPrivateParamTypes, $publicDeclaration, $lastACS, $retDebug, $fileoffset, 0, $definename, $inputCounter);
}
extendsClass:
implementsClass:
-=: LIST OF PARSED PARAMETERS :=-
-=: DUMP OF PARSE TREE :=-
+---sub
+---
+---blockParse
+---[ NEWLINE ]
-=: COMPUTED VALUE :=-
SUCCESS: 0
VALUE: 0
-=: CPP CHANGES :=-
NO CPP CHANGES
-=: FOUND MATCH :=-
1
-=: NAMED OBJECTS :=-
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::Header
NAME: Perl function 2
APIUID: //test_ref/doc/header/Perl_function_2.test
ABSTRACT: ""
DISCUSSION: "<p></p>"
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::Header"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 1
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::Function
NAME: blockParse
APIUID: //test_ref/perl/func/blockParse
ABSTRACT: ""
DISCUSSION: "<p>The blockParse function is the core of HeaderDoc's parse engine.
"
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: "default_function_group"
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::Function"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: "0"
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TAGGED PARAMETERS:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: filename
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/filename
ABSTRACT: ""
DISCUSSION: "<p>the filename being parser."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: fileoffset
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/fileoffset
ABSTRACT: ""
DISCUSSION: "<p>the line number where the current block begins. The line number printed is (fileoffset + inputCounter)."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: inputLinesRef
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/inputLinesRef
ABSTRACT: ""
DISCUSSION: "<p>a reference to an array of code lines."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: inputCounter
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/inputCounter
ABSTRACT: ""
DISCUSSION: "<p>the offset within the array. This is added to fileoffset when printing the line number."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: argparse
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/argparse
ABSTRACT: ""
DISCUSSION: "<p>disable warnings when parsing arguments to avoid seeing them twice."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: ignoreref
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/ignoreref
ABSTRACT: ""
DISCUSSION: "<p>a reference to a hash of tokens to ignore on all headers."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: perheaderignoreref
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/perheaderignoreref
ABSTRACT: ""
DISCUSSION: "<p>a reference to a hash of tokens, generated from @ignore headerdoc comments."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: perheaderignorefuncmacrosref
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/perheaderignorefuncmacrosref
ABSTRACT: ""
DISCUSSION: "<p>a reference to a hash of tokens, generated from @ignorefunmacro headerdoc comments."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: keywordhashref
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/keywordhashref
ABSTRACT: ""
DISCUSSION: "<p>a reference to a hash of keywords."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: case_sensitive
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/case_sensitive
ABSTRACT: ""
DISCUSSION: "<p>boolean: controls whether keywords should be processed in a case-sensitive fashion."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
-=: NAMED OBJECT PARSE TREES :=-
OBJECT: blockParse (HeaderDoc::Function)
+---sub
+---
+---blockParse
+---[ NEWLINE ]
END OF OBJECT
-=: HTML OUTPUT OF PARSE TREES :=-
OBJECT: blockParse (HeaderDoc::Function)
<span class="keyword">sub</span> <!-- a logicalPath="//test_ref/perl/instm/blockParse //test_ref/perl/clm/blockParse //test_ref/perl/intfcm/blockParse //test_ref/perl/intfm/blockParse //test_ref/perl/func/blockParse //test_ref/perl/ftmplt/blockParse //test_ref/perl/defn/blockParse //test_ref/perl/macro/blockParse //test_ref/doc/anysymbol/blockParse" machineGenerated="true" --><span class="function">blockParse</span><!-- /a -->
END OF OBJECT
$496969|-=: TOP LEVEL COMMENT PARSE VALUES :=-
inHeader: 0
inClass: 0
inInterface: 0
inCPPHeader: 0
inOCCHeader: 0
inPerlScript: 0
inShellScript: 0
inPHPScript: 0
inJavaSource: 0
inFunctionGroup: 0
inGroup: 0
inFunction: 0
inPDefine: 0
inTypedef: 0
inUnion: 0
inStruct: 0
inConstant: 0
inVar: 0
inEnum: 0
inMethod: 0
inAvailabilityMacro: 0
inUnknown: 1
classType: unknown
inputCounter: 0
blockOffset: 0
fullpath: /test_suite_bogus_path/Perl_function_2.test
-=: BLOCKPARSE PARSER STATE KEYS :=-
$parserState->{FULLPATH} => /test_suite_bogus_path/Perl_function_2.test
$parserState->{NEXTTOKENNOCPP} => 0
$parserState->{availability} =>
$parserState->{backslashcount} => 0
$parserState->{basetype} =>
$parserState->{bracePending} => 0
$parserState->{callbackIsTypedef} => 0
$parserState->{callbackName} =>
$parserState->{callbackNamePending} => -1
$parserState->{categoryClass} =>
$parserState->{classtype} =>
$parserState->{curvarstars} => *********************************************************************************
$parserState->{freezeStack} => ARRAY(OBJID)
$parserState->{freezereturn} => 1
$parserState->{frozensodname} => blockParse
$parserState->{functionContents} => {
my $filename = shift;
my $fileoffset = shift;
my $inputLinesRef = shift;
my $inputCounter = shift;
my $argparse = shift;
my $ignoreref = shift;
my $perheaderignoreref = shift;
my $perheaderignorefuncmacrosref = shift;
my $keywordhashref = shift;
my $case_sensitive = shift;
my $apwarn = 0;
if ($argparse && $apwarn) {
print STDERR "argparse\n";
}
# Initialize stuff
my @inputLines = @{$inputLinesRef};
my $declaration = "";
my $publicDeclaration = "";
# $HeaderDoc::fileDebug = 1;
# Debugging switches
my $retDebug = 0;
my $localDebug = 0 || $HeaderDoc::fileDebug;
my $operatorDebug = 0;
my $listDebug = 0;
my $parseDebug = 0 || $HeaderDoc::fileDebug;
my $sodDebug = 0 || $HeaderDoc::fileDebug;
my $valueDebug = 0;
my $parmDebug = 0;
my $cbnDebug = 0;
my $macroDebug = 0;
my $apDebug = 0;
my $tsDebug = 0;
my $treeDebug = 0;
my $ilcDebug = 0;
my $regexpDebug = 0;
my $parserStackDebug = 0 || $HeaderDoc::fileDebug;
my $hangDebug = 0;
my $offsetDebug = 0;
my $classDebug = 0; # prints changes to inClass, etc.
my $gccAttributeDebug = 0; # also for availability macro argument handling.
my $occMethodNameDebug = 0;
my $moduleDebug = 0; # prints changes to INMODULE
my $liteDebug = 0 || $HeaderDoc::fileDebug; # Just prints the tokens.
my $parserStateInsertDebug = 0;
$cppDebug = $cppDebugDefault || $HeaderDoc::fileDebug;
# State variables (part 1 of 3)
# my $typestring = "";
my $continue = 1; # set low when we're done.
my $parsedParamParse = 0; # set high when current token is part of param.
# my @parsedParamList = (); # currently active parsed parameter list.
# my @pplStack = (); # stack of parsed parameter lists. Used to handle
# fields and parameters in nested callbacks/structs.
# my @freezeStack = (); # copy of pplStack when frozen.
# my $frozensodname = "";
# my $stackFrozen = 0; # set to prevent fake parsed params with inline funcs
my $lang = $HeaderDoc::lang;
my $perl_or_shell = 0;
my $sublang = $HeaderDoc::sublang;
my $callback_typedef_and_name_on_one_line = 1; # deprecated
# my $returntype = "";
# my $freezereturn = 0; # set to prevent fake return types with inline funcs
my $treeNest = 0; # 1: nest future content under this node.
# 2: used if you want to nest, but have already
# inserted the contents of the node.
my $sethollow = 0;
my $setNoInsert = 0;
my $treepart = ""; # There are some cases where you want to drop a token
# for formatting, but keep it in the parse tree.
# In that case, treepart contains the original token,
# while part generally contains a space.
# my $availability = ""; # holds availability string if we find an av macro.
# my $seenTilde = 0; # set to 1 for C++ destructor.
if ($argparse && $tsDebug) { $tsDebug = 0; }
# Configure the parse tree output.
my $treeTop = HeaderDoc::ParseTree->new(); # top of parse tree.
my $treeCur = $treeTop; # current position in parse tree
my $treeSkip = 0; # set to 1 if "part" should be dropped in tree.
# my $treePopTwo = 0; # set to 1 for tokens that nest, but have no
# explicit ending token ([+-:]).
my $treePopOnNewLine = 0; # set to 1 for single-line comments, macros.
my @treeStack = (); # stack of parse trees. Used for popping
# our way up the tree to simplify tree structure.
# Leak a node here so that every real node has a parent.
$treeCur = $treeCur->addChild("");
$treeTop = $treeCur;
my $lastACS = "";
# The argparse switch is a trigger....
if ($argparse && $apDebug) {
$localDebug = 1;
$retDebug = 1;
$listDebug = 1;
$parseDebug = 1;
$sodDebug = 1;
$valueDebug = 1;
$parmDebug = 1;
$cbnDebug = 1;
$macroDebug = 1;
# $apDebug = 1;
$tsDebug = 1;
$treeDebug = 1;
$ilcDebug = 1;
$regexpDebug = 1;
}
my $spaceDebug = 0;
if ($localDebug || $apDebug || $liteDebug || $parseDebug) {
print STDERR "ENTERED BLOCKPARSE\n";
}
my $disable_cpp = 0;
if ($argparse && ($localDebug || $apDebug || $liteDebug)) {
print STDERR "ARGPARSE MODE!\n";
print STDERR "IPC: $inputCounter\nNLINES: ".$#inputLines."\n";
cluck("Call backtrace\n");
}
print STDERR "INBP\n" if ($localDebug);
if ($argparse) {
# Avoid double-processing macro inclusions.
$disable_cpp = 1;
}
if ($lang ne "C" || $sublang eq "PHP") { # || $sublang eq "IDL")
$disable_cpp = 1;
}
print STDERR "INITIAL LANG: $lang INITIAL SUBLANG: $sublang\n" if ($localDebug);
# warn("in BlockParse\n");
# State variables (part 2 of 3)
my $parserState = HeaderDoc::ParserState->new();
# $parserState->{hollow} = $treeTop;
setHollowWithLineNumbers(\$parserState, $treeTop, $fileoffset, $inputCounter);
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = 0; # included for consistency....
my @parserStack = ();
# print STDERR "TEST: ";
# if (defined($parserState->{parsedParamList})) {
# print STDERR "defined\n"
# } else { print STDERR "undefined.\n"; }
# print STDERR "\n";
# my $inComment = 0;
# my $inInlineComment = 0;
# my $inString = 0;
# my $inChar = 0;
# my $inTemplate = 0;
my @braceStack = ();
# my $inOperator = 0;
my $inPrivateParamTypes = 0; # after a colon in a C++ function declaration.
# my $onlyComments = 1; # set to 0 to avoid switching to macro parse.
# mode after we have seen a code token.
# my $inMacro = 0;
# my $inMacroLine = 0; # for handling macros in middle of data types.
# my $seenMacroPart = 0; # used to control dropping of macro body.
# my $macroNoTrunc = 1; # used to avoid truncating body of macros
# that don't begin with parenthesis or brace.
# my $inBrackets = 0; # square brackets ([]).
my $inPType = 0; # in pascal types.
my $inRegexp = 0; # in perl regexp.
my $regexpNoInterpolate = 0; # Don't interpolate (e.g. tr)
my $inRegexpTrailer = 0; # in the cruft at the end of a regexp.
my $hollowskip = 0;
my $ppSkipOneToken = 0; # Comments are always dropped from parsed
# parameter lists. However, inComment goes
# to 0 on the end-of-comment character.
# This prevents the end-of-comment character
# itself from being added....
my $regexppattern = ""; # optional characters at start of regexp
my $singleregexppattern = ""; # members of regexppattern that take only
# one argument instead of two.
my $regexpcharpattern = ""; # legal chars to start a regexp.
my @regexpStack = (); # stack of RE tokens (since some can nest).
# Get the parse tokens from Utilities.pm.
my ($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
$soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
$enumname,
$typedefname, $varname, $constname, $structisbrace, $macronameref,
$classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
$requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
my $macrore_pound = macroRegexpFromList($macronameref, 1);
my $macrore_nopound = macroRegexpFromList($macronameref, 2);
# print STDERR "LANG: $lang SUBLANG: $sublang";
print STDERR "MACRORE_POUND: \"$macrore_pound\"\n" if ($localDebug || $parseDebug);
print STDERR "MACRORE_NOPOUND: \"$macrore_nopound\"\n" if ($localDebug || $parseDebug);
# print STDERR "INITIAL PROPNAME $propname\n";
if ($parseDebug) {
print STDERR "SOT: $sotemplate EOF: $eotemplate OP: $operator SOC: $soc EOC: $eoc ILC: $ilc ILC_B: $ilc_b\n";
print STDERR "SOFUNC: $sofunction SOPROC: $soprocedure SOPREPROC: $sopreproc LBRACE: $lbrace RBRACE: $rbrace\n";
print STDERR "UNION: $unionname STRUCT: $structname TYPEDEF: $typedefname VAR: $varname CONST: $constname\n";
print STDERR "STRUCTISBRACE: $structisbrace MACRONAMEREF: $macronameref CLASSRE: $classregexp\n";
print STDERR "CLASSBRACERE: $classbraceregexp CLASSCLOSEBRACERE: $classclosebraceregexp ACCESSRE: $accessregexp\n";
print STDERR "MODULERE: $moduleregexp\n";
}
# Set up regexp patterns for perl, variable for perl or shell.
if ($lang eq "perl" || $lang eq "shell") {
$perl_or_shell = 1;
if ($lang eq "perl") {
$regexpcharpattern = '\\{|\\#\\(|\\/|\\\'|\\"|\\<|\\[|\\`';
# } vi bug workaround for previous line
$regexppattern = "qq|qr|qx|qw|q|m|s|tr|y";
$singleregexppattern = "qq|qr|qx|qw|q|m";
}
}
my $pascal = 0;
if ($lang eq "pascal") { $pascal = 1; }
# State variables (part 3 of 3)
# my $lastsymbol = ""; # Name of the last token, wiped by braces,
# parens, etc. This is not what you are
# looking for. It is used mostly for
# handling names of typedefs.
# my $name = ""; # Name of a basic data type.
# my $callbackNamePending = 0; # 1 if callback name could be here. This is
# only used for typedef'ed callbacks. All
# other callbacks get handled by the parameter
# parsing code. (If we get a second set of
# parsed parameters for a function, the first
# one becomes the callback name.)
# my $callbackName = ""; # Name of this callback.
# my $callbackIsTypedef = 0; # 1 if the callback is wrapped in a typedef---
# sets priority order of type matching (up
# one level in headerdoc2HTML.pl).
# my $namePending = 0; # 1 if name of func/variable is coming up.
# my $basetype = ""; # The main name for this data type.
# my $posstypes = ""; # List of type names for this data type.
# my $posstypesPending = 1; # If this token could be one of the
# type names of a typedef/struct/union/*
# declaration, this should be 1.
# my $sodtype = ""; # 'start of declaration' type.
# my $sodname = ""; # 'start of declaration' name.
# my $sodclass = ""; # 'start of declaration' "class". These
# bits allow us keep track of functions and
# callbacks, mostly, but not the name of a
# callback.
# my $simpleTypedef = 0; # High if it's a typedef w/o braces.
# my $simpleTDcontents = ""; # Guts of a one-line typedef. Don't ask.
# my $seenBraces = 0; # Goes high after initial brace for inline
# functions and macros -only-. We
# essentially stop parsing at this point.
# my $kr_c_function = 0; # Goes high if we see a K&R C declaration.
# my $kr_c_name = ""; # The name of a K&R function (which would
# otherwise get lost).
my $lastchar = ""; # Ends with the last token, but may be longer.
my $lastnspart = ""; # The last non-whitespace token.
my $lasttoken = ""; # The last token seen (though [\n\r] may be
# replaced by a space in some cases.
# my $startOfDec = 1; # Are we at the start of a declaration?
my $prespace = 0; # Used for indentation (deprecated).
my $prespaceadjust = 0; # Indentation is now handled by the parse
# tree (colorizer) code.
my $scratch = ""; # Scratch space.
my $curline = ""; # The current line. This is pushed onto
# the declaration at a newline and when we
# enter/leave certain constructs. This is
# deprecated in favor of the parse tree.
my $curstring = ""; # The string we're currently processing.
my $continuation = 0; # An obscure spacing workaround. Deprecated.
my $forcenobreak = 0; # An obscure spacing workaround. Deprecated.
# my $occmethod = 0; # 1 if we're in an ObjC method.
my $occspace = 0; # An obscure spacing workaround. Deprecated.
# my $occmethodname = ""; # The name of an objective C method (which
# gets augmented to be this:that:theother).
# my $preTemplateSymbol = ""; # The last symbol prior to the start of a
# C++ template. Used to determine whether
# the type returned should be a function or
# a function template.
# my $preEqualsSymbol = ""; # Used to get the name of a variable that
# is followed by an equals sign.
# my $valuepending = 0; # True if a value is pending, used to
# return the right value.
# my $value = ""; # The current value.
my $parsedParam = ""; # The current parameter being parsed.
my $postPossNL = 0; # Used to force certain newlines to be added
# to the parse tree (to end macros, etc.)
# my $categoryClass = "";
# my $classtype = "";
# my $inClass = 0;
my $pushParserStateAfterToken = 0;
my $pushParserStateAfterWordToken = 0;
my $pushParserStateAtBrace = 0;
my $occPushParserStateOnWordTokenAfterNext = 0;
$HeaderDoc::hidetokens = 0;
# Loop unti the end of file or until we've found a declaration,
# processing one line at a time.
my $nlines = $#inputLines;
my $incrementoffsetatnewline = 0;
print "INCOMING INPUTCOUNTER: $inputCounter\n" if ($HeaderDoc::inputCounterDebug);
while ($continue && ($inputCounter <= $nlines)) {
$HeaderDoc::CurLine = $inputCounter + $fileoffset;
my $line = $inputLines[$inputCounter++];
print STDERR "GOT LINE: $line\n" if (($localDebug && $apDebug) || $HeaderDoc::inputCounterDebug);
print STDERR "INCREMENTED INPUTCOUNTER [1]\n" if ($HeaderDoc::inputCounterDebug);
my @parts = ();
# $line =~ s/^\s*//go; # Don't strip leading spaces, please.
$line =~ s/\s*$//go;
# $scratch = nspaces($prespace);
# $line = "$scratch$line\n";
# $curline .= $scratch;
$line .= "\n";
if ($lang eq "C" && $sublang eq "IDL") {
if ($line =~ /cpp_quote\s*\(\s*\"(.*)\"\s*\)\s*$/) {
print "CHANGED LINE FROM \"$line\" to \"$1\"\n" if ($localDebug || $liteDebug);
$line = $1."\n";
}
}
print STDERR "LINE[$inputCounter] : $line\n" if ($offsetDebug);
# The tokenizer
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\^|\W)/, $line);
}
# See note about similar block below. This block is for fixing the
# "missing newline" problem, which otherwise would cause line numbers
# to sometimes be wrong.
push(@parts, "BOGUSBOGUSBOGUSBOGUSBOGUS");
my $xpart = "";
foreach my $nextxpart (@parts) {
if (!length($nextxpart)) { next; }
if (!length($xpart)) { $xpart = $nextxpart; next; }
if ($xpart eq "\n" && $nextxpart ne "BOGUSBOGUSBOGUSBOGUSBOGUS") {
print STDERR "FOUND EXTRA NEWLINE\n" if ($offsetDebug);
# $fileoffset++;
$incrementoffsetatnewline++;
}
$xpart = $nextxpart;
}
pop(@parts);
$parserState->{inInlineComment} = 0;
print STDERR "inInlineComment -> 0\n" if ($ilcDebug);
# warn("line $inputCounter\n");
if ($localDebug || $cppDebug || $spaceDebug) {foreach my $partlist (@parts) {print STDERR "PARTLIST: \"$partlist\"\n"; }}
# We have to do the C preprocessing work up front because token substitution
# must occur prior to actual parsing in order to do any good. This block does
# the work.
my $cpp_in_argparse = 0;
if (!$disable_cpp && (1 || $HeaderDoc::enable_cpp)) {
my $newrawline = "";
my $incppargs = 0;
my $cppstring = "";
my $cppname = "";
my $lastcpppart = "";
my @cppargs = ();
my $inChar = 0; my $inString = 0; my $inComment = $parserState->{inComment}; my $inSLC = $parserState->{inInlineComment};
my $inParen = 0;
my $inMacro = $parserState->{inMacro};
my $inCPPSpecial = $parserState->{inMacro} || $parserState->{inMacroLine};
my $inMacroTail = 0;
if ($parserState->{sodname} && ($parserState->{sodname} ne "")) {
$inMacroTail = 1;
}
print STDERR "INMACROTAIL: $inMacroTail\n" if ($cppDebug);
my @cpptrees;
my $cpptreecur = HeaderDoc::ParseTree->new();
my $cpptreetop = $cpptreecur;
# print STDERR "CHECK LINE $line\n";
if ($line =~ /^\s*#include (.*)$/) {
my $rest = $1;
$rest =~ s/^\s*//s;
$rest =~ s/\s*$//s;
if ($rest !~ s/^\<(.*)\>$/$1/s) {
$rest =~ s/^\"(.*)\"$/$1/s;
}
my $filename = basename($rest);
if ($HeaderDoc::HeaderFileCPPHashHash{$filename}) {
my $includehash = HeaderDoc::IncludeHash->new();
$includehash->{FILENAME} = $filename;
$includehash->{LINENUM} = $inputCounter + $fileoffset;
$includehash->{HASHREF} = $HeaderDoc::HeaderFileCPPHashHash{$filename};
push(@HeaderDoc::cppHashList, $includehash);
# print STDERR "PUSH HASH\n";
push(@HeaderDoc::cppArgHashList, $HeaderDoc::HeaderFileCPPArgHashHash{$filename});
}
} elsif ($line =~ /^\s*$definename\s+/) {
# print STDERR "inMacro -> 1\n";
# print STDERR "inMacro -> 1\n" if ($macroDebug || $cppDebug);
# This is a throwaway line.
$inMacro = 1;
}
if ($macrore_pound ne "" && $line =~ /^\s*\#\s*$macrore_pound\s+/) {
print STDERR "CPPSPECIAL -> 1\n" if ($macroDebug || $cppDebug);
$inCPPSpecial = 1;
}
my $cppleaddebug = 0;
do {
my $pos = 0;
my $dropargs = 0;
while ($pos < scalar(@parts)) {
my $part = $parts[$pos];
my $noCPPThisToken = 0;
if (length($part)) {
if (!$inChar && !$inString && !$inComment && !$inSLC) {
if ($parserState->{NEXTTOKENNOCPP} == 1) {
# We're in an "if" block.
if ($part eq "defined") {
$parserState->{NEXTTOKENNOCPP} = 3;
}
} elsif ($parserState->{NEXTTOKENNOCPP} == 2) {
# We're in an "ifdef"/"ifndef" block, so first word token
# ends this mode completely.
if ($part !~ /(\s|\()/) {
$parserState->{NEXTTOKENNOCPP} = 0;
$noCPPThisToken = 1;
}
} elsif ($parserState->{NEXTTOKENNOCPP} == 3) {
# We're in an "if" block, so first word token
# drops us back to default "if" block state.
if ($part !~ /(\s|\()/) {
$parserState->{NEXTTOKENNOCPP} = 1;
$noCPPThisToken = 1;
}
}
if ($inCPPSpecial && $part =~ /(ifdef|ifndef)/) {
$parserState->{NEXTTOKENNOCPP} = 2;
} elsif ($inCPPSpecial && $part =~ /if/) {
$parserState->{NEXTTOKENNOCPP} = 1;
}
}
print STDERR "TOKEN: $part NEXTTOKENNOCPP: ".$parserState->{NEXTTOKENNOCPP}." INMACRO: $inMacro INCPPSPECIAL: $inCPPSpecial\n" if ($cppleaddebug || $macroDebug || $cppDebug);
print STDERR "CPPLEADPART: $part\n"if ($cppleaddebug);
if (!$inString && !$inChar) {
if ($inComment && $part eq $eoc) {
print STDERR "EOC\n"if ($cppleaddebug);
$inComment = 0;
} elsif ($inSLC && $part =~ /[\r\n]/) {
# Handle newline in single-line comments.
print STDERR "EOSLC\n"if ($cppleaddebug);
$inSLC = 0;
} elsif (!$inSLC && $part eq $soc) {
print STDERR "SOC\n"if ($cppleaddebug);
$inComment = 1;
} elsif (!$inComment && ($part eq $ilc || $part eq $ilc_b)) {
print STDERR "INSLC\n"if ($cppleaddebug);
$inSLC = 1;
}
}
my $skip = 0;
if (!$incppargs) {
my $newpart = $part;
my $hasargs = 0;
if (!$inComment && !$inSLC && !$noCPPThisToken) {
($newpart, $hasargs) = cpp_preprocess($part, $HeaderDoc::CurLine);
# Don't drop tokens in macros.
if ($hasargs == 2 && $inMacro) {
$newpart = $part;
$hasargs = 0;
}
# Don't change the macro name. (If a
# macro gets redefined, ignore it.)
if ($inMacro && !$inMacroTail) {
$newpart = $part;
$hasargs = 0;
}
}
if ($hasargs) {
$incppargs = 1;
$cppname = $part;
if ($hasargs == 2) {
$dropargs = 1;
print STDERR "Dropping arguments for ignored macro \"$part\"\n" if ($cppDebug);
}
} else {
my $newpartnl = $newpart;
my $newpartnlcount = ($newpartnl =~ tr/\n//);
my $partnl = $part;
my $partnlcount = ($partnl =~ tr/\n//);
my $nlchange = ($newpartnlcount - $partnlcount);
print STDERR "NLCHANGE: $nlchange (FILEOFFSET = $fileoffset)\n" if ($offsetDebug);
$fileoffset -= $nlchange;
if ($inMacro) {
if ($newpart ne $part) {
print STDERR "CHANGING NEWPART FROM \"$newpart\" TO " if ($cppDebug);
$newpart =~ s/^\s*/ /s;
$newpart =~ s/\s*$//s;
$newpart =~ s/(.)\n/$1 \\\n/sg;
$newpart =~ s/\\$/ /s;
print STDERR "$newpart\n" if ($cppDebug);
}
}
$newrawline .= $newpart;
}
} elsif ($incppargs == 1) {
if ($part eq "(") {
# Don't do anything until leading parenthesis.
$incppargs = 3;
$inParen++;
}
} elsif ($incppargs == 3) {
if ($part eq '\\') {
if (!$inMacro && ($lastcpppart eq '\\')) { $lastcpppart = ""; } # @@@ CHECKME. inMacro test may not be needed.
# else {
# $lastcpppart = $part;
# if ($inMacro) {
# print STDERR "IMTEST\n" if ($cppDebug > 1);
# my $npos = $pos + 1;
# while ($npos < scalar(@parts)) {
# my $npart = $parts[$npos];
# if (length($npart)) {
# print STDERR "NEXTPART: \"".$parts[$npos]."\"\n" if ($cppDebug > 1);
# if ($npart =~ /\s/) {
# if ($npart =~ /[\n\r]/) {
# print STDERR "SKIP1\n" if ($cppDebug > 1);
# $skip = 1; last;
# } else {
# print STDERR "SPC\n" if ($cppDebug > 1);
# }
# } else {
# print STDERR "LAST\n" if ($cppDebug > 1);
# last;
# }
# }
# $npos++;
# }
# }
# }
} elsif ($part eq '"') {
if ($lastcpppart ne '\\') {
if (!$inChar && !$inComment && !$inSLC) {
$inString = !$inString;
}
}
$lastcpppart = $part;
} elsif ($part eq "'") {
if ($lastcpppart ne '\\') {
if (!$inString && !$inComment && !$inSLC) {
$inChar = !$inChar;
}
}
$lastcpppart = $part;
} elsif (!$inChar && !$inString && !$inComment && !$inSLC) {
if ($part eq "(") {
# Put in the token first, then nest.
$cpptreecur = $cpptreecur->next(HeaderDoc::ParseTree->new());
$cpptreecur->token($part);
$skip = 1;
$inParen++;
push(@cpptrees, $cpptreecur);
$cpptreecur = $cpptreecur->firstchild(HeaderDoc::ParseTree->new());
} elsif ($part eq ")") {
$inParen--;
# Go out one nesting level, then
# insert the token.
if (scalar(@cpptrees)) {
$cpptreecur = pop(@cpptrees);
while ($cpptreecur && $cpptreecur->next()) {
$cpptreecur = $cpptreecur->next();
}
}
if (!$inParen) {
push(@cppargs, $cpptreetop);
$cppstring = "";
$cpptreetop = HeaderDoc::ParseTree->new();
$cpptreecur = $cpptreetop;
$skip = 1;
$incppargs = 0;
if (!$dropargs) {
print STDERR "CALLING ARGPARSE FROM blockParse() [1].\n" if ($cppDebug);
my $addon = cpp_argparse($cppname, $HeaderDoc::CurLine, \@cppargs);
if ($inMacro) {
print STDERR "CHANGING ADDON FROM \"$addon\" TO " if ($cppDebug);
$addon =~ s/^\s*/ /s;
$addon =~ s/\s*$//s;
$addon =~ s/(.)\n/$1 \\\n/sg;
$addon =~ s/\\$/ /s;
print STDERR "$addon\n" if ($cppDebug);
}
$newrawline .= $addon;
}
$dropargs = 0;
}
} elsif (($inParen == 1) && (!$inChar && !$inString && !$inComment && !$inSLC) && ($part eq ",")) {
push(@cppargs, $cpptreetop);
$cpptreetop = HeaderDoc::ParseTree->new();
$cpptreecur = $cpptreetop;
$cppstring = "";
$skip = 1;
} elsif (($part =~ /\s/) && (!$inParen)) {
$incppargs = 0;
if (!$dropargs) {
print STDERR "CALLING ARGPARSE FROM blockParse() [2].\n" if ($cppDebug);
my $addon = cpp_argparse($cppname, $HeaderDoc::CurLine, \@cppargs);
if ($inMacro) {
print STDERR "CHANGING ADDON FROM \"$addon\" TO " if ($cppDebug);
$addon =~ s/^\s*/ /s;
$addon =~ s/\s*$//s;
$addon =~ s/(.)\n/$1 \\\n/sg;
$addon =~ s/\\$/ /s;
print STDERR "$addon\n" if ($cppDebug);
}
$newrawline .= $addon;
}
$dropargs = 0;
}
$lastcpppart = $part;
}
if ($skip) { $skip = 0; }
else {
my $xpart = $part;
# Strip newline in CPP argument list.
if ($part =~ /[\r\n]/) { $xpart = " "; }
$cpptreecur = $cpptreecur->next(HeaderDoc::ParseTree->new());
$cpptreecur->token($xpart);
}
$cppstring .= $part;
}
if ($inMacro && $part ne "define" &&
$part =~ /\w/ && !$inParen) {
$inMacroTail = 1;
}
}
$pos++;
}
if ($incppargs) {
# print STDERR "YO\n";
if ($parserState->{inMacro} || $inMacro) {
# print STDERR "YOYO\n";
if ($cppstring !~ s/\\\s*$//s) {
print STDERR "CPPS: \"$cppstring\"\n";
warn "Non-terminated macro.\n";
$incppargs = 0;
}
}
}
if ($incppargs || $inComment) {
print STDERR "Fetching new line ($incppargs, $inComment)\n" if ($cppleaddebug);
$HeaderDoc::CurLine = $inputCounter + $fileoffset;
$line = $inputLines[$inputCounter++];
if ($lang eq "C" && $sublang eq "IDL") {
if ($line =~ /cpp_quote\s*\(\s*\"(.*)\"\s*\)\s*$/) {
print "CHANGED LINE FROM \"$line\" to \"$1\"\n" if ($localDebug || $liteDebug);
$line = $1."\n";
}
}
print STDERR "INCREMENTED INPUTCOUNTER [2]\n" if ($HeaderDoc::inputCounterDebug);
# @parts = split(/(\W)/, $line);
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
}
}
} until (!$incppargs && !$inComment);
# The tokenizer
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $newrawline);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\W)/, $newrawline);
}
while (scalar(@cpptrees)) {
my $temptree = pop(@cpptrees);
if ($temptree != $cpptreetop) {
$temptree->dispose();
}
}
$cpptreetop->dispose();
}
if (!$parserState->{inMacro}) {
$parserState->{NEXTTOKENNOCPP} = 0;
}
# Throw away any empty entries caused by Perl seeing two
# adjacent tokens that match the split regexp. We don't
# want them or care about them, and they break things
# rather badly if we don't....
my @stripparts = @parts;
@parts = ();
print STDERR "BEGIN PARTLIST 2:\n" if ($spaceDebug);
foreach my $strippart (@stripparts) {
if (length($strippart)) {
print STDERR "MYPART: \"$strippart\"\n" if ($spaceDebug);
push(@parts, $strippart);
}
}
print STDERR "END PARTLIST 2.\n" if ($spaceDebug);
# This bit of code needs a bit of explanation, I think.
# We need to be able to see the token that follows the one we
# are currently processing. To do this, we actually keep track
# of the current token, and the previous token, but name then
# $nextpart and $part. We do processing on $part, which gets
# assigned the value from $nextpart at the end of the loop.
#
# To avoid losing the last part of the declaration (or needing
# to unroll an extra copy of the entire loop code) we push a
# bogus entry onto the end of the stack, which never gets
# used (other than as a bogus "next part") because we only
# process the value in $part.
#
# To avoid problems, make sure that you don't ever have a regexp
# that would match against this bogus token.
#
my $part = "";
push(@parts, "BOGUSBOGUSBOGUSBOGUSBOGUS");
if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POSTCPPPARTLIST: \"$partlist\"\n"; }}
foreach my $nextpart (@parts) {
my $hideTokenAndMaybeContents = 0;
$treeSkip = 0;
# $treePopTwo = 0;
# $treePopOnNewLine = 0;
# The current token is now in "part", and the literal next
# token in "nextpart". We can't just work with this as-is,
# though, because you can have multiple spaces, null
# tokens when two of the tokens in the split list occur
# consecutively, etc.
print STDERR "MYPART: \"$part\"\n" if ($localDebug || $spaceDebug);
$forcenobreak = 0;
if ($nextpart eq "\r") { $nextpart = "\n"; }
if ($localDebug && $nextpart eq "\n") { print STDERR "NEXTPART IS NEWLINE!\n"; }
if ($localDebug && $part eq "\n") { print STDERR "PART IS NEWLINE!\n"; }
### if ($nextpart ne "\n" && $nextpart =~ /\s/o) {
### # Replace tabs with spaces.
### $nextpart = " ";
### }
# Replace tabs with spaces.
$part =~ s/\t/ /g;
$nextpart =~ s/\t/ /g;
if ($part ne "\n" && $part =~ /\s/o && $nextpart ne "\n" &&
$nextpart =~ /\s/o) {
# we're a space followed by a space. Join the tokens.
print STDERR "MERGED \"$part\" and \"$nextpart\" into " if ($spaceDebug);
$nextpart = $part.$nextpart;
print STDERR "\"$nextpart\".\n" if ($spaceDebug);
$part = $nextpart;
next;
}
print STDERR "PART IS \"$part\"\n" if ($localDebug || $parserStackDebug || $parseDebug || $liteDebug || $spaceDebug);
print STDERR "CURLINE IS \"$curline\"\n" if ($localDebug || $hangDebug);
print STDERR "INOP: ".$parserState->{inOperator}."\n" if ($operatorDebug);
if (!length($nextpart)) {
print STDERR "SKIP NP\n" if ($localDebug);
next;
}
if (!length($part)) {
print STDERR "SKIP PART\n" if ($localDebug);
$part = $nextpart;
next;
}
if ($occPushParserStateOnWordTokenAfterNext > 1) {
if ($part =~ /\w/) {
$occPushParserStateOnWordTokenAfterNext--;
print STDERR "occPushParserStateOnWordTokenAfterNext -> $occPushParserStateOnWordTokenAfterNext (--)\n" if ($localDebug || $parseDebug);
}
} elsif ($occPushParserStateOnWordTokenAfterNext) {
# if ($part !~ /(\s|<)/)
if ($part =~ /(\/\/|\/\*|\-|\+|\w|\@)/) {
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[occPushParserStateOnWordTokenAfterNext]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 0;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
}
}
# If we get here, we aren't skipping a null or whitespace token.
# Let's print a bunch of noise if debugging is enabled.
# if ($part eq "\n" && $nextpart ne "BOGUSBOGUSBOGUSBOGUSBOGUS") {
# $fileoffset++;
# }
if ($part eq "\n" && $incrementoffsetatnewline) {
$incrementoffsetatnewline--;
$fileoffset++;
}
print STDERR "IN LOOP LANG: $lang INITIAL SUBLANG: $sublang\n" if ($localDebug || $parseDebug);
if ($parseDebug) {
print STDERR "PART: $part, type: $parserState->{typestring}, inComment: $parserState->{inComment}, inInlineComment: $parserState->{inInlineComment}, inChar: $parserState->{inChar}.\n" if ($localDebug);
print STDERR "PART: inBrackets: $parserState->{inBrackets}\n" if ($localDebug);
print STDERR "PART: onlyComments: $parserState->{onlyComments}, inClass: $parserState->{inClass}\n";
print STDERR "PART: cbsodname: $parserState->{cbsodname}\n";
print STDERR "PART: classIsObjC: $parserState->{classIsObjC}, PPSAT: $pushParserStateAfterToken, PPSAWordT: $pushParserStateAfterWordToken, PPSABrace: $pushParserStateAtBrace, occPPSOnWordTokenAfterNext: $occPushParserStateOnWordTokenAfterNext\n";
print STDERR "PART: bracecount: " . scalar(@braceStack) . " (init was $parserState->{initbsCount}).\n";
print STDERR "PART: inString: $parserState->{inString}, callbackNamePending: $parserState->{callbackNamePending}, namePending: $parserState->{namePending}, lastsymbol: $parserState->{lastsymbol}, lasttoken: $lasttoken, lastchar: $lastchar, SOL: $parserState->{startOfDec}\n" if ($localDebug);
print STDERR "PART: sodclass: $parserState->{sodclass} sodname: $parserState->{sodname}\n";
print STDERR "PART: sodtype: $parserState->{sodtype}\n";
print STDERR "PART: simpleTypedef: $parserState->{simpleTypedef}\n";
print STDERR "PART: posstypes: $parserState->{posstypes}\n";
print STDERR "PART: seenBraces: $parserState->{seenBraces} inRegexp: $inRegexp\n";
print STDERR "PART: regexpNoInterpolate: $regexpNoInterpolate\n";
print STDERR "PART: seenTilde: $parserState->{seenTilde}\n";
print STDERR "PART: CBN: $parserState->{callbackName}\n";
print STDERR "PART: regexpStack is:";
foreach my $token (@regexpStack) { print STDERR " $token"; }
print STDERR "\n";
print STDERR "PART: npplStack: ".scalar(@{$parserState->{pplStack}})." nparsedParamList: ".scalar(@{$parserState->{parsedParamList}})." nfreezeStack: ".scalar(@{$parserState->{freezeStack}})." frozen: $parserState->{stackFrozen}\n";
print STDERR "PART: inMacro: $parserState->{inMacro} treePopOnNewLine: $treePopOnNewLine\n";
print STDERR "PART: occmethod: $parserState->{occmethod} occmethodname: $parserState->{occmethodname}\n";
print STDERR "PART: returntype is $parserState->{returntype}\n";
print STDERR "length(declaration) = " . length($declaration) ."; length(curline) = " . length($curline) . "\n";
print STDERR "REQUIREDREGEXP IS \"$requiredregexp\"\n";
print STDERR "DEC: $declaration\n$curline\n";
} elsif ($tsDebug || $treeDebug) {
print STDERR "BPPART: $part\n";
}
if ($parserStackDebug) {
print STDERR "parserState: STACK CONTAINS ".scalar(@parserStack)." STATES\n";
print STDERR "parserState is $parserState\n";
}
# The ignore function returns either null, an empty string,
# or a string that gives the text equivalent of an availability
# macro. If the token is non-null and the length is non-zero,
# it's an availability macro, so blow it in as if the comment
# contained an @availability tag.
#
my $tempavail = ignore($part, $ignoreref, $perheaderignoreref);
printf("PART: $part TEMPAVAIL: $tempavail\n") if ($localDebug || $gccAttributeDebug);
if ($tempavail && ($tempavail ne "1") && ($tempavail ne "2")) {
$parserState->{availability} = $tempavail;
} elsif ($tempavail eq "2") {
# Reusing the GCC attribute handling code because that does exactly what we need.
print STDERR "Function-like availability macro detected. Collecting.\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = 1;
$parserState->{attributeParts} = ();
# Add __attribute__ as the next token.
$treeCur = $treeCur->addSibling($part, 0);
push(@treeStack, $treeCur);
my @tempAvailabilityNodesArray = ();
if ($parserState->{availabilityNodesArray}) {
@tempAvailabilityNodesArray = @{$parserState->{availabilityNodesArray}};
}
push(@tempAvailabilityNodesArray, $treeCur);
# print STDERR "ADDED $treeCur\n";
# $treeCur->dbprint();
$parserState->{availabilityNodesArray} = \@tempAvailabilityNodesArray;
# Nest all contents one level lower.
$treeCur = $treeCur->addChild("", 0);
$part = $nextpart;
next;
}
# Handle the GCC "__attribute__" extension outside the context of
# the parser because it isn't part of the language and massively
# breaks the syntax.
if ($lang eq "C" && isKeyword($part, $keywordhashref, $case_sensitive) == 2) {
print STDERR "GCC attribute detected. Collecting.\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = 1;
$parserState->{attributeParts} = ();
# Add __attribute__ as the next token.
$treeCur = $treeCur->addSibling($part, 0);
push(@treeStack, $treeCur);
# Nest all contents one level lower.
$treeCur = $treeCur->addChild("", 0);
$part = $nextpart;
next;
} elsif ($parserState->{attributeState} == 1) {
if ($part eq "(") {
print STDERR "GCC attribute open paren\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = -1;
}
$treeCur = $treeCur->addSibling($part, 0);
$part = $nextpart;
next;
} elsif ($parserState->{attributeState} < 0) {
if ($part eq "(") {
$parserState->{attributeState}--;
print STDERR "GCC attribute open paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug);
} elsif ($part eq ")") {
$parserState->{attributeState}++;
print STDERR "GCC attribute close paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug);
}
$treeCur = $treeCur->addSibling($part, 0);
if (($localDebug || $gccAttributeDebug) && !$parserState->{attributeState}) {
print STDERR "GCC attribute: done collecting.\n";
# Get back to where we started.
$treeCur = pop(@treeStack);
}
$part = $nextpart;
next;
}
# Here be the parser. Abandon all hope, ye who enter here.
$treepart = "";
if ($parserState->{inProtocol} == 1) {
print STDERR "INPROTOCOL: 1\n" if ($parseDebug || $classDebug);
if ($part =~ /\w/) {
print STDERR "INPROTOCOL: 1 -> 2\n" if ($parseDebug || $classDebug);
$parserState->{inProtocol} = 2;
}
} elsif ($parserState->{inProtocol} == 2) {
print STDERR "INPROTOCOL: 2\n" if ($parseDebug || $classDebug);
if ($part eq "<") {
print STDERR "INPROTOCOL: 2 -> 3\n" if ($parseDebug || $classDebug);
$parserState->{extendsProtocol} = "";
$parserState->{inProtocol} = 3;
} elsif ($part =~ /\S/) {
# PUSH PARSER STATE
print STDERR "parserState pushed onto stack[PROTOCOL]\n" if ($parserStackDebug);
$parserState->{inProtocol} = -1;
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterWordToken = 0;
}
} elsif ($parserState->{inProtocol} == 3) {
print STDERR "INPROTOCOL: 3\n" if ($parseDebug || $classDebug);
if ($part eq ">") {
print STDERR "INPROTOCOL: 3 -> 2\n" if ($parseDebug || $classDebug);
$parserState->{inProtocol} = 2;
} else {
$parserState->{extendsProtocol} .= $part;
}
}
if ($parserState->{inClass} == 3) {
print STDERR "INCLASS3\n" if ($parseDebug || $classDebug);
if ($part eq ")") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [1]\n" if ($classDebug);
$parserState->{categoryClass} .= $part;
print STDERR "parserState will be pushed onto stack[cparen3]\n" if ($parserStackDebug);
# $parserState->{lastTreeNode} = $treeCur;
# push(@parserStack, $parserState);
# $parserState = HeaderDoc::ParserState->new();
# $parserState->{lang} = $lang;
# $parserState->{inputCounter} = $inputCounter;
# $parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterToken = 1;
} elsif ($part eq ":") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [2]\n" if ($classDebug);
if ($parserState->{classIsObjC}) {
print STDERR "occPushParserStateOnWordTokenAfterNext -> 2\n" if ($localDebug || $parseDebug);
$occPushParserStateOnWordTokenAfterNext = 2;
} else {
$pushParserStateAfterWordToken = 1;
}
# if ($sublang eq "occ") {
# $pushParserStateAtBrace = 2;
# }
} elsif ($part =~ /</ && $parserState->{classIsObjC}) {
print STDERR "pushParserStateAfterWordToken -> 0 (Conforming)\n" if ($localDebug || $parseDebug);
print STDERR "inClassConformingToProtocol -> 1\n" if ($localDebug || $parseDebug);
$pushParserStateAfterWordToken = 0;
$parserState->{inClassConformingToProtocol} = 1;
$occPushParserStateOnWordTokenAfterNext = 0;
} elsif ($part =~ />/ && $parserState->{classIsObjC} && $parserState->{inClassConformingToProtocol}) {
print STDERR "inClassConformingToProtocol -> 0\n" if ($localDebug || $parseDebug);
$pushParserStateAfterToken = 1;
print STDERR "pushParserStateAfterWordToken -> 1 (Conforming)\n" if ($localDebug || $parseDebug);
$parserState->{inClassConformingToProtocol} = 0;
} else {
$parserState->{categoryClass} .= $part;
}
} elsif ($parserState->{inClass} == 2) {
print STDERR "INCLASS2\n" if ($parseDebug || $classDebug);
if ($part eq ")") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [3]\n" if ($classDebug);
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[cparen2]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
} elsif ($part eq ":") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [4]\n" if ($classDebug);
if ($parserState->{classIsObjC}) {
print STDERR "occPushParserStateOnWordTokenAfterNext -> 2\n" if ($localDebug || $parseDebug);
$occPushParserStateOnWordTokenAfterNext = 2;
} else {
$pushParserStateAfterWordToken = 2;
}
} elsif ($part =~ /\w/) {
# skip the class name itself.
$parserState->{inClass} = 3;
print STDERR "inClass -> 3 [5]\n" if ($classDebug);
}
} elsif ($parserState->{inClass} == 1) {
print STDERR "INCLASS1\n" if ($parseDebug || $classDebug);
# print STDERR "inclass Part is $part\n";
if ($part eq ":") {
print STDERR "INCLASS COLON\n" if ($parseDebug || $classDebug);
$parserState->{forceClassName} = $parserState->{sodname};
$parserState->{forceClassSuper} = "";
# print STDERR "XSUPER: $parserState->{forceClassSuper}\n";
} elsif ($part eq "{" || $part eq ";") {
print STDERR "INCLASS BRCSEMI\n" if ($parseDebug || $classDebug);
$parserState->{forceClassDone} = 1;
if ($parserState->{classIsObjC} && $part eq "{") {
$parserState->{ISFORWARDDECLARATION} = 0;
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[OCC-BRCSEMI]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 0;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack) + 1; # NOTE: add one here because it will change in the SWITCH to follow.
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
$pushParserStateAfterToken = 1;
} elsif ($part eq ";") {
if (!defined($parserState->{ISFORWARDDECLARATION})) {
print STDERR "FORWARD DECLARATION DETECTED\n" if ($parseDebug || $localDebug || $liteDebug);
# print STDERR "PREVIOUS FD STATE: ".$parserState->{ISFORWARDDECLARATION}."\n";
$parserState->{ISFORWARDDECLARATION} = 1;
}
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
$pushParserStateAfterToken = 0;
}
} elsif ($parserState->{forceClassName} && !$parserState->{forceClassDone}) {
print STDERR "INCLASS ADD\n" if ($parseDebug || $classDebug);
if ($part =~ /[\n\r]/) {
$parserState->{forceClassSuper} .= " ";
} else {
$parserState->{forceClassSuper} .= $part;
}
# print STDERR "SUPER IS $parserState->{forceClassSuper}\n";
} elsif ($part =~ /</ && $parserState->{classIsObjC} && $occPushParserStateOnWordTokenAfterNext) {
print STDERR "INCLASS <\n" if ($parseDebug || $classDebug);
print STDERR "pushParserStateAfterWordToken -> 0 (Conforming)\n" if ($localDebug || $parseDebug);
print STDERR "inClassConformingToProtocol -> 1\n" if ($localDebug || $parseDebug);
$pushParserStateAfterWordToken = 0;
$parserState->{inClassConformingToProtocol} = 1;
$occPushParserStateOnWordTokenAfterNext = 0;
} elsif ($part =~ />/ && $parserState->{classIsObjC} && $parserState->{inClassConformingToProtocol}) {
print STDERR "INCLASS >\n" if ($parseDebug || $classDebug);
print STDERR "inClassConformingToProtocol -> 0\n" if ($localDebug || $parseDebug);
$pushParserStateAfterToken = 1;
print STDERR "pushParserStateAfterWordToken -> 1 (Conforming)\n" if ($localDebug || $parseDebug);
$parserState->{inClassConformingToProtocol} = 0;
} elsif ($occPushParserStateOnWordTokenAfterNext && $part =~ /\w/) {
print STDERR "INCLASS OCCSUPER\n" if ($parseDebug || $classDebug);
$parserState->{occSuper} = $part;
# $occPushParserStateOnWordTokenAfterNext = 0;
# $pushParserStateAfterToken = 1;
} elsif (!$parserState->{classIsObjC}) {
print STDERR "INCLASS NOTOBJC (OTHER)\n" if ($parseDebug || $classDebug);
if ($part =~ /[*(^]/) {
print STDERR "INCLASS DROP\n" if ($parseDebug || $classDebug);
$parserState->{inClass} = 0; # We're an instance. Either a variable or a function.
print STDERR "inClass -> 0 [6]\n" if ($classDebug);
$parserState->{sodtype} = $parserState->{preclasssodtype} . $parserState->{sodtype};
}
# } else {
# print STDERR "BUG\n";
}
};
if ($parserState->{inClassConformingToProtocol} == 1) {
$parserState->{inClassConformingToProtocol} = 2;
} elsif ($parserState->{inClassConformingToProtocol}) {
$parserState->{conformsToList} .= $part;
}
if ($macroDebug) {
print STDERR "MNT: ".$parserState->{macroNoTrunc}."\n";
}
# if (($part eq $ilc || $part eq $ilc_b) && ($lang ne "perl" || $lasttoken ne "\$")) {
# print STDERR "should be ILC?\n";
# } else {
# print STDERR "NO CHANEC: PART \"$part\" ILC \"$ilc\" ILC_B: \"ilc_b\" LANG: \"$lang\" LASTTOKEN: \"$lasttoken\"\n";
# }
SWITCH: {
# Blank declaration handlers (mostly for misuse of
# OSMetaClassDeclareReservedUsed and similar)
(($part eq ";") && ($parserState->{startOfDec} == 1) && !$parserState->{inMacro} && !$parserState->{inMacroLine} && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "LEADING SEMICOLON: CASE 01\n" if ($liteDebug);
print STDERR "Dropping empty declaration\n" if ($localDebug || $parseDebug);
$part = "";
last SWITCH;
};
# Macro handlers
(($parserState->{inMacro} == 1) && ($part eq "define")) && do {
print STDERR "INMACRO/DEFINE: CASE 02\n" if ($liteDebug);
# define may be a multi-line macro
print STDERR "INMACRO AND DEFINE\n" if ($parseDebug || $localDebug);
$parserState->{inMacro} = 3;
print STDERR "inMacro -> 3\n" if ($macroDebug || $cppDebug);
$parserState->{sodname} = "";
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [1]\n"; }
$treePopOnNewLine = 2;
$pound .= $part;
$treeCur->token($pound);
}
last SWITCH;
};
# (($parserState->{inMacro} == 1 && $macrore_pound ne "" && $part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)/ && ($part ne $definename)) || ($parserState->{inMacro} == 0 && $macrore_nopound ne "" && $part =~ /$macrore_nopound/))
# (($parserState->{inMacro} == 1 && $part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)/ )) && do
(!$parserState->{inComment} && (($parserState->{inMacro} == 1 && $macrore_pound ne "" && $part =~ /^$macrore_pound$/ && ($part ne $definename)) || ($parserState->{inMacro} == 0 && $macrore_nopound ne "" && $part =~ /^$macrore_nopound$/))) && do {
print STDERR "MACRORE-v: \"$macrore_pound\"\n" if ($macroDebug);
print STDERR "MACRORE-r: \"(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)\"\n" if ($macroDebug);
print STDERR "MACRORE-n: \"$macrore_nopound\"\n" if ($macroDebug);
print STDERR "INMACRO/IF: CASE 03\n" if ($liteDebug);
print STDERR "INMACRO AND IF/IFDEF/IFNDEF/ENDIF/ELSE/PRAGMA/IMPORT/INCLUDE\n" if ($parseDebug || $localDebug);
# these are all single-line macros
$parserState->{inMacro} = 4;
print STDERR "inMacro -> 4\n" if ($macroDebug || $cppDebug);
$parserState->{sodname} = "";
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [2]\n"; }
$treePopOnNewLine = 1;
$pound .= $part;
$treeCur->token($pound);
if ($part eq "endif") {
# the rest of the line is not part of the macro
# NOTE: Do not change treeCur in the
# next line.
$treeCur->addChild("\n", 0);
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [3]\n"; }
$treePopOnNewLine = 0;
$treeSkip = 1;
}
}
last SWITCH;
};
(($parserState->{inMacroLine} == 1) && ($part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include|define)/o)) && do {
print STDERR "INMACROLINE/IF: CASE 04\n" if ($liteDebug);
print STDERR "INMACROLINE AND IF/IFDEF/IFNDEF/ENDIF/ELSE/PRAGMA/IMPORT/INCLUDE\n" if ($parseDebug || $localDebug);
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$pound .= $part;
$treeCur->token($pound);
if ($part =~ /define/o) {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [4]\n"; }
$treePopOnNewLine = 2;
} elsif ($part eq "endif") {
# the rest of the line is not part of the macro
# NOTE: Do not change treeCur in the
# next line.
$treeCur->addChild("\n", 0);
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [5]\n"; }
$treePopOnNewLine = 0;
$treeSkip = 1;
} else {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [6]\n"; }
$treePopOnNewLine = 1;
}
}
last SWITCH;
};
($parserState->{inMacro} == 1 && ($part ne $soc) && ($part ne $eoc) && $part =~ /\s/) && do {
$treepart = $part; $part = "";
last SWITCH;
};
($parserState->{inMacro} == 1 && ($part ne $soc) && ($part ne $eoc)) && do {
print STDERR "INMACRO PPTOKEN: CASE 05\n" if ($liteDebug);
print STDERR "INMACRO IS 1, CHANGING TO 2 (NO PROCESSING)\n" if ($parseDebug || $localDebug);
# error case.
$parserState->{inMacro} = 2;
print STDERR "inMacro -> 2\n" if ($macroDebug || $cppDebug);
last SWITCH;
};
($parserState->{inMacro} > 1 && $part ne "//" && $part !~ /[\n\r]/ && ($part ne $soc) && ($part ne $eoc)) && do {
print STDERR "INMACRO OTHERTOKEN: CASE 06\n" if ($liteDebug);
print STDERR "INMACRO > 1, PART NE //" if ($parseDebug || $localDebug);
if ($part eq "\\") {
$parserState->addBackslash();
} elsif ($part !~ /[ \t]/) {
$parserState->addBackslash();
}
print STDERR "PART: $part\n" if ($macroDebug);
if ($parserState->{seenMacroPart} && $HeaderDoc::truncate_inline) {
print STDERR "MACRO: SMP&TI\n" if ($macroDebug);
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
print STDERR "MACRO: NOSTACK\n" if ($macroDebug);
if ($part =~ /\s/o && $parserState->{macroNoTrunc} == 1) {
print STDERR "MACRO: ENDOFNAME\n" if ($macroDebug);
$parserState->{macroNoTrunc} = 0;
} elsif ($part =~ /[\{\(]/o) {
print STDERR "MACRO: BRACE\n" if ($macroDebug);
if (!$parserState->{macroNoTrunc}) {
# $parserState->{seenBraces} = 1;
$HeaderDoc::hidetokens = 3;
}
} else {
print STDERR "MACRO: OTHERTOKEN\n" if ($macroDebug);
$parserState->{macroNoTrunc} = 2;
}
}
}
if ($part =~ /[\{\(]/o) {
push(@braceStack, $part);
print STDERR "PUSH\n" if ($macroDebug);
} elsif ($part =~ /[\}\)]/o) {
if ($part ne peekmatch(\@braceStack, $filename, $inputCounter)) {
if ($parserState->{macroNoTrunc} == 1) {
# We haven't reached the end of the first part of the declaration, so this is an error.
warn("$filename:$inputCounter: warning: Initial braces in macro name do not match.\nWe may have a problem.\n");
}
}
pop(@braceStack);
print STDERR "POP\n" if ($macroDebug);
}
if ($part =~ /\S/o) {
$parserState->{seenMacroPart} = 1;
$parserState->{lastsymbol} = $part;
if (($parserState->{sodname} eq "") && ($parserState->{inMacro} == 3)) {
print STDERR "DEFINE NAME IS $part\n" if ($macroDebug);
$parserState->{sodname} = $part;
}
}
$lastchar = $part;
last SWITCH;
};
# Regular expression handlers
# print STDERR "IRE: $inRegexp IRT: $inRegexpTrailer IS: $parserState->{inString} ICo $parserState->{inComment} ILC: $parserState->{inInlineComment} ICh $parserState->{inChar}\n";
(length($regexppattern) && $part =~ /^($regexppattern)$/ && !($inRegexp || $inRegexpTrailer || $parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "REGEXP PATTERN: CASE 07\n" if ($liteDebug);
my $match = $1;
print STDERR "REGEXP WITH PREFIX\n" if ($regexpDebug);
$regexpNoInterpolate = 0;
if ($match =~ /^($singleregexppattern)$/) {
# e.g. perl PATTERN?
$inRegexp = 2;
} else {
$inRegexp = 4;
# print STDERR "REGEXP PART IS \"$part\"\n";
if ($part eq "tr") { $regexpNoInterpolate = 1; }
# if ($part =~ /tr/) { $regexpNoInterpolate = 1; }
}
last SWITCH;
}; # end regexppattern
(($inRegexp || $parserState->{lastsymbol} eq "~") && (length($regexpcharpattern) && $part =~ /^($regexpcharpattern)$/ && (!scalar(@regexpStack) || $part eq peekmatch(\@regexpStack, $filename, $inputCounter)))) && do {
print STDERR "REGEXP CHARACTER: CASE 08\n" if ($liteDebug);
print STDERR "REGEXP?\n" if ($regexpDebug);
if (!$inRegexp) {
$inRegexp = 2;
}
# if ($lasttoken eq "\\")
if ($parserState->isQuoted($lang. $sublang)) {
# jump to next match.
$lasttoken = $part;
$parserState->{lastsymbol} = $part;
next SWITCH;
}
print STDERR "REGEXP POINT A\n" if ($regexpDebug);
$lasttoken = $part;
$parserState->{lastsymbol} = $part;
if ($part eq "#" &&
((scalar(@regexpStack) != 1) ||
(peekmatch(\@regexpStack, $filename, $inputCounter) ne "#"))) {
if ($nextpart =~ /^\s/o) {
# it's a comment. jump to next match.
next SWITCH;
}
}
print STDERR "REGEXP POINT B\n" if ($regexpDebug);
if (!scalar(@regexpStack)) {
push(@regexpStack, $part);
$inRegexp--;
} else {
my $match = peekmatch(\@regexpStack, $filename, $inputCounter);
my $tos = pop(@regexpStack);
if (!scalar(@regexpStack) && ($match eq $part)) {
$inRegexp--;
if ($inRegexp == 2 && $tos eq "/") {
# we don't double the slash in the
# middle of a s/foo/bar/g style
# expression.
$inRegexp--;
}
if ($inRegexp) {
push(@regexpStack, $tos);
}
} elsif (scalar(@regexpStack) == 1) {
push(@regexpStack, $tos);
if ($tos =~ /['"`]/o || $regexpNoInterpolate) {
# these don't interpolate.
next SWITCH;
}
} else {
push(@regexpStack, $tos);
if ($tos =~ /['"`]/o || $regexpNoInterpolate) {
# these don't interpolate.
next SWITCH;
}
push(@regexpStack, $part);
}
}
print STDERR "REGEXP POINT C\n" if ($regexpDebug);
if (!$inRegexp) {
$inRegexpTrailer = 2;
}
last SWITCH;
}; # end regexpcharpattern
# Start of preprocessor macros
($part eq "$sopreproc") && do {
print STDERR "SOPREPROC: CASE 09\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parserState->{onlyComments}) {
print STDERR "inMacro -> 1\n" if ($macroDebug || $cppDebug);
$parserState->{inMacro} = 1;
## @@@ FIXME DAG NEXT TWO LINES NEEDED FOR IDL TO AVOID
## "warning: Declaration starts with # but is not preprocessor macro"
## ERROR MESSAGE, BUT THIS BREAKS C/C++.
## WHY !?!?!
##
## if ($$treepart = " ";
## $nextpart = $part.$nextpart;
##
## END IDL-ONLY BLOCK
# $continue = 0;
# print STDERR "continue -> 0 [1]\n" if ($localDebug || $macroDebug);
} elsif ($curline =~ /^\s*$/o) {
$parserState->{inMacroLine} = 1;
print STDERR "IML\n" if ($localDebug);
} elsif ($postPossNL) {
print STDERR "PRE-IML \"$curline\"\n" if ($localDebug || $macroDebug);
$treeCur = $treeCur->addSibling("\n", 0);
bless($treeCur, "HeaderDoc::ParseTree");
$parserState->{inMacroLine} = 1;
$postPossNL = 0;
}
}
};
# Start of token-delimited functions and procedures (e.g.
# Pascal and PHP)
($part eq "$sofunction" || $part eq "$soprocedure") && do {
print STDERR "SOFUNC: CASE 10\n" if ($liteDebug);
$parserState->{sodclass} = "function";
print STDERR "K&R C FUNCTION FOUND [1].\n" if ($localDebug);
$parserState->{kr_c_function} = 1;
$parserState->{typestring} = "function";
$parserState->{startOfDec} = 2;
$parserState->{namePending} = 1;
# if (!$parserState->{seenBraces}) { # TREEDONE
# $treeNest = 1;
# $treePopTwo++;
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
# }
print STDERR "namePending -> 1 [1]\n" if ($parseDebug);
last SWITCH;
};
# C++ destructor handler.
($part =~ /\~/o && $lang eq "C" && $sublang eq "cpp" && !!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "C++ DESTRUCTOR: CASE 11\n" if ($liteDebug);
print STDERR "TILDE\n" if ($localDebug);
$parserState->{seenTilde} = 2;
$lastchar = $part;
$parserState->{onlyComments} = 0;
# $name .= '~';
last SWITCH;
};
# Objective-C method handler.
($part =~ /[-+]/o && $parserState->{onlyComments}) && do {
print STDERR "OBJC METHOD: CASE 12\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
print STDERR "OCCMETHOD\n" if ($localDebug);
# Objective C Method.
$parserState->{occmethod} = 1;
$parserState->{occmethodtype} = $part;
$lastchar = $part;
$parserState->{onlyComments} = 0;
print STDERR "[a]onlyComments -> 0\n" if ($macroDebug);
if (!$parserState->{seenBraces}) { # TREEDONE
if (!$parserState->{hollow}) {
print STDERR "SETHOLLOW -> 1\n" if ($parserStackDebug);
$sethollow = 1;
}
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [7]\n"; }
$parserState->{treePopTwo} = 1;
}
}
last SWITCH;
};
# Newline handler.
($part =~ /[\n\r]/o) && do {
print STDERR "NEWLINE: CASE 13\n" if ($liteDebug);
# NEWLINE FOUND
$treepart = $part;
if ($inRegexp) {
warn "$filename:$inputCounter: warning: multi-line regular expression\n";
}
print STDERR "NLCR\n" if ($tsDebug || $treeDebug || $localDebug);
if ($lastchar !~ /[\,\;\{\(\)\}]/o && $nextpart !~ /[\{\}\(\)]/o) {
if ($lastchar ne "*/" && $nextpart ne "/*") {
if (!$parserState->{inMacro} && !$parserState->{inMacroLine} && !$treePopOnNewLine) {
print STDERR "NL->SPC\n" if ($localDebug);
$part = " ";
print STDERR "LC: $lastchar\n" if ($localDebug);
print STDERR "NP: $nextpart\n" if ($localDebug);
$postPossNL = 2;
} else {
$parserState->{inMacroLine} = 0;
# Don't push parsed parameter here. Just clear it.
# push(@{$parserState->{parsedParamList}}, $parsedParam);
# print STDERR "pushed $parsedParam into parsedParamList [1]\n" if ($parmDebug);
print STDERR "skipped pushing CPP directive $parsedParam into parsedParamList [1]\n" if ($parmDebug || $cppDebug || $localDebug);
$parsedParam = "";
}
}
}
if ($treePopOnNewLine < 0) {
# pop once for //, possibly again for macro
$treePopOnNewLine = 0 - $treePopOnNewLine;
$treeCur = $treeCur->addSibling($treepart, 0);
bless($treeCur, "HeaderDoc::ParseTree");
# push(@treeStack, $treeCur);
$treeSkip = 1;
$treeCur = pop(@treeStack);
if (!$treeCur) {
$treeCur = $treeTop;
warn "$filename:$inputCounter: warning: Attempted to pop off top of tree\n";
}
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [1]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($treePopOnNewLine == 1 || ($treePopOnNewLine && !$parserState->isQuoted())) {
# $parserState->{lastsymbol} ne "\\"
$treeCur = $treeCur->addSibling($treepart, 0);
bless($treeCur, "HeaderDoc::ParseTree");
# push(@treeStack, $treeCur);
$treeSkip = 1;
$treeCur = pop(@treeStack);
if (!$treeCur) {
$treeCur = $treeTop;
warn "$filename:$inputCounter: warning: Attempted to pop off top of tree\n";
}
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->addSibling("", 0); # empty token
print STDERR "TSPOP [1a]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
$treePopOnNewLine = 0;
$HeaderDoc::hidetokens = 0;
} else {
print STDERR "Not popping from tree. Probably quoted.\n" if ($localDebug || $parseDebug);
}
next SWITCH;
};
# C++ template handlers
($part eq $sotemplate && !$parserState->{seenBraces} && ($parserState->{inOperator} != 1)) && do {
print STDERR "C++ TEMPLATE: CASE 14\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($HeaderDoc::hideIDLAttributes && $lang eq "C" && $sublang eq "IDL") { $hideTokenAndMaybeContents = 3; }
print STDERR "inTemplate -> ".($parserState->{inTemplate}+1)."\n" if ($localDebug);
print STDERR "SBS: " . scalar(@braceStack) . ".\n" if ($localDebug);
$parserState->{inTemplate}++;
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
$parserState->{preTemplateSymbol} = $parserState->{lastsymbol};
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{onlyComments} = 0;
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if (!$parserState->{hollow}) { $sethollow = 1; } # IDL can have this at the start of declaration.
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [8]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
print STDERR "[b]onlyComments -> 0\n" if ($macroDebug);
}
last SWITCH;
};
($part eq $eotemplate && !$parserState->{seenBraces} && ($parserState->{inOperator} != 1)) && do {
print STDERR "C++ TEMPLATE END: CASE 15\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && (!(scalar(@braceStack)-$parserState->{initbsCount}) || $parserState->{inTemplate})) {
if ($parserState->{inTemplate}) {
print STDERR "parserState->{inTemplate} -> ".($parserState->{inTemplate}-1)."\n" if ($localDebug);
$parserState->{inTemplate}--;
$parserState->{lastsymbol} = "";
$lastchar = $part;
$curline .= " ";
$parserState->{onlyComments} = 0;
print STDERR "[c]onlyComments -> 0\n" if ($macroDebug);
}
my $top = pop(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [2]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($top ne "$sotemplate") {
warn("$filename:$inputCounter: warning: Template (angle) brackets do not match.\nWe may have a problem.\n");
}
}
last SWITCH;
};
#
# Handles C++ access control state, e.g. "public:"
#
($part eq ":") && do {
print STDERR "Access control colon: CASE 16\n" if ($liteDebug);
print STDERR "TS IS \"$parserState->{typestring}\"\n" if ($localDebug || $parseDebug);
# fall through to next colon handling case if we fail.
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (length($accessregexp) && ($lastnspart =~ /$accessregexp/)) {
# We're special.
print STDERR "PERMANENT ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$parserState->{typestring} = "";
print STDERR "RESET HOLLOW at $part\n" if ($parserStackDebug);
$parserState->{hollow} = undef;
$parserState->{onlyComments} = 1;
print STDERR "hollowskip -> 1 (ACS)\n" if ($parserStateInsertDebug);
$hollowskip = 1;
$HeaderDoc::AccessControlState = $1;
$lastACS = $1;
last SWITCH;
} elsif ($parserState->{typestring} eq "struct") {
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
if (!$parserState->{structClassName}) {
$parserState->{structClassName} = $parserState->{lastsymbol};
$parserState->{bracePending} = 2;
}
}
}
}
};
(length($accessregexp) && ($part =~ /$accessregexp/)) && do {
print STDERR "Access regexp: CASE 17\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
# We're special.
if ($part =~ /^\@(.*)$/) {
print STDERR "PERMANENT ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$parserState->{typestring} = "";
print STDERR "RESET HOLLOW at $part\n" if ($parserStackDebug);
$parserState->{hollow} = undef;
$parserState->{onlyComments} = 1;
$hollowskip = 1;
print STDERR "hollowskip -> 1 (\@ACS)\n" if ($parserStateInsertDebug);
$HeaderDoc::AccessControlState = $1;
$lastACS = $1;
last SWITCH;
} else {
print STDERR "TEMPORARY ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$lastACS = $HeaderDoc::AccessControlState;
$HeaderDoc::AccessControlState = $1;
}
} else {
next SWITCH;
}
};
(length($requiredregexp) && $part =~ /$requiredregexp/) && do {
print STDERR "REQUIRED REGEXP MATCH: \"$part\"\n" if ($localDebug || $parseDebug);
$hollowskip = 1;
print STDERR "hollowskip -> 1 (requiredregexp)\n" if ($parserStateInsertDebug);
last SWITCH;
};
#
# C++ copy constructor handler. For example:
#
# char *class(void *a, void *b) :
# class(pri_type, pri_type);
#
($part eq ":") && do {
print STDERR "Copy constructor: CASE 18\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parserState->{occmethod}) {
$parserState->{name} = $parserState->{lastsymbol};
if ($parserState->{occparmlabelfound}) {
$parserState->{occmethodname} .= "$parserState->{lastsymbol}:";
if ($occMethodNameDebug) {
print STDERR "OCC method name now ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\").\n";
}
$parserState->{occparmlabelfound} = -1; # next token is name of this parameter, followed by label for next parameter.
} else {
if ($occMethodNameDebug) {
print STDERR "OCC method name missing.\n";
print STDERR "OCC method name still ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\").\n";
}
$parserState->{occparmlabelfound} = -2; # Special case: grab the parameter name instead because parameter has no label.
}
# Start doing line splitting here.
# Also, capture the method's name.
if ($parserState->{occmethod} == 1) {
$parserState->{occmethod} = 2;
if (!$prespace) { $prespaceadjust = 4; }
$parserState->{onlyComments} = 0;
print STDERR "[d]onlyComments -> 0\n" if ($macroDebug);
}
} else {
if ($lang eq "C" && $sublang eq "cpp") {
if (!(scalar(@braceStack)-$parserState->{initbsCount}) && $parserState->{sodclass} eq "function") {
$inPrivateParamTypes = 1;
$declaration .= "$curline";
$publicDeclaration = $declaration;
$declaration = "";
} else {
next SWITCH;
}
if (!$parserState->{stackFrozen}) {
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
# print STDERR "SEOPPLS\n";
# for my $item (@{$parserState->{pplStack}}) {
# print STDERR "PPLS: $item\n";
# }
# print STDERR "OEOPPLS\n";
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
} else {
next SWITCH;
}
}
if (!$parserState->{seenBraces} && !$parserState->{occmethod}) { # TREEDONE
# $treeCur->addSibling($part, 0); $treeSkip = 1;
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [9]\n"; }
$parserState->{treePopTwo} = 1;
# $treeCur = pop(@treeStack) || $treeTop;
# bless($treeCur, "HeaderDoc::ParseTree");
}
last SWITCH;
} else {
next SWITCH;
}
};
# Non-newline, non-carriage-return whitespace handler.
($part =~ /\s/o) && do {
print STDERR "Whitespace: CASE 19\n" if ($liteDebug);
# just add white space silently.
# if ($part eq "\n") { $parserState->{lastsymbol} = ""; };
$lastchar = $part;
last SWITCH;
};
# backslash handler (largely useful for macros, strings).
($part =~ /\\/o) && do {
print STDERR "BACKSLASH: CASE 20\n" if ($liteDebug);
$parserState->{lastsymbol} = $part; $lastchar = $part;
$parserState->addBackslash();
};
# quote and bracket handlers.
($part eq "\"") && do {
print STDERR "DOUBLE QUOTE: CASE 21\n" if ($liteDebug);
print STDERR "dquo\n" if ($localDebug);
# print STDERR "QUOTEDEBUG: CURSTRING IS '$curstring'\n";
# print STDERR "QUOTEDEBUG: CURLINE IS '$curline'\n";
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{onlyComments} = 0;
print STDERR "[e]onlyComments -> 0\n" if ($macroDebug);
print STDERR "LASTTOKEN: $lasttoken\nCS: $curstring\n" if ($localDebug);
# if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o))
if (!$parserState->isQuoted($lang, $sublang)) {
if (!$parserState->{inString}) {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [10]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} else {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [3]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
$parserState->{inString} = (1-$parserState->{inString});
}
}
$lastchar = $part;
$parserState->{lastsymbol} = "";
last SWITCH;
};
($part eq "[") && do {
print STDERR "LEFT BRACKET: CASE 22\n" if ($liteDebug);
# left square bracket (square brace)
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
print STDERR "lbracket\n" if ($localDebug);
print STDERR "LBRACKET DEBUG TRACE: SODNAME: ".$parserState->{sodname}." SODTYPE: ".$parserState->{sodtype}." SIMPLETDCONTENTS: ".$parserState->{simpleTDcontents}."\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
$parserState->{onlyComments} = 0;
print STDERR "[f]onlyComments -> 0\n" if ($macroDebug);
}
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [11]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$parserState->{inBrackets} += 1;
}
$lastchar = $part;
last SWITCH;
};
($part eq "]") && do {
print STDERR "CLOSE BRACKET: CASE 23\n" if ($liteDebug);
# right square bracket (square brace)
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
print STDERR "rbracket\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
$parserState->{onlyComments} = 0;
print STDERR "[g]onlyComments -> 0\n" if ($macroDebug);
}
my $top = pop(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [4]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($top ne "[") {
warn("$filename:$inputCounter: warning: Square brackets do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
}
pbs(@braceStack);
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$parserState->{inBrackets} -= 1;
}
$lastchar = $part;
last SWITCH;
};
($part eq "'") && do {
print STDERR "SINGLE QUOTE: CASE 24\n" if ($liteDebug);
print STDERR "squo\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
# if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o))
if (!$parserState->isQuoted($lang, $sublang)) {
$parserState->{onlyComments} = 0;
print STDERR "[h]onlyComments -> 0\n" if ($macroDebug);
if (!$parserState->{inChar}) {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [12]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} else {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [5]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
$parserState->{inChar} = !$parserState->{inChar};
}
if ($lastchar =~ /\=$/o) {
$curline .= " ";
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Inline comment (two slashes in c++, hash in perl/shell)
# handler.
(($part eq $ilc || $part eq $ilc_b) && ($lang ne "perl" || $lasttoken ne "\$")) && do {
print STDERR "SINGLE LINE COMMENT: CASE 25\n" if ($liteDebug);
print STDERR "ILC\n" if ($localDebug || $ilcDebug);
if (!($parserState->{inComment} || $parserState->{inChar} || $parserState->{inString} || $inRegexp)) {
$parserState->{inInlineComment} = 4;
print STDERR "inInlineComment -> 1\n" if ($ilcDebug);
$curline = spacefix($curline, $part, $lastchar, $soc, $eoc, $ilc, $ilc_b);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [13]\n"; }
if (!$treePopOnNewLine) {
$treePopOnNewLine = 1;
} else {
$treePopOnNewLine = 0 - $treePopOnNewLine;
}
print STDERR "treePopOnNewLine -> $treePopOnNewLine\n" if ($ilcDebug);
# $treeCur->addSibling($part, 0); $treeSkip = 1;
# $treePopOnNewLine = 1;
# $treeCur = pop(@treeStack) || $treeTop;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif ($parserState->{inComment}) {
my $linenum = $inputCounter + $fileoffset;
if (!$cpp_in_argparse) {
# We've already seen these.
if ($nestedcommentwarn) {
warn("$filename:$linenum: warning: Nested comment found [1]. Ignoring.\n");
}
# This isn't really a problem.
# Don't warn to avoid bogus
# warnings for apple_ref and
# URL markup in comments.
}
# warn("XX $cpp_in_argparse XX $inputCounter XX $fileoffset XX\n");
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Standard comment handlers: soc = start of comment,
# eoc = end of comment.
($part eq $soc) && do {
print STDERR "START OF MULTILINE COMMENT: CASE 26\n" if ($liteDebug);
print STDERR "SOC\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{inComment} = 4;
$curline = spacefix($curline, $part, $lastchar);
if (!$parserState->{seenBraces}) {
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [14]\n"; }
# print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug);
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild("", 0);
# bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif ($parserState->{inComment}) {
my $linenum = $inputCounter + $fileoffset;
# Modern compilers shouldn't have trouble with this. It occurs |
# frequently in apple_ref markup (e.g. //apple_ref/C/instm/ \|/
# IOFireWireDeviceInterface/AddIsochCallbackDispatcherToRunLoop/*Add
# IsochCallbackDispatcherToRunLoopIOFireWireLibDeviceRefCFRunLoopRef)
if ($nestedcommentwarn) {
warn("$filename:$linenum: warning: Nested comment found [2]. Ignoring.\n");
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
($part eq $eoc) && do {
print STDERR "END OF MULTILINE COMMENT: CASE 27\n" if ($liteDebug);
print STDERR "EOC\n" if ($localDebug);
if ($parserState->{inComment} && !($parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{inComment} = 0;
$curline = spacefix($curline, $part, $lastchar);
$ppSkipOneToken = 1;
if (!$parserState->{seenBraces}) {
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif (!$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && !$inRegexp) {
my $linenum = $inputCounter + $fileoffset;
warn("$filename:$linenum: warning: Unmatched close comment tag found. Ignoring.\n");
} elsif ($parserState->{inInlineComment}) {
my $linenum = $inputCounter + $fileoffset;
# We'll leave this one on for now.
if ((1 || $nestedcommentwarn) && (!$HeaderDoc::test_mode)) {
warn("$filename:$linenum: warning: Nested comment found [3]. Ignoring.\n");
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Parenthesis and brace handlers.
($part eq "(") && do {
print STDERR "OPEN PAREN: CASE 28\n" if ($liteDebug);
my @tempppl = undef;
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
if (!(scalar(@braceStack)-$parserState->{initbsCount})) {
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
print STDERR "parsedParamList wiped\n" if ($parmDebug);
@tempppl = @{$parserState->{parsedParamList}};
@{$parserState->{parsedParamList}} = ();
$parsedParam = "";
}
$parserState->{onlyComments} = 0;
print STDERR "[i]onlyComments -> 0\n" if ($macroDebug);
if ($parserState->{simpleTypedef} && !(scalar(@braceStack)- $parserState->{initbsCount})) {
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "Setting typedef sodname to ".$parserState->{lastsymbol}."\n" if ($localDebug || $sodDebug);
$parserState->{sodname} = $parserState->{lastsymbol};
$parserState->{sodclass} = "function";
# DAG: changed to respect freezereturn
# and hollow, but in the unlikely event
# that we should start seeing any weird
# "missing return type info" bugs,
# this next line might need to be
# put back in rather than the lines
# that follow it.
# $parserState->{returntype} = "$declaration$curline";
if (!$parserState->{freezereturn} && $parserState->{hollow}) {
$parserState->{returntype} = "$declaration$curline";
} elsif (!$parserState->{freezereturn} && !$parserState->{hollow}) {
$parserState->{returntype} = "$curline";
$declaration = "";
}
}
$parserState->{posstypesPending} = 0;
if ($parserState->{callbackNamePending} == 2) {
$parserState->{callbackNamePending} = 3;
print STDERR "callbackNamePending -> 3\n" if ($localDebug || $cbnDebug);
}
print STDERR "lparen\n" if ($localDebug);
if ($parserState->{cbsodname} && (scalar(@braceStack)-$parserState->{initbsCount}) == 0) {
if (!$parserState->{functionReturnsCallback}) {
# At the top level, if we see a second open parenthesis after setting a callback
# name, the first token in the first set of open parentheses is the name of
# the callback, so clear cbsodname.
#
# Until this point, the value in cbsodname was a copy of the already-cleared
# sodname field, and would replace the callbackName field at the end of
# processing.
$parserState->{cbsodname} = "";
} else {
# If we are in a function that returns a callback, everything from here on
# is a list of parameters for the callback, not the function, so the
# previous parameter list should be discarded (though it is useful to
# add these parameters as valid things to comment about)
@{$parserState->{parsedParamList}} = @tempppl;
$parserState->{functionReturnsCallback}--;
print STDERR "parsedParamList restored\n" if ($parmDebug);
}
}
if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) {
if ($parserState->{callbackName}) {
$parserState->{cbsodname} = $parserState->{callbackName};
$parserState->{sodclass} = "function";
# $parserState->{callbackName} = "";
$parserState->{functionReturnsCallback}++;
print "Function returning callback. NAME: $parserState->{cbsodname}\n" if ($parmDebug || $localDebug || $parseDebug);
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
print STDERR "parsedParamList wiped\n" if ($parmDebug);
@tempppl = @{$parserState->{parsedParamList}};
@{$parserState->{parsedParamList}} = ();
$parsedParam = "";
}
}
if ($parserState->{inOperator} == 1) {
$parserState->{inOperator} = 2;
}
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [15]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
print STDERR "LASTCHARCHECK: \"$lastchar\" \"$lastnspart\" \"$curline\".\n" if ($localDebug);
if ($lastnspart eq ")") { # || $curline =~ /\)\s*$/so
print STDERR "HERE: DEC IS $declaration\nENDDEC\nCURLINE IS $curline\nENDCURLINE\n" if ($localDebug);
# print STDERR "CALLBACKMAYBE: $parserState->{callbackNamePending} $parserState->{sodclass} ".scalar(@braceStack)."\n";
print STDERR "SBS: ".scalar(@braceStack)."\n" if ($localDebug);
### if (!$parserState->{callbackNamePending} && ($parserState->{sodclass} eq "function") && ((scalar(@braceStack)-$parserState->{initbsCount}) == 1)) { # && $argparse
### # Guess it must be a callback anyway.
### my $temp = pop(@tempppl);
### $parserState->{callbackName} = $temp;
### $parserState->{name} = "";
### $parserState->{sodclass} = "";
### $parserState->{sodname} = "";
### print STDERR "CALLBACKHERE ($temp)!\n" if ($cbnDebug || $parseDebug);
### }
if ($declaration =~ /.*\n(.*?)\n$/so) {
my $lastline = $1;
print STDERR "LL: $lastline\nLLDEC: $declaration" if ($localDebug);
$declaration =~ s/(.*)\n(.*?)\n$/$1\n/so;
$curline = "$lastline $curline";
$curline =~ s/^\s*//so;
$prespace -= 4;
$prespaceadjust += 4;
$forcenobreak = 1;
print STDERR "NEWDEC: $declaration\nNEWCURLINE: $curline\n" if ($localDebug);
} elsif (length($declaration) && $callback_typedef_and_name_on_one_line) {
print STDERR "SCARYCASE\n" if ($localDebug);
$declaration =~ s/\n$//so;
$curline = "$declaration $curline";
$declaration = "";
$prespace -= 4;
$prespaceadjust += 4;
$forcenobreak = 1;
}
} else { print STDERR "OPARENLC: \"$lastchar\"\nCURLINE IS: \"$curline\"\n" if ($localDebug);}
$parserState->{lastsymbol} = "";
$lastchar = $part;
if ($parserState->{startOfDec} == 2) {
$parserState->{sodclass} = "function";
$parserState->{freezereturn} = 1;
$parserState->{returntype} =~ s/^\s*//so;
$parserState->{returntype} =~ s/\s*$//so;
}
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
print STDERR "OUTGOING CURLINE: \"$curline\"\n" if ($localDebug);
last SWITCH;
};
($part eq ")") && do {
print STDERR "CLOSE PAREN: CASE 29\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate && (peek(\@regexpStack) ne "("))) {
if ((scalar(@braceStack)-$parserState->{initbsCount} - $parserState->{functionReturnsCallback}) == 1) {
# stop parameter parsing
$parsedParamParse = 0;
print STDERR "parsedParamParse -> 0\n" if ($parmDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if ($parsedParam ne "void") {
# ignore foo(void)
push(@{$parserState->{parsedParamList}}, $parsedParam);
print STDERR "pushed $parsedParam into parsedParamList [1]\n" if ($parmDebug);
}
$parsedParam = "";
}
$parserState->{onlyComments} = 0;
print STDERR "[j]onlyComments -> 0\n" if ($macroDebug);
print STDERR "rparen\n" if ($localDebug);
my $test = pop(@braceStack); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6a]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if (!($test eq "(")) { # ) brace hack for vi
warn("$filename:$inputCounter: warning: Parentheses do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
# cluck("backtrace follows\n");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace -= 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust -= 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
(casecmp($part, $lbrace, $case_sensitive)) && do {
print STDERR "LEFT BRACE: CASE 30\n" if ($liteDebug);
if ($parserState->{onlyComments} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inChar} && !($inRegexp && $regexpNoInterpolate) && scalar(@parserStack)) {
# Somebody put in a brace in the middle of
# a class or else we're seeing ObjC private
# class bits. Either way, throw away the
# curly brace.
print STDERR "NOINSERT\n" if ($parserStackDebug);
$pushParserStateAtBrace = 1;
# $setNoInsert = 1;
$parserState->{noInsert} = 1;
}
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
$parserState->{bracePending} = 0;
print STDERR "bracePending -> 0 [brace]\n" if ($localDebug);
$parserState->{onlyComments} = 0;
print STDERR "[k]onlyComments -> 0\n" if ($macroDebug);
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
# print STDERR "statecheck: ".$parserState->{inClass}."X".$parserState->{sodclass}."X".$parserState->{inOperator}."X".$parserState->{occmethod}."\n"; # @@@ CHECKME - Do this for Obj-C methods too?
if (!$parserState->{inClass} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator} || $parserState->{occmethod})) {
# This is the opening brace of a function. Start ignoring everything
# until the matching brace is encountered.
print "seenBraces -> 1\n" if ($parseDebug);
$parserState->{seenBraces} = 1;
if (!$parserState->{stackFrozen}) {
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
@{$parserState->{pplStack}} = ();
}
$parserState->{posstypesPending} = 0;
$parserState->{namePending} = 0;
$parserState->{callbackNamePending} = -1;
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "callbackNamePending -> -1\n" if ($localDebug || $cbnDebug);
print STDERR "lbrace\n" if ($localDebug);
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [16]\n"; }
print STDERR "TN -> 1\n" if ($localDebug);
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
if ($parserState->{INMODULE} == 2) {
# Drop token on the floor.
$treepart = " ";
}
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
(casecmp($part, $rbrace, $case_sensitive)) && do {
print STDERR "RIGHT BRACE: CASE 31\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate && (peek(\@regexpStack) ne "$lbrace"))) {
my $oldOC = $parserState->{onlyComments};
print STDERR "rbrace???\n" if ($localDebug);
# $parserState->{onlyComments} = 0; # If this is all we've seen, there's either a bug or we're
# unrolling a class or similar anyway.
print STDERR "[l]onlyComments -> 0\n" if ($macroDebug);
my $bsCount = scalar(@braceStack);
if (scalar(@parserStack) && !($bsCount - $parserState->{initbsCount})) {
print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug);
if ($parserState->{noInsert} || $oldOC) {
print STDERR "parserState insertion skipped[RBRACE]\n" if ($parserStackDebug || $parserStateInsertDebug);
} elsif ($parserState->{hollow}) {
print STDERR "inserted parser state into tree [RBRACE]\n" if ($parserStateInsertDebug);
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[1].\n";
}
print STDERR "parserState popped from parserStack[rbrace]\n" if ($parserStackDebug);
# print STDERR "PREINMODULE: ".$parserState->{INMODULE}."\n";
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
# print STDERR "INMODULE: ".$parserState->{INMODULE}."\n";
if ($parserState->{INMODULE} == 2) {
# Drop token on the floor.
print STDERR "CURRENT: ".$treeCur->{TOKEN}."\n" if ($localDebug);
$part = "";
print STDERR "INMODULE -> 3\n" if ($localDebug || $moduleDebug);
$parserState->{INMODULE} = 3;
print STDERR "continue -> 0 [1a]\n" if ($localDebug || $liteDebug);
$parserState->{noInsert} = 0;
$continue = 0;
print STDERR "AT END: REALPS IS ".$parserState->{REALPS}."\n" if ($parserStackDebug || $localDebug);
print STDERR "STACK COUNT: ".scalar(@parserStack)."\n" if ($parserStackDebug || $localDebug);
}
if ($lang eq "php" || ($lang eq "C" && $sublang eq "IDL")) {
# print STDERR "PHP OUT OF BRACES?: ".scalar(@braceStack)."\n";
if (scalar(@braceStack) == 1) {
# PHP and IDL classes end at
# the brace.
print STDERR "continue -> 0 [1a]\n" if ($localDebug || $liteDebug);
$continue = 0;
}
}
if ($parserState->{noInsert} && scalar(@parserStack)) {
# This is to handle the end of
# the private vars in an
# Objective C class.
print STDERR "parserState: Hit me.\n" if ($localDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
# It's about to go down by 1.
$parserState->{initbsCount} = scalar(@braceStack) - 1;
}
# $parserState->{onlyComments} = 1;
} else {
print STDERR "NO CHANGE IN PARSER STATE STACK (nPARSERSTACK = ".scalar(@parserStack).", $bsCount != $parserState->{initbsCount})\n" if ($parseDebug || $parserStackDebug);
}
if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) {
# stop parameter parsing
$parsedParamParse = 0;
print STDERR "parsedParamParse -> 0\n" if ($parmDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) {
# ignore foo(void)
push(@{$parserState->{parsedParamList}}, $parsedParam);
print STDERR "pushed $parsedParam into parsedParamList [1b]\n" if ($parmDebug);
}
$parsedParam = "";
} else {
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
}
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
print STDERR "rbrace\n" if ($localDebug);
my $test = pop(@braceStack); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [7]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if (!($test eq "$lbrace") && (!length($structname) || (!($test eq $structname) && $structisbrace))) {
warn("$filename:$inputCounter: warning: Braces do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace -= 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust -= 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
# Typedef, struct, enum, and union handlers.
# Merge the '@' symbol onto @protocol, @property, @public, and similar.
(length($part) && length($nextpart) && ((length($propname) && $propname =~ /\@/) || length($objcdynamicname) || length($objcsynthesizename) || length($classregexp) || (length($accessregexp) && $accessregexp =~ /\@/)) && $part =~ /^\@$/ && !$parserState->{inComment} && !$parserState->{inChar} && !$parserState->{inString} && !$parserState->{inInlineComment}) && do {
print STDERR "PROPERTY PREPEND AT (\@): CASE 32\n" if ($liteDebug);
my $temp = "\@".$nextpart;
# print STDERR "TEMP IS $temp PROPNAME is $propname\n";
if ($temp =~ /$accessregexp/) {
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
$parserState->{classIsObjC} = 1;
} elsif ($temp =~ /$classregexp/) {
$nextpart = "\@".$nextpart;
$parserState->{classIsObjC} = 1;
} elsif ($temp =~ /$classclosebraceregexp/) {
$nextpart = "\@".$nextpart;
} elsif ($temp eq $propname) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif (length($requiredregexp) && $temp =~ /$requiredregexp/) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif ($temp eq $objcdynamicname) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif ($temp eq $objcsynthesizename) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
}
next SWITCH;
};
($modules_are_special && !$parserState->{inTemplate} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && length($moduleregexp) && $part =~ /$moduleregexp/) && do {
print STDERR "INMODULE -> 1\n" if ($localDebug || $moduleDebug);
$parserState->{INMODULE} = 1;
print STDERR "MODULE START TOKEN: CASE 32-M-1\n" if ($localDebug || $liteDebug);
};
(length($classclosebraceregexp) && ($part =~ /$classclosebraceregexp/) && !$parserState->{inComment} && !$parserState->{inChar} && !$parserState->{inString} && !$parserState->{inInlineComment}) && do {
print STDERR "CLASS CLOSE BRACE: CASE 33\n" if ($liteDebug);
if ($part ne peekmatch(\@braceStack, $filename, $inputCounter)) {
warn("$filename:inputCounter: warning: Class braces do not match.\nWe may have a problem.\n");
}
$parserState->{seenBraces} = 1;
pop(@braceStack);
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
$part =~ s/^\@//s;
if ( 1 || $nextpart ne ";") {
# Objective C protocol/interface declarations end at the close curly brace.
# No ';' necessary (though we'll eat it if it's there.
# No, we won't. Deal with it.
if (scalar(@parserStack) == 1) {
# Throw away current parser state, since
# it will always be empty anyway.
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
$continue = 0;
print STDERR "continue -> 0 [occend]\n" if ($localDebug);
} else {
if (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[\@end]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
print STDERR "inserted parser state into tree [\@end]\n" if ($parserStateInsertDebug);
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[2].\n";
}
print STDERR "parserState: Created parser state[1].\n" if ($parserStackDebug);
print STDERR "CURLINE CLEAR[PRS2]\n" if ($localDebug);
$curline = "";
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
}
print STDERR "parserState popped from parserStack[\@end]\n" if ($parserStackDebug);
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
}
}
# fall through to next case. WHY???
};
(!$parserState->{inTemplate} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && length($classregexp) && $part =~ /$classregexp/) && do {
print STDERR "START OF CLASS: CASE 34\n" if ($liteDebug);
### if ($parserState->{classIsObjC}) { $sublang = "occ"; }
### else { $sublang = "cpp"; }
### print STDERR "LANG $lang SUBLANG $sublang\n" if ($localDebug || $parseDebug || $classDebug);
### # Update the class regular expressions because our language has changed.
### ($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
### $soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
### $enumname,
### $typedefname, $varname, $constname, $structisbrace, $macronameref,
### $classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
### $requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
### print STDERR "PROPNAME NOW $propname\n" if ($localDebug || $parseDebug || $classDebug);
my $localclasstype = $1;
if ($part =~ /^\@/) { $part =~ s/^\@//s; }
if (!(scalar(@braceStack)-$parserState->{initbsCount})) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
print STDERR "ITISACLASS\n" if ($localDebug);
if (!length($parserState->{sodclass})) {
print STDERR "GOOD.\n" if ($localDebug);
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [7]\n" if ($classDebug);
$pushParserStateAtBrace = 1;
if ($localclasstype =~ /\@interface/) {
$parserState->{inClass} = 2;
print STDERR "inClass -> 2 [8]\n" if ($classDebug);
$pushParserStateAtBrace = 0;
} elsif ($localclasstype =~ /\@protocol/) {
$pushParserStateAtBrace = 0;
$pushParserStateAfterWordToken = 0;
$parserState->{inClass} = 0;
print STDERR "inClass -> 0 [9]\n" if ($classDebug);
$parserState->{inProtocol} = 1;
} elsif ($localclasstype =~ /\@implementation/) {
$pushParserStateAtBrace = 0;
$pushParserStateAfterWordToken = 2;
}
$parserState->{sodclass} = "class";
$parserState->{classtype} = $localclasstype;
$parserState->{preclasssodtype} = $parserState->{sodtype} . $part;
$parserState->{sodtype} = "";
$parserState->{startOfDec} = 1;
$parserState->{onlyComments} = 0;
print STDERR "[m]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
# Get the parse tokens from Utilities.pm.
if (length($classbraceregexp) && ($localclasstype =~ /$classbraceregexp/)) {
print STDERR "CLASS ($localclasstype) IS A BRACE.\n" if ($localDebug);
push(@braceStack, $localclasstype); pbs(@braceStack);
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [17]\n"; }
# } else {
# print STDERR "CBRE: \"$classbraceregexp\"\n";
}
($lang, $sublang) = getLangAndSublangFromClassType($localclasstype);
$HeaderDoc::lang = $lang;
$HeaderDoc::sublang = $sublang;
($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
$soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
$enumname,
$typedefname, $varname, $constname, $structisbrace, $macronameref,
$classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
$requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
my $macrore = macroRegexpFromList($macronameref);
# print STDERR "PROPNAME2: $propname\n";
print STDERR "ARP: $accessregexp\n" if ($localDebug);
last SWITCH;
}
}
}
};
($part eq $objcdynamicname) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $objcsynthesizename) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $propname) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $structname || $part eq $enumname || $part eq $unionname) && do {
print STDERR "STRUCT/ENUM/UNION: CASE 36\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($structisbrace) {
if ($parserState->{sodclass} eq "function") {
$parserState->{seenBraces} = 1;
if (!$parserState->{stackFrozen}) {
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
@{$parserState->{pplStack}} = ();
}
$parserState->{posstypesPending} = 0;
$parserState->{callbackNamePending} = -1;
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "callbackNamePending -> -1\n" if ($localDebug || $cbnDebug);
print STDERR "lbrace\n" if ($localDebug);
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [18]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
} else {
if (!$parserState->{simpleTypedef}) {
print STDERR "simpleTypedef -> 2\n" if ($localDebug);
$parserState->{simpleTypedef} = 2;
}
# if (!$parserState->{seenBraces}) { # TREEDONE
# $treePopTwo++;
# $treeNest = 1;
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
# }
}
$parserState->{onlyComments} = 0;
print STDERR "[n]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
# $parserState->{simpleTypedef} = 0;
if ($parserState->{basetype} eq "") { $parserState->{basetype} = $part; }
# fall through to default case when we're done.
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString} || $parserState->{inChar})) {
$parserState->{namePending} = 2;
print STDERR "namePending -> 2 [2]\n" if ($parseDebug);
if ($parserState->{posstypesPending}) { $parserState->{posstypes} .=" $part"; }
}
if ($parserState->{sodclass} eq "") {
$parserState->{startOfDec} = 0; $parserState->{sodname} = "";
print STDERR "sodname cleared (seu)\n" if ($sodDebug);
}
$lastchar = $part;
}; # end if
}; # end do
($part =~ /^$typedefname$/) && do {
print STDERR "TYPEDEF: CASE 37\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (!(scalar(@braceStack)-$parserState->{initbsCount})) { $parserState->{callbackIsTypedef} = 1; $parserState->{inTypedef} = 1; }
$parserState->{onlyComments} = 0;
print STDERR "[o]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
$parserState->{simpleTypedef} = 1; print STDERR "simpleTypedef -> 1\n" if ($localDebug);
# previous case falls through, so be explicit.
if ($part =~ /^$typedefname$/) {
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString} || $parserState->{inChar})) {
if ($pascal) {
$parserState->{namePending} = 2;
$inPType = 1;
print STDERR "namePending -> 2 [3]\n" if ($parseDebug);
}
if ($parserState->{posstypesPending}) { $parserState->{posstypes} .=" $part"; }
if (!($parserState->{callbackNamePending})) {
print STDERR "callbackNamePending -> 1\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 1;
}
}
}
if ($parserState->{sodclass} eq "") {
$parserState->{startOfDec} = 0; $parserState->{sodname} = "";
print STDERR "sodname cleared ($typedefname)\n" if ($sodDebug);
}
$lastchar = $part;
}; # end if
}; # end do
# C++ operator keyword handler
($part eq "$operator") && do {
print STDERR "OPERATOR KEYWORD: CASE 38\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{inOperator} = 1;
$parserState->{sodname} = "";
}
$parserState->{lastsymbol} = $part;
$lastchar = $part;
last SWITCH;
# next;
};
# Punctuation handlers
($part =~ /;/o) && do {
print STDERR "SEMICOLON: CASE 39\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parsedParamParse) {
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) { push(@{$parserState->{parsedParamList}}, $parsedParam); }
print STDERR "pushed $parsedParam into parsedParamList [2semi]\n" if ($parmDebug);
$parsedParam = "";
}
# skip this token
$parsedParamParse = 2;
$parserState->{freezereturn} = 1;
# $parserState->{onlyComments} = 0; # If this is all we've seen, there's either a bug or we're
# unrolling a class or similar anyway.
$parserState->{temponlyComments} = $parserState->{onlyComments};
print STDERR "[p]onlyComments -> 0\n" if ($macroDebug);
print STDERR "valuepending -> 0\n" if ($valueDebug);
$parserState->{valuepending} = 0;
$continuation = 1;
if ($parserState->{occmethod}) {
$prespaceadjust = -$prespace;
}
# previous case falls through, so be explicit.
if ($part =~ /;/o && !$parserState->{inMacroLine} && !$parserState->{inMacro}) {
my $bsCount = scalar(@braceStack)-$parserState->{initbsCount};
if (!$bsCount && !$parserState->{kr_c_function}) {
if ($parserState->{startOfDec} == 2) {
$parserState->{sodclass} = "constant";
$parserState->{startOfDec} = 1;
} elsif (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{startOfDec} = 1;
}
# $parserState->{lastsymbol} .= $part;
}
if (!$bsCount) {
$treeCur = $treeCur->addSibling(";"); $treepart = " "; # $treeSkip = 1;
if (0) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [8]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
# $parserState->{lastTreeNode} = $treeCur;
# print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n";
while ($parserState->{treePopTwo}--) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [9]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
$parserState->{treePopTwo} = 0;
}
}
$lastchar = $part;
}; # end if
}; # end do
($part eq "=" && ($parserState->{lastsymbol} ne "operator") && (!(($parserState->{inOperator} == 1) && $parserState->{lastsymbol} =~ /\W/ && $parserState->{lastsymbol} =~ /\S/)) && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "EQUALS: CASE 40\n" if ($liteDebug);
$parserState->{onlyComments} = 0;
print STDERR "[q]onlyComments -> 0\n" if ($macroDebug);
if ($part =~ /=/o && !(scalar(@braceStack)-$parserState->{initbsCount}) &&
$nextpart !~ /=/o && $lastchar !~ /=/o &&
$parserState->{sodclass} ne "function" && !$inPType) {
print STDERR "valuepending -> 1\n" if ($valueDebug);
$parserState->{valuepending} = 1;
$parserState->{preEqualsSymbol} = $parserState->{lastsymbol};
$parserState->{sodclass} = "constant";
$parserState->{startOfDec} = 0;
}; # end if
}; # end do
($part =~ /,/o) && do {
print STDERR "COMMA: CASE 41\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{onlyComments} = 0;
print STDERR "[r]onlyComments -> 0\n" if ($macroDebug);
}
if ($part =~ /,/o && $parsedParamParse && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && ((scalar(@braceStack)-$parserState->{initbsCount}-$parserState->{functionReturnsCallback}) == 1) && (peek(\@braceStack) eq '(' || peek(\@braceStack) eq '{')) {
print STDERR "$part is a comma\n" if ($localDebug || $parseDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) { push(@{$parserState->{parsedParamList}}, $parsedParam); }
print STDERR "pushed $parsedParam into parsedParamList [2]\n" if ($parmDebug);
$parsedParam = "";
# skip this token
$parsedParamParse = 2;
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
}; # end if
}; # end do
($part =~ /[*^]/) && do {
if ($lastnspart eq "(" && # ")"
!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) &&
!$parserState->{callbackNamePending} &&
((scalar(@braceStack)-$parserState->{initbsCount}) == 1)) {
# print "CBNP\n";
$parserState->{callbackNamePending} = 3;
}
# Fall through to the default case.
}; # end star/asterisk/caret case
{ # SWITCH default case
print STDERR "DEFAULT CASE: CASE 42\n" if ($liteDebug);
# Handler for all other text (data types, string contents,
# comment contents, character contents, etc.)
print STDERR "DEFAULT CASE\n" if ($localDebug || $parseDebug);
# print STDERR "TEST CURLINE IS \"$curline\".\n";
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (!ignore($part, $ignoreref, $perheaderignoreref)) {
if ($part =~ /\S/o) {
$parserState->{onlyComments} = 0;
print STDERR "[s]onlyComments -> 0\n" if ($macroDebug);
}
if (!$continuation && !$occspace) {
$curline = spacefix($curline, $part, $lastchar);
} else {
$continuation = 0;
$occspace = 0;
}
# print STDERR "BAD CURLINE IS \"$curline\".\n";
if (length($part) && !($parserState->{inComment} || $parserState->{inInlineComment})) {
if ($localDebug && $lastchar eq ")") {print STDERR "LC: $lastchar\nPART: $part\n";}
# print STDERR "XXX LC: $lastchar SC: $parserState->{sodclass} LG: $lang\n";
if ($lastchar eq ")" && $parserState->{sodclass} eq "function" && ($lang eq "C" || $lang eq "Csource") && !(scalar(@braceStack)-$parserState->{initbsCount})) {
if ($part !~ /^\s*;/o) {
# warn "K&R C FUNCTION FOUND.\n";
# warn "NAME: $parserState->{sodname}\n";
if (!isKeyword($part, $keywordhashref, $case_sensitive)) {
my $tempavail = ignore($part, $ignoreref, $perheaderignoreref);
if (!$tempavail) {
print STDERR "K&R C FUNCTION FOUND [2].\n" if ($localDebug);
print STDERR "TOKEN: \"$part\"\n" if ($localDebug);
print STDERR "TA: \"$tempavail\"\n" if ($localDebug);
$parserState->{kr_c_function} = 1;
$parserState->{kr_c_name} = $parserState->{sodname};
$parsedParamParse = 1;
print STDERR "parsedParamParse -> 1\n" if ($parmDebug);
}
}
}
}
$lastchar = $part;
if ($part =~ /\w/o || $part eq "::") {
if ($parserState->{callbackNamePending} == 1) {
if (!($part eq $structname || $part eq $enumname || $part eq $unionname || $part eq $typedefname)) {
# we've seen the initial type. The name of
# the callback is after the next open
# parenthesis.
print STDERR "callbackNamePending -> 2\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 2;
}
} elsif ($parserState->{callbackNamePending} == 3) {
print STDERR "callbackNamePending -> 4\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 4;
$parserState->{callbackName} = $part;
$parserState->{name} = "";
$parserState->{sodclass} = "";
$parserState->{cbsodname} = $parserState->{sodname};
$parserState->{sodname} = "";
} elsif ($parserState->{callbackNamePending} == 4) {
if ($part eq "::") {
print STDERR "callbackNamePending -> 5\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 5;
$parserState->{callbackName} .= $part;
} elsif ($part !~ /\s/o) {
print STDERR "callbackNamePending -> 0\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 0;
}
} elsif ($parserState->{callbackNamePending} == 5) {
if ($part !~ /\s/o) {
print STDERR "callbackNamePending -> 4\n" if ($localDebug || $cbnDebug);
if ($part !~ /\*/ && $part !~ /\^/) {
$parserState->{callbackNamePending} = 4;
}
$parserState->{callbackName} .= $part;
}
}
if ($parserState->{namePending} == 2) {
$parserState->{namePending} = 1;
print STDERR "namePending -> 1 [4]\n" if ($parseDebug);
if (!(scalar(@braceStack)-$parserState->{initbsCount}) && ($parserState->{simpleTypedef} == 2)) {
print STDERR "bracePending -> 1\n" if ($localDebug);
$parserState->{bracePending} = 1;
}
} elsif ($parserState->{namePending}) {
if ($parserState->{name} eq "") { $parserState->{name} = $part; }
$parserState->{namePending} = 0;
print STDERR "namePending -> 0 [5]\n" if ($parseDebug);
} elsif ($parserState->{bracePending} == 1) {
if ($part eq "::") {
# struct foo::bar ....
# "foo::bar" is the name of
# the struct and should not
# trigger this (though we might
# trigger it on the following
# word.
print STDERR "bracePending -> 2 [classmember]\n" if ($localDebug);
$parserState->{bracePending} = 2;
} else {
# Word token when brace pending. It's
# a variable.
print STDERR "IT'S A VARIABLE! NAME WAS \"$part\".\n" if ($localDebug);
print STDERR "Word token before brace. Setting sodname to ".$parserState->{lastsymbol}."\n" if ($localDebug || $sodDebug);
$parserState->{sodname} = $part;
# $parserState->{sodtype} = $parserState->{returntype}; # . " " . $parserState->{name};
$parserState->{sodtype} = "$declaration$curline";
$parserState->{sodclass} = "constant";
$parserState->{frozensodname} = $part;
print STDERR "bracePending -> 0 [word]\n" if ($localDebug);
$parserState->{bracePending} = 0;
}
} elsif ($parserState->{bracePending} == 2) {
$parserState->{bracePending}--;
}
} # end if ($part =~ /\w/o)
if ($part !~ /[,;\[\]]/o && !$parserState->{inBrackets}) {
my $opttilde = "";
if ($parserState->{seenTilde}) { $opttilde = "~"; }
print STDERR "CHECKPOINT: INTEMPLATE IS ".$parserState->{inTemplate}." SOD IS ".$parserState->{startOfDec}."\n" if ($localDebug || $sodDebug);
if ($parserState->{startOfDec} == 1) { # @@@ FIXME DAG. This should not set sodname, but otherwise, we're losing classes!!!
if (!$parserState->{inTemplate}) {
print STDERR "Setting sodname (maybe type) to \"$part\"\n" if ($sodDebug);
$parserState->{sodname} = $opttilde.$part;
if ($part =~ /\w/o) {
$parserState->{startOfDec}++;
}
} else {
print STDERR "Not adjusting startOfDec or sodname because in template.\n" if ($localDebug || $sodDebug);
}
} elsif ($parserState->{startOfDec} == 2) {
if ($part =~ /\w/o && !$parserState->{inTemplate}) {
$parserState->{preTemplateSymbol} = "";
}
if (!$parserState->{inTemplate}) {
if ($parserState->{inOperator} == 1) {
$parserState->{sodname} .= $part;
} else {
if (length($parserState->{sodname})) {
$parserState->{sodtype} .= " $parserState->{sodname}";
}
$parserState->{sodname} = $opttilde.$part;
}
print STDERR "sodname set to $part\n" if ($sodDebug);
} else {
print STDERR "Not adjusting startOfDec or sodname because in template.\n" if ($localDebug || $sodDebug);
}
} else {
$parserState->{startOfDec} = 0;
}
} elsif ($part eq "[") { # if ($part !~ /[;\[\]]/o)
$parserState->{inBrackets} += 1;
print STDERR "inBrackets -> $parserState->{inBrackets}\n" if ($sodDebug);
} elsif ($part eq "]") {
$parserState->{inBrackets} -= 1;
print STDERR "inBrackets -> $parserState->{inBrackets}\n" if ($sodDebug);
} # end if ($part !~ /[;\[\]]/o)
if (!($part eq $eoc)) {
print STDERR "SETTING LS ($part)\n" if ($parseDebug);
if ($parserState->{typestring} eq "") { $parserState->{typestring} = $part; }
if ($parserState->{lastsymbol} =~ /\,\s*$/o) {
$parserState->{lastsymbol} .= $part;
} elsif ($parserState->{inTypedef} && !(scalar(@braceStack)-$parserState->{initbsCount}) && $part =~ /,/) {
$parserState->{lastsymbol} .= $part;
} elsif ($part =~ /^\s*\;\s*$/o) {
$parserState->{lastsymbol} .= $part;
} elsif (length($part)) {
# warn("replacing lastsymbol with \"$part\"\n");
$parserState->{lastsymbol} = $part;
}
} # end if (!($part eq $eoc))
} # end if (length($part) && !($parserState->{inComment} || $parserState->{inInlineComment}))
}
} # end if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}))
} # end SWITCH default case
} # end SWITCH
if ($parserState->{seenBraces}) {
# print "SEENBRACES. TP: $treepart PT: $part\n";
if ($treepart) {
$parserState->{functionContents} .= $treepart;
} else {
$parserState->{functionContents} .= $part;
}
# print "SEENBRACES. FC: ".$parserState->{functionContents}."\n";
}
if ($part !~ /\\/o) {
if (!($parserState->{inMacro} || $parserState->{inMacroLine}) || $part !~ /\s/) {
$parserState->resetBackslash();
}
}
if (length($part)) { $lasttoken = $part; }
if (length($part) && $inRegexpTrailer) { --$inRegexpTrailer; }
if ($postPossNL) { --$postPossNL; }
if (($parserState->{simpleTypedef} == 1) && ($part ne $typedefname) &&
!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} ||
$inRegexp)) {
# print STDERR "NP: $parserState->{namePending} PTP: $parserState->{posstypesPending} PART: $part\n";
$parserState->{simpleTDcontents} .= $part;
}
my $ignoretoken = ignore($part, $ignoreref, $perheaderignoreref);
my $hide = ( $hideTokenAndMaybeContents ||
( $ignoretoken &&
!( $parserState->{inString} || $parserState->{inComment} ||
$parserState->{inInlineComment} || $parserState->{inChar}
)
)
);
print STDERR "TPONL: $treePopOnNewLine TPTWO: ".$parserState->{treePopTwo}."\n" if ($tsDebug);
print STDERR "TN: $treeNest TS: $treeSkip nTS: ".scalar(@treeStack)."\n" if ($tsDebug || $parserStateInsertDebug);
print STDERR "sethollow: $sethollow\n" if ($parserStateInsertDebug);
if (!$treeSkip) {
if (!$parserState->{seenBraces}) { # TREEDONE
if ($treeNest != 2) {
# If we really want to skip and nest, set treeNest to 2.
if (length($treepart)) {
if ((($parserState->{inComment} == 1) || ($parserState->{inInlineComment} == 1)) && $treepart !~ /[\r\n!]/) {
$treeCur->token($treeCur->token() . $treepart);
# print STDERR "SHORT\n";
} else {
$treeCur = $treeCur->addSibling($treepart, $hide);
}
$treepart = "";
} else {
if ((($parserState->{inComment} == 1) || ($parserState->{inInlineComment} == 1)) && $treepart !~ /[\r\n!]/) {
$treeCur->token($treeCur->token() . $part);
# print STDERR "SHORT\n";
} else {
$treeCur = $treeCur->addSibling($part, $hide);
}
}
bless($treeCur, "HeaderDoc::ParseTree");
}
# print STDERR "TC IS $treeCur\n";
# $treeCur = %{$treeCur};
if ($treeNest) {
if ($sethollow) {
print STDERR "WILL INSERT STATE $parserState (SETHOLLOW) at ".$treeCur->token()."\n" if ($parserStackDebug);
# $parserState->{hollow} = $treeCur;
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$sethollow = 0;
}
print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug);
push(@treeStack, $treeCur);
$treeCur = $treeCur->addChild("", 0);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
}
if ($parserState->{inComment} > 1) { $parserState->{inComment}--; }
if ($parserState->{inInlineComment} > 1) { $parserState->{inInlineComment}--; }
if (($parserState->{inComment} == 1) && $treepart eq "!") {
$parserState->{inComment} = 3;
}
if (($parserState->{inInlineComment} == 1) && $treepart eq "!") {
$parserState->{inInlineComment} = 3;
}
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [19]\n"; }
if (!$parserState->{freezereturn} && $parserState->{hollow}) {
# print STDERR "WARNING: RETURN TYPE CHANGE[A]".$parserState->{returntype}." CHANGED TO $declaration$curline.\n";
$parserState->{returntype} = "$declaration$curline";
} elsif (!$parserState->{freezereturn} && !$parserState->{hollow}) {
# print STDERR "WARNING: RETURN TYPE CHANGE[B]".$parserState->{returntype}." CHANGED TO $curline.\n";
$parserState->{returntype} = "$curline";
$declaration = "";
# } else {
# print STDERR "WARNING: LEAVING RETURN TYPE ALONE: ".$parserState->{returntype}." NOT CHANGED TO $curline.\n";
}
# From here down is... magic. This is where we figure out how
# to handle parsed parameters, K&R C types, and in general,
# determine whether we've received a complete declaration or not.
#
# About 90% of this is legacy code to handle proper spacing.
# Those bits got effectively replaced by the parseTree class.
# The only way you ever see this output is if you don't have
# any styles defined in your config file.
if (($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) ||
!$ignoretoken) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) &&
!$ppSkipOneToken) {
if ($parsedParamParse == 1) {
$parsedParam .= $part;
} elsif ($parsedParamParse == 2) {
$parsedParamParse = 1;
print STDERR "parsedParamParse -> 1\n" if ($parmDebug);
}
}
if ($ppSkipOneToken) {
$hollowskip = $ppSkipOneToken;
print STDERR "hollowskip -> $ppSkipOneToken (ppSkipOneToken)\n" if ($parserStateInsertDebug);
}
$ppSkipOneToken = 0;
print STDERR "MIDPOINT CL: $curline\nDEC:$declaration\nSCR: \"$scratch\"\n" if ($localDebug);
if (!$parserState->{seenBraces}) {
# Add to current line (but don't put inline function/macro
# declarations in.
if ($parserState->{inString}) {
$curstring .= $part;
} else {
if (length($curstring)) {
if (length($curline) + length($curstring) >
$HeaderDoc::maxDecLen) {
$scratch = nspaces($prespace);
# Was != /\n/ which is clearly
# wrong. Suspect the next line
# if we start losing leading spaces
# where we shouldn't (or don't where
# we should). Also was just /g.
if ($curline !~ /^\s*\n/so) { $curline =~ s/^\s*//sgo; }
# NEWLINE INSERT
print STDERR "CURLINE CLEAR [1]\n" if ($localDebug);
$declaration .= "$scratch$curline\n";
$curline = "";
$prespace += $prespaceadjust;
$prespaceadjust = 0;
$prespaceadjust -= 4;
$prespace += 4;
} else {
# no wrap, so maybe add a space.
if ($lastchar =~ /\=$/o) {
$curline .= " ";
}
}
$curline .= $curstring;
$curstring = "";
}
if ((length($curline) + length($part) > $HeaderDoc::maxDecLen)) {
$scratch = nspaces($prespace);
# Was != /\n/ which is clearly
# wrong. Suspect the next line
# if we start losing leading spaces
# where we shouldn't (or don't where
# we should). Also was /g instead of /sg.
if ($curline !~ /^\s*\n/so) { $curline =~ s/^\s*//sgo; }
# NEWLINE INSERT
$declaration .= "$scratch$curline\n";
print STDERR "CURLINE CLEAR [2]\n" if ($localDebug);
$curline = "";
$prespace += $prespaceadjust;
$prespaceadjust = 0;
$prespaceadjust -= 4;
$prespace += 4;
}
if (length($curline) || $part ne " ") {
# Add it to curline unless it's a space that
# has inadvertently been wrapped to the
# start of a line.
$curline .= $part;
}
}
if (peek(\@braceStack) ne "<") {
if ($part =~ /\n/o || ($part =~ /[\(;,]/o && $nextpart !~ /\n/o &&
!$parserState->{occmethod}) ||
($part =~ /[:;.]/o && $nextpart !~ /\n/o &&
$parserState->{occmethod})) {
if ($curline !~ /\n/o && !($parserState->{inMacro} || ($pascal && (scalar(@braceStack)-$parserState->{initbsCount})) || $parserState->{inInlineComment} || $parserState->{inComment} || $parserState->{inString})) {
# NEWLINE INSERT
$curline .= "\n";
}
# Add the current line to the declaration.
$scratch = nspaces($prespace);
if ($curline !~ /\n/o) { $curline =~ s/^\s*//go; }
if ($declaration !~ /\n\s*$/o) {
$scratch = " ";
if ($localDebug) {
my $zDec = $declaration;
$zDec = s/ /z/sg;
$zDec = s/\t/Z/sg;
print STDERR "ZEROSCRATCH\n";
print STDERR "zDec: \"$zDec\"\n";
}
}
$declaration .= "$scratch$curline";
print STDERR "CURLINE CLEAR [3]\n" if ($localDebug);
$curline = "";
# $curline = nspaces($prespace);
print STDERR "PS: $prespace -> " . $prespace + $prespaceadjust . "\n" if ($localDebug);
$prespace += $prespaceadjust;
$prespaceadjust = 0;
} elsif ($part =~ /[\(;,]/o && $nextpart !~ /\n/o &&
($parserState->{occmethod} == 1)) {
print STDERR "SPC\n" if ($localDebug);
$curline .= " "; $occspace = 1;
} else {
print STDERR "NOSPC: $part:$nextpart:$parserState->{occmethod}\n" if ($localDebug);
}
}
}
if ($parserState->{temponlyComments}) {
# print STDERR "GOT TOC: ".$parserState->{temponlyComments}."\n";
$parserState->{onlyComments} = $parserState->{temponlyComments};
$parserState->{temponlyComments} = undef;
}
print STDERR "CURLINE IS \"$curline\".\n" if ($localDebug);
my $bsCount = scalar(@braceStack);
print STDERR "ENDTEST: $bsCount \"$parserState->{lastsymbol}\"\n" if ($localDebug);
print STDERR "KRC: $parserState->{kr_c_function} SB: $parserState->{seenBraces}\n" if ($localDebug);
if (!($bsCount - $parserState->{initbsCount}) && $parserState->{lastsymbol} =~ /;\s*$/o) {
# print STDERR "DPA\n";
if ((!$parserState->{kr_c_function} || $parserState->{seenBraces}) && !$parserState->{inMacro}) {
# print STDERR "DPB\n";
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [3]\n" if ($localDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[SEMI-1]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} elsif ($parserState->{classtype} && length($parserState->{classtype})) {
warn "Couldn't insert info into parse tree[3class].\n" if ($localDebug);
} else {
warn "Couldn't insert info into parse tree[3].\n";
print STDERR "Printing tree.\n";
$parserState->print();
$treeTop->dbprint();
}
print STDERR "parserState: Created parser state[2].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "NEWRETURNTYPE: $parserState->{returntype}\n" if ($localDebug);
print STDERR "CURLINE CLEAR[PRS2]\n" if ($localDebug);
$curline = "";
}
}
} else {
print STDERR "bsCount: $bsCount - $parserState->{initbsCount}, ls: $parserState->{lastsymbol}\n" if ($localDebug);
pbs(@braceStack);
}
if (!($bsCount - $parserState->{initbsCount}) && $parserState->{seenBraces} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator}) &&
($nextpart ne ";")) {
# Function declarations end at the close curly brace.
# No ';' necessary (though we'll eat it if it's there.
if ($parserState->{treePopTwo}) {
# Fix nesting.
# print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n";
while ($parserState->{treePopTwo}--) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [13]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
$treeCur = $treeCur->addSibling(";", 0);
$parserState->{lastTreeNode} = $treeCur;
$parserState->{treePopTwo} = 0;
}
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [4]\n" if ($localDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[SEMI-2]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[4].\n";
}
print STDERR "parserState: Created parser state[3].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "CURLINE CLEAR[PRS3]\n" if ($localDebug);
$curline = "";
}
}
print STDERR "INMACRO: ".$parserState->{inMacro}."\n" if ($localDebug || $cppDebug || $cppDebug);
# $parserState->{lastsymbol} ne "\\"
print STDERR "IM: ".$parserState->{inMacro}." IQ: ".$parserState->isQuoted($lang, $sublang)."\n" if ($localDebug);
if (($parserState->{inMacro} == 3 && !$parserState->isQuoted($lang, $sublang)) || $parserState->{inMacro} == 4) {
print STDERR "CHECKPART AGAINST NEWLINE\n" if ($localDebug || $cppDebug);
if ($part =~ /[\n\r]/o && !$parserState->{inComment}) {
print STDERR "MLS: $parserState->{lastsymbol}\n" if ($macroDebug);
print STDERR "PARSER STACK CONTAINS ".scalar(@parserStack)." FRAMES\n" if ($cppDebug || $parserStackDebug);
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [5]\n" if ($localDebug || $liteDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
print STDERR "NOT setting continue to 0 for macro: parser stack nonempty\n" if ($liteDebug);
print STDERR "DONE WITH MACRO. HANDLING.\n" if ($localDebug || $parseDebug);
if ($parserState->{inMacro} == 3) {
if (!$HeaderDoc::skipNextPDefine) {
cpp_add($parserState->{hollow});
} else {
cpp_add($parserState->{hollow}, 1);
$HeaderDoc::skipNextPDefine = 0;
}
}
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[5].\n";
}
print STDERR "parserState: Created parser state[4].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "CURLINE CLEAR[PRS4]\n" if ($localDebug);
$curline = "";
}
}
} elsif ($parserState->{inMacro} == 2) {
my $linenum = $inputCounter + $fileoffset;
warn "$filename:$linenum: warning: Declaration starts with # but is not preprocessor macro\n";
warn "PART: $part\n";
} elsif ($parserState->{inMacro} == 3 && $parserState->isQuoted($lang, $sublang)) {
# $parserState->{lastsymbol} eq "\\"
print STDERR "TAIL BACKSLASH ($continue)\n" if ($localDebug || $macroDebug);
}
if ($parserState->{valuepending} == 2) {
# skip the "=" part;
$parserState->{value} .= $part;
} elsif ($parserState->{valuepending}) {
$parserState->{valuepending} = 2;
print STDERR "valuepending -> 2\n" if ($valueDebug);
}
} # end if "we're not ignoring this token"
print STDERR "OOGABOOGA\n" if ($parserStackDebug);
if ($pushParserStateAfterToken == 1) {
print STDERR "parserState pushed onto stack[token]\n" if ($parserStackDebug);
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterToken = 0;
$pushParserStateAtBrace = 0;
} elsif ($pushParserStateAfterWordToken == 1) {
if ($part =~ /\w/) {
print STDERR "parserState pushed onto stack[word]\n" if ($parserStackDebug);
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterWordToken = 0;
}
} elsif ($pushParserStateAfterWordToken) {
print STDERR "PPSAFTERWT CHANGED $pushParserStateAfterWordToken -> " if ($parserStackDebug);
$pushParserStateAfterWordToken--;
print STDERR "$pushParserStateAfterWordToken\n" if ($parserStackDebug);
} elsif ($pushParserStateAtBrace) {
print STDERR "PPSatBrace?\n" if ($parserStackDebug);
if (casecmp($part, $lbrace, $case_sensitive)) {
$parserState->{ISFORWARDDECLARATION} = 0;
print STDERR "parserState pushed onto stack[brace]\n" if ($parserStackDebug);
# if ($pushParserStateAtBrace == 2) {
# print STDERR "NOINSERT parserState: $parserState\n" if ($parserStackDebug);
# $parserState->{hollow} = undef;
# $parserState->{noInsert} = 1;
# }
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
} elsif ($pushParserStateAtBrace) {
if ($part =~ /\;/) {
# It's a class instance declaration. Whoops.
$pushParserStateAtBrace = 0;
$parserState->{inClass} = 0;
print STDERR "inClass -> 0 [10]\n" if ($classDebug);
}
# if ($part =~ /\S/) { $pushParserStateAtBrace = 0; }
}
if (!$parserState->{hollow}) {
my $tok = $part; # $treeCur->token();
print STDERR "parserState: NOT HOLLOW [1]\n" if ($parserStackDebug);
print STDERR "IS: $parserState->{inString}\nICom: $parserState->{inComment}\nISLC: $parserState->{inInlineComment}\nIChar: $parserState->{inChar}\nSkipToken: $parserState->{skiptoken}\nHollowSkip: $hollowskip\n" if ($parserStackDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
print STDERR "parserState: NOT STRING/CHAR/COMMENT\n" if ($parserStackDebug);
if ($tok =~ /\S/) {
print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug);
print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug);
if (!casecmp($tok, $rbrace, $case_sensitive) && $part !~ /\)/) {
# $parserState->{hollow} = $treeCur;
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$HeaderDoc::curParserState = $parserState;
print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-1) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug);
}
}
}
$hollowskip = 0;
print STDERR "hollowskip -> 0 (NOTHOLLOW - 1)\n" if ($parserStateInsertDebug);
$parserState->{skiptoken} = 0;
}
} else {
if (!$parserState->{hollow}) {
my $tok = $part; # $treeCur->token();
print STDERR "parserState: NOT HOLLOW [2]\n" if ($parserStackDebug);
print STDERR "IS: $parserState->{inString}\nICom: $parserState->{inComment}\nISLC: $parserState->{inInlineComment}\nIChar: $parserState->{inChar}\nSkipToken: $parserState->{skiptoken}\nHollowSkip: $hollowskip\n" if ($parserStackDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
print STDERR "parserState: NOT STRING/CHAR/COMMENT\n" if ($parserStackDebug);
if ($tok =~ /\S/) {
print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug);
print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug);
if (!casecmp($tok, $rbrace, $case_sensitive) && $part !~ /\)/) {
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$HeaderDoc::curParserState = $parserState;
print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-2) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug);
}
}
}
$hollowskip = 0;
print STDERR "hollowskip -> 0 (NOTHOLLOW - 2)\n" if ($parserStateInsertDebug);
$parserState->{skiptoken} = 0;
}
}
if ($part =~ /\w+/) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
if ($parserState->{occparmlabelfound} == -2) {
if (!($parserState->{initbsCount} - scalar(@braceStack) )) { # Skip types
$parserState->{occparmlabelfound} = 0; # Next token is the label for the next parameter.
if ($HeaderDoc::useParmNameForUnlabeledParms) {
$parserState->{occmethodname} .= "$part:";
} else {
$parserState->{occmethodname} .= ":";
}
if ($occMethodNameDebug) {
print STDERR "OCC parameter name substituted; OCC method name now ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\", part was \"".$part."\").\n";
}
}
} else {
if (!($parserState->{initbsCount} - scalar(@braceStack) )) { # Skip types
$parserState->{occparmlabelfound}++;
if ($occMethodNameDebug && ($parserState->{occparmlabelfound} > 0)) {
print STDERR "OCC possible label: \"$part\".\n";
}
}
}
}
}
if (length($part) && $part =~ /\S/o) { $lastnspart = $part; }
if ($parserState->{seenTilde} && length($part) && $part !~ /\s/o) { $parserState->{seenTilde}--; }
$part = $nextpart;
} # end foreach (parts of the current line)
} # end while (continue && ...)
print STDERR "RETURNING DECLARATION\n" if ($localDebug);
# Format and insert curline into the declaration. This handles the
# trailing line. (Deprecated.)
if ($curline !~ /\n/) { $curline =~ s/^\s*//go; }
if ($curline =~ /\S/o) {
$scratch = nspaces($prespace);
$declaration .= "$scratch$curline\n";
}
print STDERR "($parserState->{typestring}, $parserState->{basetype})\n" if ($localDebug || $listDebug);
print STDERR "LS: $parserState->{lastsymbol}\n" if ($localDebug);
$parserState->{lastTreeNode} = $treeCur;
$parserState->{inputCounter} = $inputCounter;
print STDERR "PARSERSTATE: $parserState\n" if ($localDebug);
if ($parserState->{inMacro} == 3) {
if (!$HeaderDoc::skipNextPDefine) {
cpp_add($treeTop);
} else {
cpp_add($treeTop, 1);
$HeaderDoc::skipNextPDefine = 0;
}
}
print STDERR "LEFTBPMAIN\n" if ($localDebug || $hangDebug);
if ($argparse && $apwarn) {
print STDERR "end argparse\n";
}
# Return the top parser context even if we got interrupted.
my $tempParserState = pop(@parserStack);
while ($tempParserState) {
$parserState = $tempParserState;
$tempParserState = pop(@parserStack);
}
$HeaderDoc::module = $parserState->{MODULE};
if ($localDebug || $apDebug || $liteDebug || $parseDebug) {
print STDERR "LEAVING BLOCKPARSE\n";
}
if (0) {
print STDERR "Returning the following parse tree:\n";
$treeTop->dbprint();
print STDERR "End of parse tree.\n";
}
# print "FC: ".$parserState->{functionContents}."\n";
return blockParseReturnState($parserState, $treeTop, $argparse, $declaration, $inPrivateParamTypes, $publicDeclaration, $lastACS, $retDebug, $fileoffset, 0, $definename, $inputCounter);
}
$parserState->{functionReturnsCallback} => 0
$parserState->{hollow} => HeaderDoc::ParseTree=HASH(OBJID)
$parserState->{inBrackets} => 0
$parserState->{inChar} =>
$parserState->{inClass} => 0
$parserState->{inComment} => 0
$parserState->{inInlineComment} => 0
$parserState->{inMacro} => 0
$parserState->{inMacroLine} => 0
$parserState->{inOperator} => 0
$parserState->{inPrivateParamTypes} => 0
$parserState->{inString} => 0
$parserState->{inTemplate} => 0
$parserState->{initbsCount} => 0
$parserState->{inputCounter} => 3647
$parserState->{kr_c_function} => 0
$parserState->{kr_c_name} =>
$parserState->{lang} => perl
$parserState->{lastTreeNode} => HeaderDoc::ParseTree=HASH(OBJID)
$parserState->{lastsymbol} =>
$parserState->{macroNoTrunc} => 1
$parserState->{name} => blockParse
$parserState->{namePending} => 0
$parserState->{noInsert} => 0
$parserState->{occmethod} => 0
$parserState->{occmethodname} =>
$parserState->{occparmlabelfound} => 2
$parserState->{onlyComments} => 0
$parserState->{parsedParamAtBrace} => ARRAY(OBJID)
$parserState->{parsedParamList} => ARRAY(OBJID)
$parserState->{parsedParamParse} => 0
$parserState->{parsedParamStateAtBrace} => ARRAY(OBJID)
$parserState->{posstypes} =>
$parserState->{posstypesPending} => 0
$parserState->{pplStack} => ARRAY(OBJID)
$parserState->{preEqualsSymbol} =>
$parserState->{preTemplateSymbol} =>
$parserState->{prekeywordsodname} =>
$parserState->{prekeywordsodtype} =>
$parserState->{returntype} => sub blockParse
$parserState->{seenBraces} => 1
$parserState->{seenMacroPart} => 0
$parserState->{seenTilde} => 0
$parserState->{simpleTDcontents} =>
$parserState->{simpleTypedef} => 0
$parserState->{sodclass} => function
$parserState->{sodname} => blockParse
$parserState->{sodtype} =>
$parserState->{stackFrozen} => 1
$parserState->{startOfDec} => 0
$parserState->{sublang} => perl
$parserState->{temponlyComments} => 0
$parserState->{typestring} => function
$parserState->{value} =>
$parserState->{valuepending} => 0
-=: BLOCKPARSE RETURN VALUES :=-
newcount: 3647
typelist: function
namelist: blockParse
posstypes: function method
value:
returntype:
pridec:
simpleTDcontents:
bpavail:
blockOffset: 0
conformsToList:
functionContents: {
my $filename = shift;
my $fileoffset = shift;
my $inputLinesRef = shift;
my $inputCounter = shift;
my $argparse = shift;
my $ignoreref = shift;
my $perheaderignoreref = shift;
my $perheaderignorefuncmacrosref = shift;
my $keywordhashref = shift;
my $case_sensitive = shift;
my $apwarn = 0;
if ($argparse && $apwarn) {
print STDERR "argparse\n";
}
# Initialize stuff
my @inputLines = @{$inputLinesRef};
my $declaration = "";
my $publicDeclaration = "";
# $HeaderDoc::fileDebug = 1;
# Debugging switches
my $retDebug = 0;
my $localDebug = 0 || $HeaderDoc::fileDebug;
my $operatorDebug = 0;
my $listDebug = 0;
my $parseDebug = 0 || $HeaderDoc::fileDebug;
my $sodDebug = 0 || $HeaderDoc::fileDebug;
my $valueDebug = 0;
my $parmDebug = 0;
my $cbnDebug = 0;
my $macroDebug = 0;
my $apDebug = 0;
my $tsDebug = 0;
my $treeDebug = 0;
my $ilcDebug = 0;
my $regexpDebug = 0;
my $parserStackDebug = 0 || $HeaderDoc::fileDebug;
my $hangDebug = 0;
my $offsetDebug = 0;
my $classDebug = 0; # prints changes to inClass, etc.
my $gccAttributeDebug = 0; # also for availability macro argument handling.
my $occMethodNameDebug = 0;
my $moduleDebug = 0; # prints changes to INMODULE
my $liteDebug = 0 || $HeaderDoc::fileDebug; # Just prints the tokens.
my $parserStateInsertDebug = 0;
$cppDebug = $cppDebugDefault || $HeaderDoc::fileDebug;
# State variables (part 1 of 3)
# my $typestring = "";
my $continue = 1; # set low when we're done.
my $parsedParamParse = 0; # set high when current token is part of param.
# my @parsedParamList = (); # currently active parsed parameter list.
# my @pplStack = (); # stack of parsed parameter lists. Used to handle
# fields and parameters in nested callbacks/structs.
# my @freezeStack = (); # copy of pplStack when frozen.
# my $frozensodname = "";
# my $stackFrozen = 0; # set to prevent fake parsed params with inline funcs
my $lang = $HeaderDoc::lang;
my $perl_or_shell = 0;
my $sublang = $HeaderDoc::sublang;
my $callback_typedef_and_name_on_one_line = 1; # deprecated
# my $returntype = "";
# my $freezereturn = 0; # set to prevent fake return types with inline funcs
my $treeNest = 0; # 1: nest future content under this node.
# 2: used if you want to nest, but have already
# inserted the contents of the node.
my $sethollow = 0;
my $setNoInsert = 0;
my $treepart = ""; # There are some cases where you want to drop a token
# for formatting, but keep it in the parse tree.
# In that case, treepart contains the original token,
# while part generally contains a space.
# my $availability = ""; # holds availability string if we find an av macro.
# my $seenTilde = 0; # set to 1 for C++ destructor.
if ($argparse && $tsDebug) { $tsDebug = 0; }
# Configure the parse tree output.
my $treeTop = HeaderDoc::ParseTree->new(); # top of parse tree.
my $treeCur = $treeTop; # current position in parse tree
my $treeSkip = 0; # set to 1 if "part" should be dropped in tree.
# my $treePopTwo = 0; # set to 1 for tokens that nest, but have no
# explicit ending token ([+-:]).
my $treePopOnNewLine = 0; # set to 1 for single-line comments, macros.
my @treeStack = (); # stack of parse trees. Used for popping
# our way up the tree to simplify tree structure.
# Leak a node here so that every real node has a parent.
$treeCur = $treeCur->addChild("");
$treeTop = $treeCur;
my $lastACS = "";
# The argparse switch is a trigger....
if ($argparse && $apDebug) {
$localDebug = 1;
$retDebug = 1;
$listDebug = 1;
$parseDebug = 1;
$sodDebug = 1;
$valueDebug = 1;
$parmDebug = 1;
$cbnDebug = 1;
$macroDebug = 1;
# $apDebug = 1;
$tsDebug = 1;
$treeDebug = 1;
$ilcDebug = 1;
$regexpDebug = 1;
}
my $spaceDebug = 0;
if ($localDebug || $apDebug || $liteDebug || $parseDebug) {
print STDERR "ENTERED BLOCKPARSE\n";
}
my $disable_cpp = 0;
if ($argparse && ($localDebug || $apDebug || $liteDebug)) {
print STDERR "ARGPARSE MODE!\n";
print STDERR "IPC: $inputCounter\nNLINES: ".$#inputLines."\n";
cluck("Call backtrace\n");
}
print STDERR "INBP\n" if ($localDebug);
if ($argparse) {
# Avoid double-processing macro inclusions.
$disable_cpp = 1;
}
if ($lang ne "C" || $sublang eq "PHP") { # || $sublang eq "IDL")
$disable_cpp = 1;
}
print STDERR "INITIAL LANG: $lang INITIAL SUBLANG: $sublang\n" if ($localDebug);
# warn("in BlockParse\n");
# State variables (part 2 of 3)
my $parserState = HeaderDoc::ParserState->new();
# $parserState->{hollow} = $treeTop;
setHollowWithLineNumbers(\$parserState, $treeTop, $fileoffset, $inputCounter);
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = 0; # included for consistency....
my @parserStack = ();
# print STDERR "TEST: ";
# if (defined($parserState->{parsedParamList})) {
# print STDERR "defined\n"
# } else { print STDERR "undefined.\n"; }
# print STDERR "\n";
# my $inComment = 0;
# my $inInlineComment = 0;
# my $inString = 0;
# my $inChar = 0;
# my $inTemplate = 0;
my @braceStack = ();
# my $inOperator = 0;
my $inPrivateParamTypes = 0; # after a colon in a C++ function declaration.
# my $onlyComments = 1; # set to 0 to avoid switching to macro parse.
# mode after we have seen a code token.
# my $inMacro = 0;
# my $inMacroLine = 0; # for handling macros in middle of data types.
# my $seenMacroPart = 0; # used to control dropping of macro body.
# my $macroNoTrunc = 1; # used to avoid truncating body of macros
# that don't begin with parenthesis or brace.
# my $inBrackets = 0; # square brackets ([]).
my $inPType = 0; # in pascal types.
my $inRegexp = 0; # in perl regexp.
my $regexpNoInterpolate = 0; # Don't interpolate (e.g. tr)
my $inRegexpTrailer = 0; # in the cruft at the end of a regexp.
my $hollowskip = 0;
my $ppSkipOneToken = 0; # Comments are always dropped from parsed
# parameter lists. However, inComment goes
# to 0 on the end-of-comment character.
# This prevents the end-of-comment character
# itself from being added....
my $regexppattern = ""; # optional characters at start of regexp
my $singleregexppattern = ""; # members of regexppattern that take only
# one argument instead of two.
my $regexpcharpattern = ""; # legal chars to start a regexp.
my @regexpStack = (); # stack of RE tokens (since some can nest).
# Get the parse tokens from Utilities.pm.
my ($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
$soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
$enumname,
$typedefname, $varname, $constname, $structisbrace, $macronameref,
$classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
$requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
my $macrore_pound = macroRegexpFromList($macronameref, 1);
my $macrore_nopound = macroRegexpFromList($macronameref, 2);
# print STDERR "LANG: $lang SUBLANG: $sublang";
print STDERR "MACRORE_POUND: \"$macrore_pound\"\n" if ($localDebug || $parseDebug);
print STDERR "MACRORE_NOPOUND: \"$macrore_nopound\"\n" if ($localDebug || $parseDebug);
# print STDERR "INITIAL PROPNAME $propname\n";
if ($parseDebug) {
print STDERR "SOT: $sotemplate EOF: $eotemplate OP: $operator SOC: $soc EOC: $eoc ILC: $ilc ILC_B: $ilc_b\n";
print STDERR "SOFUNC: $sofunction SOPROC: $soprocedure SOPREPROC: $sopreproc LBRACE: $lbrace RBRACE: $rbrace\n";
print STDERR "UNION: $unionname STRUCT: $structname TYPEDEF: $typedefname VAR: $varname CONST: $constname\n";
print STDERR "STRUCTISBRACE: $structisbrace MACRONAMEREF: $macronameref CLASSRE: $classregexp\n";
print STDERR "CLASSBRACERE: $classbraceregexp CLASSCLOSEBRACERE: $classclosebraceregexp ACCESSRE: $accessregexp\n";
print STDERR "MODULERE: $moduleregexp\n";
}
# Set up regexp patterns for perl, variable for perl or shell.
if ($lang eq "perl" || $lang eq "shell") {
$perl_or_shell = 1;
if ($lang eq "perl") {
$regexpcharpattern = '\\{|\\#\\(|\\/|\\\'|\\"|\\<|\\[|\\`';
# } vi bug workaround for previous line
$regexppattern = "qq|qr|qx|qw|q|m|s|tr|y";
$singleregexppattern = "qq|qr|qx|qw|q|m";
}
}
my $pascal = 0;
if ($lang eq "pascal") { $pascal = 1; }
# State variables (part 3 of 3)
# my $lastsymbol = ""; # Name of the last token, wiped by braces,
# parens, etc. This is not what you are
# looking for. It is used mostly for
# handling names of typedefs.
# my $name = ""; # Name of a basic data type.
# my $callbackNamePending = 0; # 1 if callback name could be here. This is
# only used for typedef'ed callbacks. All
# other callbacks get handled by the parameter
# parsing code. (If we get a second set of
# parsed parameters for a function, the first
# one becomes the callback name.)
# my $callbackName = ""; # Name of this callback.
# my $callbackIsTypedef = 0; # 1 if the callback is wrapped in a typedef---
# sets priority order of type matching (up
# one level in headerdoc2HTML.pl).
# my $namePending = 0; # 1 if name of func/variable is coming up.
# my $basetype = ""; # The main name for this data type.
# my $posstypes = ""; # List of type names for this data type.
# my $posstypesPending = 1; # If this token could be one of the
# type names of a typedef/struct/union/*
# declaration, this should be 1.
# my $sodtype = ""; # 'start of declaration' type.
# my $sodname = ""; # 'start of declaration' name.
# my $sodclass = ""; # 'start of declaration' "class". These
# bits allow us keep track of functions and
# callbacks, mostly, but not the name of a
# callback.
# my $simpleTypedef = 0; # High if it's a typedef w/o braces.
# my $simpleTDcontents = ""; # Guts of a one-line typedef. Don't ask.
# my $seenBraces = 0; # Goes high after initial brace for inline
# functions and macros -only-. We
# essentially stop parsing at this point.
# my $kr_c_function = 0; # Goes high if we see a K&R C declaration.
# my $kr_c_name = ""; # The name of a K&R function (which would
# otherwise get lost).
my $lastchar = ""; # Ends with the last token, but may be longer.
my $lastnspart = ""; # The last non-whitespace token.
my $lasttoken = ""; # The last token seen (though [\n\r] may be
# replaced by a space in some cases.
# my $startOfDec = 1; # Are we at the start of a declaration?
my $prespace = 0; # Used for indentation (deprecated).
my $prespaceadjust = 0; # Indentation is now handled by the parse
# tree (colorizer) code.
my $scratch = ""; # Scratch space.
my $curline = ""; # The current line. This is pushed onto
# the declaration at a newline and when we
# enter/leave certain constructs. This is
# deprecated in favor of the parse tree.
my $curstring = ""; # The string we're currently processing.
my $continuation = 0; # An obscure spacing workaround. Deprecated.
my $forcenobreak = 0; # An obscure spacing workaround. Deprecated.
# my $occmethod = 0; # 1 if we're in an ObjC method.
my $occspace = 0; # An obscure spacing workaround. Deprecated.
# my $occmethodname = ""; # The name of an objective C method (which
# gets augmented to be this:that:theother).
# my $preTemplateSymbol = ""; # The last symbol prior to the start of a
# C++ template. Used to determine whether
# the type returned should be a function or
# a function template.
# my $preEqualsSymbol = ""; # Used to get the name of a variable that
# is followed by an equals sign.
# my $valuepending = 0; # True if a value is pending, used to
# return the right value.
# my $value = ""; # The current value.
my $parsedParam = ""; # The current parameter being parsed.
my $postPossNL = 0; # Used to force certain newlines to be added
# to the parse tree (to end macros, etc.)
# my $categoryClass = "";
# my $classtype = "";
# my $inClass = 0;
my $pushParserStateAfterToken = 0;
my $pushParserStateAfterWordToken = 0;
my $pushParserStateAtBrace = 0;
my $occPushParserStateOnWordTokenAfterNext = 0;
$HeaderDoc::hidetokens = 0;
# Loop unti the end of file or until we've found a declaration,
# processing one line at a time.
my $nlines = $#inputLines;
my $incrementoffsetatnewline = 0;
print "INCOMING INPUTCOUNTER: $inputCounter\n" if ($HeaderDoc::inputCounterDebug);
while ($continue && ($inputCounter <= $nlines)) {
$HeaderDoc::CurLine = $inputCounter + $fileoffset;
my $line = $inputLines[$inputCounter++];
print STDERR "GOT LINE: $line\n" if (($localDebug && $apDebug) || $HeaderDoc::inputCounterDebug);
print STDERR "INCREMENTED INPUTCOUNTER [1]\n" if ($HeaderDoc::inputCounterDebug);
my @parts = ();
# $line =~ s/^\s*//go; # Don't strip leading spaces, please.
$line =~ s/\s*$//go;
# $scratch = nspaces($prespace);
# $line = "$scratch$line\n";
# $curline .= $scratch;
$line .= "\n";
if ($lang eq "C" && $sublang eq "IDL") {
if ($line =~ /cpp_quote\s*\(\s*\"(.*)\"\s*\)\s*$/) {
print "CHANGED LINE FROM \"$line\" to \"$1\"\n" if ($localDebug || $liteDebug);
$line = $1."\n";
}
}
print STDERR "LINE[$inputCounter] : $line\n" if ($offsetDebug);
# The tokenizer
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\^|\W)/, $line);
}
# See note about similar block below. This block is for fixing the
# "missing newline" problem, which otherwise would cause line numbers
# to sometimes be wrong.
push(@parts, "BOGUSBOGUSBOGUSBOGUSBOGUS");
my $xpart = "";
foreach my $nextxpart (@parts) {
if (!length($nextxpart)) { next; }
if (!length($xpart)) { $xpart = $nextxpart; next; }
if ($xpart eq "\n" && $nextxpart ne "BOGUSBOGUSBOGUSBOGUSBOGUS") {
print STDERR "FOUND EXTRA NEWLINE\n" if ($offsetDebug);
# $fileoffset++;
$incrementoffsetatnewline++;
}
$xpart = $nextxpart;
}
pop(@parts);
$parserState->{inInlineComment} = 0;
print STDERR "inInlineComment -> 0\n" if ($ilcDebug);
# warn("line $inputCounter\n");
if ($localDebug || $cppDebug || $spaceDebug) {foreach my $partlist (@parts) {print STDERR "PARTLIST: \"$partlist\"\n"; }}
# We have to do the C preprocessing work up front because token substitution
# must occur prior to actual parsing in order to do any good. This block does
# the work.
my $cpp_in_argparse = 0;
if (!$disable_cpp && (1 || $HeaderDoc::enable_cpp)) {
my $newrawline = "";
my $incppargs = 0;
my $cppstring = "";
my $cppname = "";
my $lastcpppart = "";
my @cppargs = ();
my $inChar = 0; my $inString = 0; my $inComment = $parserState->{inComment}; my $inSLC = $parserState->{inInlineComment};
my $inParen = 0;
my $inMacro = $parserState->{inMacro};
my $inCPPSpecial = $parserState->{inMacro} || $parserState->{inMacroLine};
my $inMacroTail = 0;
if ($parserState->{sodname} && ($parserState->{sodname} ne "")) {
$inMacroTail = 1;
}
print STDERR "INMACROTAIL: $inMacroTail\n" if ($cppDebug);
my @cpptrees;
my $cpptreecur = HeaderDoc::ParseTree->new();
my $cpptreetop = $cpptreecur;
# print STDERR "CHECK LINE $line\n";
if ($line =~ /^\s*#include (.*)$/) {
my $rest = $1;
$rest =~ s/^\s*//s;
$rest =~ s/\s*$//s;
if ($rest !~ s/^\<(.*)\>$/$1/s) {
$rest =~ s/^\"(.*)\"$/$1/s;
}
my $filename = basename($rest);
if ($HeaderDoc::HeaderFileCPPHashHash{$filename}) {
my $includehash = HeaderDoc::IncludeHash->new();
$includehash->{FILENAME} = $filename;
$includehash->{LINENUM} = $inputCounter + $fileoffset;
$includehash->{HASHREF} = $HeaderDoc::HeaderFileCPPHashHash{$filename};
push(@HeaderDoc::cppHashList, $includehash);
# print STDERR "PUSH HASH\n";
push(@HeaderDoc::cppArgHashList, $HeaderDoc::HeaderFileCPPArgHashHash{$filename});
}
} elsif ($line =~ /^\s*$definename\s+/) {
# print STDERR "inMacro -> 1\n";
# print STDERR "inMacro -> 1\n" if ($macroDebug || $cppDebug);
# This is a throwaway line.
$inMacro = 1;
}
if ($macrore_pound ne "" && $line =~ /^\s*\#\s*$macrore_pound\s+/) {
print STDERR "CPPSPECIAL -> 1\n" if ($macroDebug || $cppDebug);
$inCPPSpecial = 1;
}
my $cppleaddebug = 0;
do {
my $pos = 0;
my $dropargs = 0;
while ($pos < scalar(@parts)) {
my $part = $parts[$pos];
my $noCPPThisToken = 0;
if (length($part)) {
if (!$inChar && !$inString && !$inComment && !$inSLC) {
if ($parserState->{NEXTTOKENNOCPP} == 1) {
# We're in an "if" block.
if ($part eq "defined") {
$parserState->{NEXTTOKENNOCPP} = 3;
}
} elsif ($parserState->{NEXTTOKENNOCPP} == 2) {
# We're in an "ifdef"/"ifndef" block, so first word token
# ends this mode completely.
if ($part !~ /(\s|\()/) {
$parserState->{NEXTTOKENNOCPP} = 0;
$noCPPThisToken = 1;
}
} elsif ($parserState->{NEXTTOKENNOCPP} == 3) {
# We're in an "if" block, so first word token
# drops us back to default "if" block state.
if ($part !~ /(\s|\()/) {
$parserState->{NEXTTOKENNOCPP} = 1;
$noCPPThisToken = 1;
}
}
if ($inCPPSpecial && $part =~ /(ifdef|ifndef)/) {
$parserState->{NEXTTOKENNOCPP} = 2;
} elsif ($inCPPSpecial && $part =~ /if/) {
$parserState->{NEXTTOKENNOCPP} = 1;
}
}
print STDERR "TOKEN: $part NEXTTOKENNOCPP: ".$parserState->{NEXTTOKENNOCPP}." INMACRO: $inMacro INCPPSPECIAL: $inCPPSpecial\n" if ($cppleaddebug || $macroDebug || $cppDebug);
print STDERR "CPPLEADPART: $part\n"if ($cppleaddebug);
if (!$inString && !$inChar) {
if ($inComment && $part eq $eoc) {
print STDERR "EOC\n"if ($cppleaddebug);
$inComment = 0;
} elsif ($inSLC && $part =~ /[\r\n]/) {
# Handle newline in single-line comments.
print STDERR "EOSLC\n"if ($cppleaddebug);
$inSLC = 0;
} elsif (!$inSLC && $part eq $soc) {
print STDERR "SOC\n"if ($cppleaddebug);
$inComment = 1;
} elsif (!$inComment && ($part eq $ilc || $part eq $ilc_b)) {
print STDERR "INSLC\n"if ($cppleaddebug);
$inSLC = 1;
}
}
my $skip = 0;
if (!$incppargs) {
my $newpart = $part;
my $hasargs = 0;
if (!$inComment && !$inSLC && !$noCPPThisToken) {
($newpart, $hasargs) = cpp_preprocess($part, $HeaderDoc::CurLine);
# Don't drop tokens in macros.
if ($hasargs == 2 && $inMacro) {
$newpart = $part;
$hasargs = 0;
}
# Don't change the macro name. (If a
# macro gets redefined, ignore it.)
if ($inMacro && !$inMacroTail) {
$newpart = $part;
$hasargs = 0;
}
}
if ($hasargs) {
$incppargs = 1;
$cppname = $part;
if ($hasargs == 2) {
$dropargs = 1;
print STDERR "Dropping arguments for ignored macro \"$part\"\n" if ($cppDebug);
}
} else {
my $newpartnl = $newpart;
my $newpartnlcount = ($newpartnl =~ tr/\n//);
my $partnl = $part;
my $partnlcount = ($partnl =~ tr/\n//);
my $nlchange = ($newpartnlcount - $partnlcount);
print STDERR "NLCHANGE: $nlchange (FILEOFFSET = $fileoffset)\n" if ($offsetDebug);
$fileoffset -= $nlchange;
if ($inMacro) {
if ($newpart ne $part) {
print STDERR "CHANGING NEWPART FROM \"$newpart\" TO " if ($cppDebug);
$newpart =~ s/^\s*/ /s;
$newpart =~ s/\s*$//s;
$newpart =~ s/(.)\n/$1 \\\n/sg;
$newpart =~ s/\\$/ /s;
print STDERR "$newpart\n" if ($cppDebug);
}
}
$newrawline .= $newpart;
}
} elsif ($incppargs == 1) {
if ($part eq "(") {
# Don't do anything until leading parenthesis.
$incppargs = 3;
$inParen++;
}
} elsif ($incppargs == 3) {
if ($part eq '\\') {
if (!$inMacro && ($lastcpppart eq '\\')) { $lastcpppart = ""; } # @@@ CHECKME. inMacro test may not be needed.
# else {
# $lastcpppart = $part;
# if ($inMacro) {
# print STDERR "IMTEST\n" if ($cppDebug > 1);
# my $npos = $pos + 1;
# while ($npos < scalar(@parts)) {
# my $npart = $parts[$npos];
# if (length($npart)) {
# print STDERR "NEXTPART: \"".$parts[$npos]."\"\n" if ($cppDebug > 1);
# if ($npart =~ /\s/) {
# if ($npart =~ /[\n\r]/) {
# print STDERR "SKIP1\n" if ($cppDebug > 1);
# $skip = 1; last;
# } else {
# print STDERR "SPC\n" if ($cppDebug > 1);
# }
# } else {
# print STDERR "LAST\n" if ($cppDebug > 1);
# last;
# }
# }
# $npos++;
# }
# }
# }
} elsif ($part eq '"') {
if ($lastcpppart ne '\\') {
if (!$inChar && !$inComment && !$inSLC) {
$inString = !$inString;
}
}
$lastcpppart = $part;
} elsif ($part eq "'") {
if ($lastcpppart ne '\\') {
if (!$inString && !$inComment && !$inSLC) {
$inChar = !$inChar;
}
}
$lastcpppart = $part;
} elsif (!$inChar && !$inString && !$inComment && !$inSLC) {
if ($part eq "(") {
# Put in the token first, then nest.
$cpptreecur = $cpptreecur->next(HeaderDoc::ParseTree->new());
$cpptreecur->token($part);
$skip = 1;
$inParen++;
push(@cpptrees, $cpptreecur);
$cpptreecur = $cpptreecur->firstchild(HeaderDoc::ParseTree->new());
} elsif ($part eq ")") {
$inParen--;
# Go out one nesting level, then
# insert the token.
if (scalar(@cpptrees)) {
$cpptreecur = pop(@cpptrees);
while ($cpptreecur && $cpptreecur->next()) {
$cpptreecur = $cpptreecur->next();
}
}
if (!$inParen) {
push(@cppargs, $cpptreetop);
$cppstring = "";
$cpptreetop = HeaderDoc::ParseTree->new();
$cpptreecur = $cpptreetop;
$skip = 1;
$incppargs = 0;
if (!$dropargs) {
print STDERR "CALLING ARGPARSE FROM blockParse() [1].\n" if ($cppDebug);
my $addon = cpp_argparse($cppname, $HeaderDoc::CurLine, \@cppargs);
if ($inMacro) {
print STDERR "CHANGING ADDON FROM \"$addon\" TO " if ($cppDebug);
$addon =~ s/^\s*/ /s;
$addon =~ s/\s*$//s;
$addon =~ s/(.)\n/$1 \\\n/sg;
$addon =~ s/\\$/ /s;
print STDERR "$addon\n" if ($cppDebug);
}
$newrawline .= $addon;
}
$dropargs = 0;
}
} elsif (($inParen == 1) && (!$inChar && !$inString && !$inComment && !$inSLC) && ($part eq ",")) {
push(@cppargs, $cpptreetop);
$cpptreetop = HeaderDoc::ParseTree->new();
$cpptreecur = $cpptreetop;
$cppstring = "";
$skip = 1;
} elsif (($part =~ /\s/) && (!$inParen)) {
$incppargs = 0;
if (!$dropargs) {
print STDERR "CALLING ARGPARSE FROM blockParse() [2].\n" if ($cppDebug);
my $addon = cpp_argparse($cppname, $HeaderDoc::CurLine, \@cppargs);
if ($inMacro) {
print STDERR "CHANGING ADDON FROM \"$addon\" TO " if ($cppDebug);
$addon =~ s/^\s*/ /s;
$addon =~ s/\s*$//s;
$addon =~ s/(.)\n/$1 \\\n/sg;
$addon =~ s/\\$/ /s;
print STDERR "$addon\n" if ($cppDebug);
}
$newrawline .= $addon;
}
$dropargs = 0;
}
$lastcpppart = $part;
}
if ($skip) { $skip = 0; }
else {
my $xpart = $part;
# Strip newline in CPP argument list.
if ($part =~ /[\r\n]/) { $xpart = " "; }
$cpptreecur = $cpptreecur->next(HeaderDoc::ParseTree->new());
$cpptreecur->token($xpart);
}
$cppstring .= $part;
}
if ($inMacro && $part ne "define" &&
$part =~ /\w/ && !$inParen) {
$inMacroTail = 1;
}
}
$pos++;
}
if ($incppargs) {
# print STDERR "YO\n";
if ($parserState->{inMacro} || $inMacro) {
# print STDERR "YOYO\n";
if ($cppstring !~ s/\\\s*$//s) {
print STDERR "CPPS: \"$cppstring\"\n";
warn "Non-terminated macro.\n";
$incppargs = 0;
}
}
}
if ($incppargs || $inComment) {
print STDERR "Fetching new line ($incppargs, $inComment)\n" if ($cppleaddebug);
$HeaderDoc::CurLine = $inputCounter + $fileoffset;
$line = $inputLines[$inputCounter++];
if ($lang eq "C" && $sublang eq "IDL") {
if ($line =~ /cpp_quote\s*\(\s*\"(.*)\"\s*\)\s*$/) {
print "CHANGED LINE FROM \"$line\" to \"$1\"\n" if ($localDebug || $liteDebug);
$line = $1."\n";
}
}
print STDERR "INCREMENTED INPUTCOUNTER [2]\n" if ($HeaderDoc::inputCounterDebug);
# @parts = split(/(\W)/, $line);
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\W)/, $line);
}
}
} until (!$incppargs && !$inComment);
# The tokenizer
if ($lang eq "perl" || $lang eq "shell") {
@parts = split(/("|'|\#|\{|\}|\(|\)|\s|;|\\|\W)/, $newrawline);
} else {
@parts = split(/("|'|\/\/|\/\*|\*\/|::|==|<=|>=|!=|\<\<|\>\>|\{|\}|\(|\)|\s|;|\\|\W)/, $newrawline);
}
while (scalar(@cpptrees)) {
my $temptree = pop(@cpptrees);
if ($temptree != $cpptreetop) {
$temptree->dispose();
}
}
$cpptreetop->dispose();
}
if (!$parserState->{inMacro}) {
$parserState->{NEXTTOKENNOCPP} = 0;
}
# Throw away any empty entries caused by Perl seeing two
# adjacent tokens that match the split regexp. We don't
# want them or care about them, and they break things
# rather badly if we don't....
my @stripparts = @parts;
@parts = ();
print STDERR "BEGIN PARTLIST 2:\n" if ($spaceDebug);
foreach my $strippart (@stripparts) {
if (length($strippart)) {
print STDERR "MYPART: \"$strippart\"\n" if ($spaceDebug);
push(@parts, $strippart);
}
}
print STDERR "END PARTLIST 2.\n" if ($spaceDebug);
# This bit of code needs a bit of explanation, I think.
# We need to be able to see the token that follows the one we
# are currently processing. To do this, we actually keep track
# of the current token, and the previous token, but name then
# $nextpart and $part. We do processing on $part, which gets
# assigned the value from $nextpart at the end of the loop.
#
# To avoid losing the last part of the declaration (or needing
# to unroll an extra copy of the entire loop code) we push a
# bogus entry onto the end of the stack, which never gets
# used (other than as a bogus "next part") because we only
# process the value in $part.
#
# To avoid problems, make sure that you don't ever have a regexp
# that would match against this bogus token.
#
my $part = "";
push(@parts, "BOGUSBOGUSBOGUSBOGUSBOGUS");
if ($localDebug || $cppDebug) {foreach my $partlist (@parts) {print STDERR "POSTCPPPARTLIST: \"$partlist\"\n"; }}
foreach my $nextpart (@parts) {
my $hideTokenAndMaybeContents = 0;
$treeSkip = 0;
# $treePopTwo = 0;
# $treePopOnNewLine = 0;
# The current token is now in "part", and the literal next
# token in "nextpart". We can't just work with this as-is,
# though, because you can have multiple spaces, null
# tokens when two of the tokens in the split list occur
# consecutively, etc.
print STDERR "MYPART: \"$part\"\n" if ($localDebug || $spaceDebug);
$forcenobreak = 0;
if ($nextpart eq "\r") { $nextpart = "\n"; }
if ($localDebug && $nextpart eq "\n") { print STDERR "NEXTPART IS NEWLINE!\n"; }
if ($localDebug && $part eq "\n") { print STDERR "PART IS NEWLINE!\n"; }
### if ($nextpart ne "\n" && $nextpart =~ /\s/o) {
### # Replace tabs with spaces.
### $nextpart = " ";
### }
# Replace tabs with spaces.
$part =~ s/\t/ /g;
$nextpart =~ s/\t/ /g;
if ($part ne "\n" && $part =~ /\s/o && $nextpart ne "\n" &&
$nextpart =~ /\s/o) {
# we're a space followed by a space. Join the tokens.
print STDERR "MERGED \"$part\" and \"$nextpart\" into " if ($spaceDebug);
$nextpart = $part.$nextpart;
print STDERR "\"$nextpart\".\n" if ($spaceDebug);
$part = $nextpart;
next;
}
print STDERR "PART IS \"$part\"\n" if ($localDebug || $parserStackDebug || $parseDebug || $liteDebug || $spaceDebug);
print STDERR "CURLINE IS \"$curline\"\n" if ($localDebug || $hangDebug);
print STDERR "INOP: ".$parserState->{inOperator}."\n" if ($operatorDebug);
if (!length($nextpart)) {
print STDERR "SKIP NP\n" if ($localDebug);
next;
}
if (!length($part)) {
print STDERR "SKIP PART\n" if ($localDebug);
$part = $nextpart;
next;
}
if ($occPushParserStateOnWordTokenAfterNext > 1) {
if ($part =~ /\w/) {
$occPushParserStateOnWordTokenAfterNext--;
print STDERR "occPushParserStateOnWordTokenAfterNext -> $occPushParserStateOnWordTokenAfterNext (--)\n" if ($localDebug || $parseDebug);
}
} elsif ($occPushParserStateOnWordTokenAfterNext) {
# if ($part !~ /(\s|<)/)
if ($part =~ /(\/\/|\/\*|\-|\+|\w|\@)/) {
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[occPushParserStateOnWordTokenAfterNext]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 0;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
}
}
# If we get here, we aren't skipping a null or whitespace token.
# Let's print a bunch of noise if debugging is enabled.
# if ($part eq "\n" && $nextpart ne "BOGUSBOGUSBOGUSBOGUSBOGUS") {
# $fileoffset++;
# }
if ($part eq "\n" && $incrementoffsetatnewline) {
$incrementoffsetatnewline--;
$fileoffset++;
}
print STDERR "IN LOOP LANG: $lang INITIAL SUBLANG: $sublang\n" if ($localDebug || $parseDebug);
if ($parseDebug) {
print STDERR "PART: $part, type: $parserState->{typestring}, inComment: $parserState->{inComment}, inInlineComment: $parserState->{inInlineComment}, inChar: $parserState->{inChar}.\n" if ($localDebug);
print STDERR "PART: inBrackets: $parserState->{inBrackets}\n" if ($localDebug);
print STDERR "PART: onlyComments: $parserState->{onlyComments}, inClass: $parserState->{inClass}\n";
print STDERR "PART: cbsodname: $parserState->{cbsodname}\n";
print STDERR "PART: classIsObjC: $parserState->{classIsObjC}, PPSAT: $pushParserStateAfterToken, PPSAWordT: $pushParserStateAfterWordToken, PPSABrace: $pushParserStateAtBrace, occPPSOnWordTokenAfterNext: $occPushParserStateOnWordTokenAfterNext\n";
print STDERR "PART: bracecount: " . scalar(@braceStack) . " (init was $parserState->{initbsCount}).\n";
print STDERR "PART: inString: $parserState->{inString}, callbackNamePending: $parserState->{callbackNamePending}, namePending: $parserState->{namePending}, lastsymbol: $parserState->{lastsymbol}, lasttoken: $lasttoken, lastchar: $lastchar, SOL: $parserState->{startOfDec}\n" if ($localDebug);
print STDERR "PART: sodclass: $parserState->{sodclass} sodname: $parserState->{sodname}\n";
print STDERR "PART: sodtype: $parserState->{sodtype}\n";
print STDERR "PART: simpleTypedef: $parserState->{simpleTypedef}\n";
print STDERR "PART: posstypes: $parserState->{posstypes}\n";
print STDERR "PART: seenBraces: $parserState->{seenBraces} inRegexp: $inRegexp\n";
print STDERR "PART: regexpNoInterpolate: $regexpNoInterpolate\n";
print STDERR "PART: seenTilde: $parserState->{seenTilde}\n";
print STDERR "PART: CBN: $parserState->{callbackName}\n";
print STDERR "PART: regexpStack is:";
foreach my $token (@regexpStack) { print STDERR " $token"; }
print STDERR "\n";
print STDERR "PART: npplStack: ".scalar(@{$parserState->{pplStack}})." nparsedParamList: ".scalar(@{$parserState->{parsedParamList}})." nfreezeStack: ".scalar(@{$parserState->{freezeStack}})." frozen: $parserState->{stackFrozen}\n";
print STDERR "PART: inMacro: $parserState->{inMacro} treePopOnNewLine: $treePopOnNewLine\n";
print STDERR "PART: occmethod: $parserState->{occmethod} occmethodname: $parserState->{occmethodname}\n";
print STDERR "PART: returntype is $parserState->{returntype}\n";
print STDERR "length(declaration) = " . length($declaration) ."; length(curline) = " . length($curline) . "\n";
print STDERR "REQUIREDREGEXP IS \"$requiredregexp\"\n";
print STDERR "DEC: $declaration\n$curline\n";
} elsif ($tsDebug || $treeDebug) {
print STDERR "BPPART: $part\n";
}
if ($parserStackDebug) {
print STDERR "parserState: STACK CONTAINS ".scalar(@parserStack)." STATES\n";
print STDERR "parserState is $parserState\n";
}
# The ignore function returns either null, an empty string,
# or a string that gives the text equivalent of an availability
# macro. If the token is non-null and the length is non-zero,
# it's an availability macro, so blow it in as if the comment
# contained an @availability tag.
#
my $tempavail = ignore($part, $ignoreref, $perheaderignoreref);
printf("PART: $part TEMPAVAIL: $tempavail\n") if ($localDebug || $gccAttributeDebug);
if ($tempavail && ($tempavail ne "1") && ($tempavail ne "2")) {
$parserState->{availability} = $tempavail;
} elsif ($tempavail eq "2") {
# Reusing the GCC attribute handling code because that does exactly what we need.
print STDERR "Function-like availability macro detected. Collecting.\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = 1;
$parserState->{attributeParts} = ();
# Add __attribute__ as the next token.
$treeCur = $treeCur->addSibling($part, 0);
push(@treeStack, $treeCur);
my @tempAvailabilityNodesArray = ();
if ($parserState->{availabilityNodesArray}) {
@tempAvailabilityNodesArray = @{$parserState->{availabilityNodesArray}};
}
push(@tempAvailabilityNodesArray, $treeCur);
# print STDERR "ADDED $treeCur\n";
# $treeCur->dbprint();
$parserState->{availabilityNodesArray} = \@tempAvailabilityNodesArray;
# Nest all contents one level lower.
$treeCur = $treeCur->addChild("", 0);
$part = $nextpart;
next;
}
# Handle the GCC "__attribute__" extension outside the context of
# the parser because it isn't part of the language and massively
# breaks the syntax.
if ($lang eq "C" && isKeyword($part, $keywordhashref, $case_sensitive) == 2) {
print STDERR "GCC attribute detected. Collecting.\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = 1;
$parserState->{attributeParts} = ();
# Add __attribute__ as the next token.
$treeCur = $treeCur->addSibling($part, 0);
push(@treeStack, $treeCur);
# Nest all contents one level lower.
$treeCur = $treeCur->addChild("", 0);
$part = $nextpart;
next;
} elsif ($parserState->{attributeState} == 1) {
if ($part eq "(") {
print STDERR "GCC attribute open paren\n" if ($localDebug || $gccAttributeDebug);
$parserState->{attributeState} = -1;
}
$treeCur = $treeCur->addSibling($part, 0);
$part = $nextpart;
next;
} elsif ($parserState->{attributeState} < 0) {
if ($part eq "(") {
$parserState->{attributeState}--;
print STDERR "GCC attribute open paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug);
} elsif ($part eq ")") {
$parserState->{attributeState}++;
print STDERR "GCC attribute close paren, count=".(0-$parserState->{attributeState})."\n" if ($localDebug || $gccAttributeDebug);
}
$treeCur = $treeCur->addSibling($part, 0);
if (($localDebug || $gccAttributeDebug) && !$parserState->{attributeState}) {
print STDERR "GCC attribute: done collecting.\n";
# Get back to where we started.
$treeCur = pop(@treeStack);
}
$part = $nextpart;
next;
}
# Here be the parser. Abandon all hope, ye who enter here.
$treepart = "";
if ($parserState->{inProtocol} == 1) {
print STDERR "INPROTOCOL: 1\n" if ($parseDebug || $classDebug);
if ($part =~ /\w/) {
print STDERR "INPROTOCOL: 1 -> 2\n" if ($parseDebug || $classDebug);
$parserState->{inProtocol} = 2;
}
} elsif ($parserState->{inProtocol} == 2) {
print STDERR "INPROTOCOL: 2\n" if ($parseDebug || $classDebug);
if ($part eq "<") {
print STDERR "INPROTOCOL: 2 -> 3\n" if ($parseDebug || $classDebug);
$parserState->{extendsProtocol} = "";
$parserState->{inProtocol} = 3;
} elsif ($part =~ /\S/) {
# PUSH PARSER STATE
print STDERR "parserState pushed onto stack[PROTOCOL]\n" if ($parserStackDebug);
$parserState->{inProtocol} = -1;
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterWordToken = 0;
}
} elsif ($parserState->{inProtocol} == 3) {
print STDERR "INPROTOCOL: 3\n" if ($parseDebug || $classDebug);
if ($part eq ">") {
print STDERR "INPROTOCOL: 3 -> 2\n" if ($parseDebug || $classDebug);
$parserState->{inProtocol} = 2;
} else {
$parserState->{extendsProtocol} .= $part;
}
}
if ($parserState->{inClass} == 3) {
print STDERR "INCLASS3\n" if ($parseDebug || $classDebug);
if ($part eq ")") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [1]\n" if ($classDebug);
$parserState->{categoryClass} .= $part;
print STDERR "parserState will be pushed onto stack[cparen3]\n" if ($parserStackDebug);
# $parserState->{lastTreeNode} = $treeCur;
# push(@parserStack, $parserState);
# $parserState = HeaderDoc::ParserState->new();
# $parserState->{lang} = $lang;
# $parserState->{inputCounter} = $inputCounter;
# $parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterToken = 1;
} elsif ($part eq ":") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [2]\n" if ($classDebug);
if ($parserState->{classIsObjC}) {
print STDERR "occPushParserStateOnWordTokenAfterNext -> 2\n" if ($localDebug || $parseDebug);
$occPushParserStateOnWordTokenAfterNext = 2;
} else {
$pushParserStateAfterWordToken = 1;
}
# if ($sublang eq "occ") {
# $pushParserStateAtBrace = 2;
# }
} elsif ($part =~ /</ && $parserState->{classIsObjC}) {
print STDERR "pushParserStateAfterWordToken -> 0 (Conforming)\n" if ($localDebug || $parseDebug);
print STDERR "inClassConformingToProtocol -> 1\n" if ($localDebug || $parseDebug);
$pushParserStateAfterWordToken = 0;
$parserState->{inClassConformingToProtocol} = 1;
$occPushParserStateOnWordTokenAfterNext = 0;
} elsif ($part =~ />/ && $parserState->{classIsObjC} && $parserState->{inClassConformingToProtocol}) {
print STDERR "inClassConformingToProtocol -> 0\n" if ($localDebug || $parseDebug);
$pushParserStateAfterToken = 1;
print STDERR "pushParserStateAfterWordToken -> 1 (Conforming)\n" if ($localDebug || $parseDebug);
$parserState->{inClassConformingToProtocol} = 0;
} else {
$parserState->{categoryClass} .= $part;
}
} elsif ($parserState->{inClass} == 2) {
print STDERR "INCLASS2\n" if ($parseDebug || $classDebug);
if ($part eq ")") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [3]\n" if ($classDebug);
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[cparen2]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
} elsif ($part eq ":") {
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [4]\n" if ($classDebug);
if ($parserState->{classIsObjC}) {
print STDERR "occPushParserStateOnWordTokenAfterNext -> 2\n" if ($localDebug || $parseDebug);
$occPushParserStateOnWordTokenAfterNext = 2;
} else {
$pushParserStateAfterWordToken = 2;
}
} elsif ($part =~ /\w/) {
# skip the class name itself.
$parserState->{inClass} = 3;
print STDERR "inClass -> 3 [5]\n" if ($classDebug);
}
} elsif ($parserState->{inClass} == 1) {
print STDERR "INCLASS1\n" if ($parseDebug || $classDebug);
# print STDERR "inclass Part is $part\n";
if ($part eq ":") {
print STDERR "INCLASS COLON\n" if ($parseDebug || $classDebug);
$parserState->{forceClassName} = $parserState->{sodname};
$parserState->{forceClassSuper} = "";
# print STDERR "XSUPER: $parserState->{forceClassSuper}\n";
} elsif ($part eq "{" || $part eq ";") {
print STDERR "INCLASS BRCSEMI\n" if ($parseDebug || $classDebug);
$parserState->{forceClassDone} = 1;
if ($parserState->{classIsObjC} && $part eq "{") {
$parserState->{ISFORWARDDECLARATION} = 0;
$parserState->{lastTreeNode} = $treeCur;
print STDERR "parserState pushed onto stack[OCC-BRCSEMI]\n" if ($parserStackDebug);
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 0;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack) + 1; # NOTE: add one here because it will change in the SWITCH to follow.
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
$pushParserStateAfterToken = 1;
} elsif ($part eq ";") {
if (!defined($parserState->{ISFORWARDDECLARATION})) {
print STDERR "FORWARD DECLARATION DETECTED\n" if ($parseDebug || $localDebug || $liteDebug);
# print STDERR "PREVIOUS FD STATE: ".$parserState->{ISFORWARDDECLARATION}."\n";
$parserState->{ISFORWARDDECLARATION} = 1;
}
$pushParserStateAtBrace = 0;
$occPushParserStateOnWordTokenAfterNext = 0;
$pushParserStateAfterToken = 0;
}
} elsif ($parserState->{forceClassName} && !$parserState->{forceClassDone}) {
print STDERR "INCLASS ADD\n" if ($parseDebug || $classDebug);
if ($part =~ /[\n\r]/) {
$parserState->{forceClassSuper} .= " ";
} else {
$parserState->{forceClassSuper} .= $part;
}
# print STDERR "SUPER IS $parserState->{forceClassSuper}\n";
} elsif ($part =~ /</ && $parserState->{classIsObjC} && $occPushParserStateOnWordTokenAfterNext) {
print STDERR "INCLASS <\n" if ($parseDebug || $classDebug);
print STDERR "pushParserStateAfterWordToken -> 0 (Conforming)\n" if ($localDebug || $parseDebug);
print STDERR "inClassConformingToProtocol -> 1\n" if ($localDebug || $parseDebug);
$pushParserStateAfterWordToken = 0;
$parserState->{inClassConformingToProtocol} = 1;
$occPushParserStateOnWordTokenAfterNext = 0;
} elsif ($part =~ />/ && $parserState->{classIsObjC} && $parserState->{inClassConformingToProtocol}) {
print STDERR "INCLASS >\n" if ($parseDebug || $classDebug);
print STDERR "inClassConformingToProtocol -> 0\n" if ($localDebug || $parseDebug);
$pushParserStateAfterToken = 1;
print STDERR "pushParserStateAfterWordToken -> 1 (Conforming)\n" if ($localDebug || $parseDebug);
$parserState->{inClassConformingToProtocol} = 0;
} elsif ($occPushParserStateOnWordTokenAfterNext && $part =~ /\w/) {
print STDERR "INCLASS OCCSUPER\n" if ($parseDebug || $classDebug);
$parserState->{occSuper} = $part;
# $occPushParserStateOnWordTokenAfterNext = 0;
# $pushParserStateAfterToken = 1;
} elsif (!$parserState->{classIsObjC}) {
print STDERR "INCLASS NOTOBJC (OTHER)\n" if ($parseDebug || $classDebug);
if ($part =~ /[*(^]/) {
print STDERR "INCLASS DROP\n" if ($parseDebug || $classDebug);
$parserState->{inClass} = 0; # We're an instance. Either a variable or a function.
print STDERR "inClass -> 0 [6]\n" if ($classDebug);
$parserState->{sodtype} = $parserState->{preclasssodtype} . $parserState->{sodtype};
}
# } else {
# print STDERR "BUG\n";
}
};
if ($parserState->{inClassConformingToProtocol} == 1) {
$parserState->{inClassConformingToProtocol} = 2;
} elsif ($parserState->{inClassConformingToProtocol}) {
$parserState->{conformsToList} .= $part;
}
if ($macroDebug) {
print STDERR "MNT: ".$parserState->{macroNoTrunc}."\n";
}
# if (($part eq $ilc || $part eq $ilc_b) && ($lang ne "perl" || $lasttoken ne "\$")) {
# print STDERR "should be ILC?\n";
# } else {
# print STDERR "NO CHANEC: PART \"$part\" ILC \"$ilc\" ILC_B: \"ilc_b\" LANG: \"$lang\" LASTTOKEN: \"$lasttoken\"\n";
# }
SWITCH: {
# Blank declaration handlers (mostly for misuse of
# OSMetaClassDeclareReservedUsed and similar)
(($part eq ";") && ($parserState->{startOfDec} == 1) && !$parserState->{inMacro} && !$parserState->{inMacroLine} && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "LEADING SEMICOLON: CASE 01\n" if ($liteDebug);
print STDERR "Dropping empty declaration\n" if ($localDebug || $parseDebug);
$part = "";
last SWITCH;
};
# Macro handlers
(($parserState->{inMacro} == 1) && ($part eq "define")) && do {
print STDERR "INMACRO/DEFINE: CASE 02\n" if ($liteDebug);
# define may be a multi-line macro
print STDERR "INMACRO AND DEFINE\n" if ($parseDebug || $localDebug);
$parserState->{inMacro} = 3;
print STDERR "inMacro -> 3\n" if ($macroDebug || $cppDebug);
$parserState->{sodname} = "";
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [1]\n"; }
$treePopOnNewLine = 2;
$pound .= $part;
$treeCur->token($pound);
}
last SWITCH;
};
# (($parserState->{inMacro} == 1 && $macrore_pound ne "" && $part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)/ && ($part ne $definename)) || ($parserState->{inMacro} == 0 && $macrore_nopound ne "" && $part =~ /$macrore_nopound/))
# (($parserState->{inMacro} == 1 && $part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)/ )) && do
(!$parserState->{inComment} && (($parserState->{inMacro} == 1 && $macrore_pound ne "" && $part =~ /^$macrore_pound$/ && ($part ne $definename)) || ($parserState->{inMacro} == 0 && $macrore_nopound ne "" && $part =~ /^$macrore_nopound$/))) && do {
print STDERR "MACRORE-v: \"$macrore_pound\"\n" if ($macroDebug);
print STDERR "MACRORE-r: \"(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include)\"\n" if ($macroDebug);
print STDERR "MACRORE-n: \"$macrore_nopound\"\n" if ($macroDebug);
print STDERR "INMACRO/IF: CASE 03\n" if ($liteDebug);
print STDERR "INMACRO AND IF/IFDEF/IFNDEF/ENDIF/ELSE/PRAGMA/IMPORT/INCLUDE\n" if ($parseDebug || $localDebug);
# these are all single-line macros
$parserState->{inMacro} = 4;
print STDERR "inMacro -> 4\n" if ($macroDebug || $cppDebug);
$parserState->{sodname} = "";
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [2]\n"; }
$treePopOnNewLine = 1;
$pound .= $part;
$treeCur->token($pound);
if ($part eq "endif") {
# the rest of the line is not part of the macro
# NOTE: Do not change treeCur in the
# next line.
$treeCur->addChild("\n", 0);
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [3]\n"; }
$treePopOnNewLine = 0;
$treeSkip = 1;
}
}
last SWITCH;
};
(($parserState->{inMacroLine} == 1) && ($part =~ /(if|ifdef|ifndef|endif|else|undef|elif|pragma|import|include|define)/o)) && do {
print STDERR "INMACROLINE/IF: CASE 04\n" if ($liteDebug);
print STDERR "INMACROLINE AND IF/IFDEF/IFNDEF/ENDIF/ELSE/PRAGMA/IMPORT/INCLUDE\n" if ($parseDebug || $localDebug);
my $pound = $treeCur->token();
if ($pound eq "$sopreproc") {
$pound .= $part;
$treeCur->token($pound);
if ($part =~ /define/o) {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [4]\n"; }
$treePopOnNewLine = 2;
} elsif ($part eq "endif") {
# the rest of the line is not part of the macro
# NOTE: Do not change treeCur in the
# next line.
$treeCur->addChild("\n", 0);
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [5]\n"; }
$treePopOnNewLine = 0;
$treeSkip = 1;
} else {
$treeNest = 2;
if ($treeDebug) { print STDERR "TS TREENEST -> 2 [6]\n"; }
$treePopOnNewLine = 1;
}
}
last SWITCH;
};
($parserState->{inMacro} == 1 && ($part ne $soc) && ($part ne $eoc) && $part =~ /\s/) && do {
$treepart = $part; $part = "";
last SWITCH;
};
($parserState->{inMacro} == 1 && ($part ne $soc) && ($part ne $eoc)) && do {
print STDERR "INMACRO PPTOKEN: CASE 05\n" if ($liteDebug);
print STDERR "INMACRO IS 1, CHANGING TO 2 (NO PROCESSING)\n" if ($parseDebug || $localDebug);
# error case.
$parserState->{inMacro} = 2;
print STDERR "inMacro -> 2\n" if ($macroDebug || $cppDebug);
last SWITCH;
};
($parserState->{inMacro} > 1 && $part ne "//" && $part !~ /[\n\r]/ && ($part ne $soc) && ($part ne $eoc)) && do {
print STDERR "INMACRO OTHERTOKEN: CASE 06\n" if ($liteDebug);
print STDERR "INMACRO > 1, PART NE //" if ($parseDebug || $localDebug);
if ($part eq "\\") {
$parserState->addBackslash();
} elsif ($part !~ /[ \t]/) {
$parserState->addBackslash();
}
print STDERR "PART: $part\n" if ($macroDebug);
if ($parserState->{seenMacroPart} && $HeaderDoc::truncate_inline) {
print STDERR "MACRO: SMP&TI\n" if ($macroDebug);
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
print STDERR "MACRO: NOSTACK\n" if ($macroDebug);
if ($part =~ /\s/o && $parserState->{macroNoTrunc} == 1) {
print STDERR "MACRO: ENDOFNAME\n" if ($macroDebug);
$parserState->{macroNoTrunc} = 0;
} elsif ($part =~ /[\{\(]/o) {
print STDERR "MACRO: BRACE\n" if ($macroDebug);
if (!$parserState->{macroNoTrunc}) {
# $parserState->{seenBraces} = 1;
$HeaderDoc::hidetokens = 3;
}
} else {
print STDERR "MACRO: OTHERTOKEN\n" if ($macroDebug);
$parserState->{macroNoTrunc} = 2;
}
}
}
if ($part =~ /[\{\(]/o) {
push(@braceStack, $part);
print STDERR "PUSH\n" if ($macroDebug);
} elsif ($part =~ /[\}\)]/o) {
if ($part ne peekmatch(\@braceStack, $filename, $inputCounter)) {
if ($parserState->{macroNoTrunc} == 1) {
# We haven't reached the end of the first part of the declaration, so this is an error.
warn("$filename:$inputCounter: warning: Initial braces in macro name do not match.\nWe may have a problem.\n");
}
}
pop(@braceStack);
print STDERR "POP\n" if ($macroDebug);
}
if ($part =~ /\S/o) {
$parserState->{seenMacroPart} = 1;
$parserState->{lastsymbol} = $part;
if (($parserState->{sodname} eq "") && ($parserState->{inMacro} == 3)) {
print STDERR "DEFINE NAME IS $part\n" if ($macroDebug);
$parserState->{sodname} = $part;
}
}
$lastchar = $part;
last SWITCH;
};
# Regular expression handlers
# print STDERR "IRE: $inRegexp IRT: $inRegexpTrailer IS: $parserState->{inString} ICo $parserState->{inComment} ILC: $parserState->{inInlineComment} ICh $parserState->{inChar}\n";
(length($regexppattern) && $part =~ /^($regexppattern)$/ && !($inRegexp || $inRegexpTrailer || $parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "REGEXP PATTERN: CASE 07\n" if ($liteDebug);
my $match = $1;
print STDERR "REGEXP WITH PREFIX\n" if ($regexpDebug);
$regexpNoInterpolate = 0;
if ($match =~ /^($singleregexppattern)$/) {
# e.g. perl PATTERN?
$inRegexp = 2;
} else {
$inRegexp = 4;
# print STDERR "REGEXP PART IS \"$part\"\n";
if ($part eq "tr") { $regexpNoInterpolate = 1; }
# if ($part =~ /tr/) { $regexpNoInterpolate = 1; }
}
last SWITCH;
}; # end regexppattern
(($inRegexp || $parserState->{lastsymbol} eq "~") && (length($regexpcharpattern) && $part =~ /^($regexpcharpattern)$/ && (!scalar(@regexpStack) || $part eq peekmatch(\@regexpStack, $filename, $inputCounter)))) && do {
print STDERR "REGEXP CHARACTER: CASE 08\n" if ($liteDebug);
print STDERR "REGEXP?\n" if ($regexpDebug);
if (!$inRegexp) {
$inRegexp = 2;
}
# if ($lasttoken eq "\\")
if ($parserState->isQuoted($lang. $sublang)) {
# jump to next match.
$lasttoken = $part;
$parserState->{lastsymbol} = $part;
next SWITCH;
}
print STDERR "REGEXP POINT A\n" if ($regexpDebug);
$lasttoken = $part;
$parserState->{lastsymbol} = $part;
if ($part eq "#" &&
((scalar(@regexpStack) != 1) ||
(peekmatch(\@regexpStack, $filename, $inputCounter) ne "#"))) {
if ($nextpart =~ /^\s/o) {
# it's a comment. jump to next match.
next SWITCH;
}
}
print STDERR "REGEXP POINT B\n" if ($regexpDebug);
if (!scalar(@regexpStack)) {
push(@regexpStack, $part);
$inRegexp--;
} else {
my $match = peekmatch(\@regexpStack, $filename, $inputCounter);
my $tos = pop(@regexpStack);
if (!scalar(@regexpStack) && ($match eq $part)) {
$inRegexp--;
if ($inRegexp == 2 && $tos eq "/") {
# we don't double the slash in the
# middle of a s/foo/bar/g style
# expression.
$inRegexp--;
}
if ($inRegexp) {
push(@regexpStack, $tos);
}
} elsif (scalar(@regexpStack) == 1) {
push(@regexpStack, $tos);
if ($tos =~ /['"`]/o || $regexpNoInterpolate) {
# these don't interpolate.
next SWITCH;
}
} else {
push(@regexpStack, $tos);
if ($tos =~ /['"`]/o || $regexpNoInterpolate) {
# these don't interpolate.
next SWITCH;
}
push(@regexpStack, $part);
}
}
print STDERR "REGEXP POINT C\n" if ($regexpDebug);
if (!$inRegexp) {
$inRegexpTrailer = 2;
}
last SWITCH;
}; # end regexpcharpattern
# Start of preprocessor macros
($part eq "$sopreproc") && do {
print STDERR "SOPREPROC: CASE 09\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parserState->{onlyComments}) {
print STDERR "inMacro -> 1\n" if ($macroDebug || $cppDebug);
$parserState->{inMacro} = 1;
## @@@ FIXME DAG NEXT TWO LINES NEEDED FOR IDL TO AVOID
## "warning: Declaration starts with # but is not preprocessor macro"
## ERROR MESSAGE, BUT THIS BREAKS C/C++.
## WHY !?!?!
##
## if ($$treepart = " ";
## $nextpart = $part.$nextpart;
##
## END IDL-ONLY BLOCK
# $continue = 0;
# print STDERR "continue -> 0 [1]\n" if ($localDebug || $macroDebug);
} elsif ($curline =~ /^\s*$/o) {
$parserState->{inMacroLine} = 1;
print STDERR "IML\n" if ($localDebug);
} elsif ($postPossNL) {
print STDERR "PRE-IML \"$curline\"\n" if ($localDebug || $macroDebug);
$treeCur = $treeCur->addSibling("\n", 0);
bless($treeCur, "HeaderDoc::ParseTree");
$parserState->{inMacroLine} = 1;
$postPossNL = 0;
}
}
};
# Start of token-delimited functions and procedures (e.g.
# Pascal and PHP)
($part eq "$sofunction" || $part eq "$soprocedure") && do {
print STDERR "SOFUNC: CASE 10\n" if ($liteDebug);
$parserState->{sodclass} = "function";
print STDERR "K&R C FUNCTION FOUND [1].\n" if ($localDebug);
$parserState->{kr_c_function} = 1;
$parserState->{typestring} = "function";
$parserState->{startOfDec} = 2;
$parserState->{namePending} = 1;
# if (!$parserState->{seenBraces}) { # TREEDONE
# $treeNest = 1;
# $treePopTwo++;
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
# }
print STDERR "namePending -> 1 [1]\n" if ($parseDebug);
last SWITCH;
};
# C++ destructor handler.
($part =~ /\~/o && $lang eq "C" && $sublang eq "cpp" && !!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "C++ DESTRUCTOR: CASE 11\n" if ($liteDebug);
print STDERR "TILDE\n" if ($localDebug);
$parserState->{seenTilde} = 2;
$lastchar = $part;
$parserState->{onlyComments} = 0;
# $name .= '~';
last SWITCH;
};
# Objective-C method handler.
($part =~ /[-+]/o && $parserState->{onlyComments}) && do {
print STDERR "OBJC METHOD: CASE 12\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
print STDERR "OCCMETHOD\n" if ($localDebug);
# Objective C Method.
$parserState->{occmethod} = 1;
$parserState->{occmethodtype} = $part;
$lastchar = $part;
$parserState->{onlyComments} = 0;
print STDERR "[a]onlyComments -> 0\n" if ($macroDebug);
if (!$parserState->{seenBraces}) { # TREEDONE
if (!$parserState->{hollow}) {
print STDERR "SETHOLLOW -> 1\n" if ($parserStackDebug);
$sethollow = 1;
}
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [7]\n"; }
$parserState->{treePopTwo} = 1;
}
}
last SWITCH;
};
# Newline handler.
($part =~ /[\n\r]/o) && do {
print STDERR "NEWLINE: CASE 13\n" if ($liteDebug);
# NEWLINE FOUND
$treepart = $part;
if ($inRegexp) {
warn "$filename:$inputCounter: warning: multi-line regular expression\n";
}
print STDERR "NLCR\n" if ($tsDebug || $treeDebug || $localDebug);
if ($lastchar !~ /[\,\;\{\(\)\}]/o && $nextpart !~ /[\{\}\(\)]/o) {
if ($lastchar ne "*/" && $nextpart ne "/*") {
if (!$parserState->{inMacro} && !$parserState->{inMacroLine} && !$treePopOnNewLine) {
print STDERR "NL->SPC\n" if ($localDebug);
$part = " ";
print STDERR "LC: $lastchar\n" if ($localDebug);
print STDERR "NP: $nextpart\n" if ($localDebug);
$postPossNL = 2;
} else {
$parserState->{inMacroLine} = 0;
# Don't push parsed parameter here. Just clear it.
# push(@{$parserState->{parsedParamList}}, $parsedParam);
# print STDERR "pushed $parsedParam into parsedParamList [1]\n" if ($parmDebug);
print STDERR "skipped pushing CPP directive $parsedParam into parsedParamList [1]\n" if ($parmDebug || $cppDebug || $localDebug);
$parsedParam = "";
}
}
}
if ($treePopOnNewLine < 0) {
# pop once for //, possibly again for macro
$treePopOnNewLine = 0 - $treePopOnNewLine;
$treeCur = $treeCur->addSibling($treepart, 0);
bless($treeCur, "HeaderDoc::ParseTree");
# push(@treeStack, $treeCur);
$treeSkip = 1;
$treeCur = pop(@treeStack);
if (!$treeCur) {
$treeCur = $treeTop;
warn "$filename:$inputCounter: warning: Attempted to pop off top of tree\n";
}
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [1]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($treePopOnNewLine == 1 || ($treePopOnNewLine && !$parserState->isQuoted())) {
# $parserState->{lastsymbol} ne "\\"
$treeCur = $treeCur->addSibling($treepart, 0);
bless($treeCur, "HeaderDoc::ParseTree");
# push(@treeStack, $treeCur);
$treeSkip = 1;
$treeCur = pop(@treeStack);
if (!$treeCur) {
$treeCur = $treeTop;
warn "$filename:$inputCounter: warning: Attempted to pop off top of tree\n";
}
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->addSibling("", 0); # empty token
print STDERR "TSPOP [1a]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
$treePopOnNewLine = 0;
$HeaderDoc::hidetokens = 0;
} else {
print STDERR "Not popping from tree. Probably quoted.\n" if ($localDebug || $parseDebug);
}
next SWITCH;
};
# C++ template handlers
($part eq $sotemplate && !$parserState->{seenBraces} && ($parserState->{inOperator} != 1)) && do {
print STDERR "C++ TEMPLATE: CASE 14\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($HeaderDoc::hideIDLAttributes && $lang eq "C" && $sublang eq "IDL") { $hideTokenAndMaybeContents = 3; }
print STDERR "inTemplate -> ".($parserState->{inTemplate}+1)."\n" if ($localDebug);
print STDERR "SBS: " . scalar(@braceStack) . ".\n" if ($localDebug);
$parserState->{inTemplate}++;
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
$parserState->{preTemplateSymbol} = $parserState->{lastsymbol};
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{onlyComments} = 0;
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if (!$parserState->{hollow}) { $sethollow = 1; } # IDL can have this at the start of declaration.
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [8]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
print STDERR "[b]onlyComments -> 0\n" if ($macroDebug);
}
last SWITCH;
};
($part eq $eotemplate && !$parserState->{seenBraces} && ($parserState->{inOperator} != 1)) && do {
print STDERR "C++ TEMPLATE END: CASE 15\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && (!(scalar(@braceStack)-$parserState->{initbsCount}) || $parserState->{inTemplate})) {
if ($parserState->{inTemplate}) {
print STDERR "parserState->{inTemplate} -> ".($parserState->{inTemplate}-1)."\n" if ($localDebug);
$parserState->{inTemplate}--;
$parserState->{lastsymbol} = "";
$lastchar = $part;
$curline .= " ";
$parserState->{onlyComments} = 0;
print STDERR "[c]onlyComments -> 0\n" if ($macroDebug);
}
my $top = pop(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [2]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($top ne "$sotemplate") {
warn("$filename:$inputCounter: warning: Template (angle) brackets do not match.\nWe may have a problem.\n");
}
}
last SWITCH;
};
#
# Handles C++ access control state, e.g. "public:"
#
($part eq ":") && do {
print STDERR "Access control colon: CASE 16\n" if ($liteDebug);
print STDERR "TS IS \"$parserState->{typestring}\"\n" if ($localDebug || $parseDebug);
# fall through to next colon handling case if we fail.
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (length($accessregexp) && ($lastnspart =~ /$accessregexp/)) {
# We're special.
print STDERR "PERMANENT ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$parserState->{typestring} = "";
print STDERR "RESET HOLLOW at $part\n" if ($parserStackDebug);
$parserState->{hollow} = undef;
$parserState->{onlyComments} = 1;
print STDERR "hollowskip -> 1 (ACS)\n" if ($parserStateInsertDebug);
$hollowskip = 1;
$HeaderDoc::AccessControlState = $1;
$lastACS = $1;
last SWITCH;
} elsif ($parserState->{typestring} eq "struct") {
if (!(scalar(@braceStack) - $parserState->{initbsCount})) {
if (!$parserState->{structClassName}) {
$parserState->{structClassName} = $parserState->{lastsymbol};
$parserState->{bracePending} = 2;
}
}
}
}
};
(length($accessregexp) && ($part =~ /$accessregexp/)) && do {
print STDERR "Access regexp: CASE 17\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
# We're special.
if ($part =~ /^\@(.*)$/) {
print STDERR "PERMANENT ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$parserState->{typestring} = "";
print STDERR "RESET HOLLOW at $part\n" if ($parserStackDebug);
$parserState->{hollow} = undef;
$parserState->{onlyComments} = 1;
$hollowskip = 1;
print STDERR "hollowskip -> 1 (\@ACS)\n" if ($parserStateInsertDebug);
$HeaderDoc::AccessControlState = $1;
$lastACS = $1;
last SWITCH;
} else {
print STDERR "TEMPORARY ACS CHANGE from $HeaderDoc::AccessControlState to $1\n" if ($localDebug);
$parserState->{sodname} = "";
$lastACS = $HeaderDoc::AccessControlState;
$HeaderDoc::AccessControlState = $1;
}
} else {
next SWITCH;
}
};
(length($requiredregexp) && $part =~ /$requiredregexp/) && do {
print STDERR "REQUIRED REGEXP MATCH: \"$part\"\n" if ($localDebug || $parseDebug);
$hollowskip = 1;
print STDERR "hollowskip -> 1 (requiredregexp)\n" if ($parserStateInsertDebug);
last SWITCH;
};
#
# C++ copy constructor handler. For example:
#
# char *class(void *a, void *b) :
# class(pri_type, pri_type);
#
($part eq ":") && do {
print STDERR "Copy constructor: CASE 18\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parserState->{occmethod}) {
$parserState->{name} = $parserState->{lastsymbol};
if ($parserState->{occparmlabelfound}) {
$parserState->{occmethodname} .= "$parserState->{lastsymbol}:";
if ($occMethodNameDebug) {
print STDERR "OCC method name now ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\").\n";
}
$parserState->{occparmlabelfound} = -1; # next token is name of this parameter, followed by label for next parameter.
} else {
if ($occMethodNameDebug) {
print STDERR "OCC method name missing.\n";
print STDERR "OCC method name still ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\").\n";
}
$parserState->{occparmlabelfound} = -2; # Special case: grab the parameter name instead because parameter has no label.
}
# Start doing line splitting here.
# Also, capture the method's name.
if ($parserState->{occmethod} == 1) {
$parserState->{occmethod} = 2;
if (!$prespace) { $prespaceadjust = 4; }
$parserState->{onlyComments} = 0;
print STDERR "[d]onlyComments -> 0\n" if ($macroDebug);
}
} else {
if ($lang eq "C" && $sublang eq "cpp") {
if (!(scalar(@braceStack)-$parserState->{initbsCount}) && $parserState->{sodclass} eq "function") {
$inPrivateParamTypes = 1;
$declaration .= "$curline";
$publicDeclaration = $declaration;
$declaration = "";
} else {
next SWITCH;
}
if (!$parserState->{stackFrozen}) {
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
# print STDERR "SEOPPLS\n";
# for my $item (@{$parserState->{pplStack}}) {
# print STDERR "PPLS: $item\n";
# }
# print STDERR "OEOPPLS\n";
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
} else {
next SWITCH;
}
}
if (!$parserState->{seenBraces} && !$parserState->{occmethod}) { # TREEDONE
# $treeCur->addSibling($part, 0); $treeSkip = 1;
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [9]\n"; }
$parserState->{treePopTwo} = 1;
# $treeCur = pop(@treeStack) || $treeTop;
# bless($treeCur, "HeaderDoc::ParseTree");
}
last SWITCH;
} else {
next SWITCH;
}
};
# Non-newline, non-carriage-return whitespace handler.
($part =~ /\s/o) && do {
print STDERR "Whitespace: CASE 19\n" if ($liteDebug);
# just add white space silently.
# if ($part eq "\n") { $parserState->{lastsymbol} = ""; };
$lastchar = $part;
last SWITCH;
};
# backslash handler (largely useful for macros, strings).
($part =~ /\\/o) && do {
print STDERR "BACKSLASH: CASE 20\n" if ($liteDebug);
$parserState->{lastsymbol} = $part; $lastchar = $part;
$parserState->addBackslash();
};
# quote and bracket handlers.
($part eq "\"") && do {
print STDERR "DOUBLE QUOTE: CASE 21\n" if ($liteDebug);
print STDERR "dquo\n" if ($localDebug);
# print STDERR "QUOTEDEBUG: CURSTRING IS '$curstring'\n";
# print STDERR "QUOTEDEBUG: CURLINE IS '$curline'\n";
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{onlyComments} = 0;
print STDERR "[e]onlyComments -> 0\n" if ($macroDebug);
print STDERR "LASTTOKEN: $lasttoken\nCS: $curstring\n" if ($localDebug);
# if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o))
if (!$parserState->isQuoted($lang, $sublang)) {
if (!$parserState->{inString}) {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [10]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} else {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [3]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
$parserState->{inString} = (1-$parserState->{inString});
}
}
$lastchar = $part;
$parserState->{lastsymbol} = "";
last SWITCH;
};
($part eq "[") && do {
print STDERR "LEFT BRACKET: CASE 22\n" if ($liteDebug);
# left square bracket (square brace)
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
print STDERR "lbracket\n" if ($localDebug);
print STDERR "LBRACKET DEBUG TRACE: SODNAME: ".$parserState->{sodname}." SODTYPE: ".$parserState->{sodtype}." SIMPLETDCONTENTS: ".$parserState->{simpleTDcontents}."\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
$parserState->{onlyComments} = 0;
print STDERR "[f]onlyComments -> 0\n" if ($macroDebug);
}
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [11]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$parserState->{inBrackets} += 1;
}
$lastchar = $part;
last SWITCH;
};
($part eq "]") && do {
print STDERR "CLOSE BRACKET: CASE 23\n" if ($liteDebug);
# right square bracket (square brace)
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
print STDERR "rbracket\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
$parserState->{onlyComments} = 0;
print STDERR "[g]onlyComments -> 0\n" if ($macroDebug);
}
my $top = pop(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [4]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if ($top ne "[") {
warn("$filename:$inputCounter: warning: Square brackets do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
}
pbs(@braceStack);
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$parserState->{inBrackets} -= 1;
}
$lastchar = $part;
last SWITCH;
};
($part eq "'") && do {
print STDERR "SINGLE QUOTE: CASE 24\n" if ($liteDebug);
print STDERR "squo\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString})) {
# if (($lasttoken !~ /\\$/o) && ($curstring !~ /\\$/o))
if (!$parserState->isQuoted($lang, $sublang)) {
$parserState->{onlyComments} = 0;
print STDERR "[h]onlyComments -> 0\n" if ($macroDebug);
if (!$parserState->{inChar}) {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [12]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} else {
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [5]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
$parserState->{inChar} = !$parserState->{inChar};
}
if ($lastchar =~ /\=$/o) {
$curline .= " ";
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Inline comment (two slashes in c++, hash in perl/shell)
# handler.
(($part eq $ilc || $part eq $ilc_b) && ($lang ne "perl" || $lasttoken ne "\$")) && do {
print STDERR "SINGLE LINE COMMENT: CASE 25\n" if ($liteDebug);
print STDERR "ILC\n" if ($localDebug || $ilcDebug);
if (!($parserState->{inComment} || $parserState->{inChar} || $parserState->{inString} || $inRegexp)) {
$parserState->{inInlineComment} = 4;
print STDERR "inInlineComment -> 1\n" if ($ilcDebug);
$curline = spacefix($curline, $part, $lastchar, $soc, $eoc, $ilc, $ilc_b);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [13]\n"; }
if (!$treePopOnNewLine) {
$treePopOnNewLine = 1;
} else {
$treePopOnNewLine = 0 - $treePopOnNewLine;
}
print STDERR "treePopOnNewLine -> $treePopOnNewLine\n" if ($ilcDebug);
# $treeCur->addSibling($part, 0); $treeSkip = 1;
# $treePopOnNewLine = 1;
# $treeCur = pop(@treeStack) || $treeTop;
# bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif ($parserState->{inComment}) {
my $linenum = $inputCounter + $fileoffset;
if (!$cpp_in_argparse) {
# We've already seen these.
if ($nestedcommentwarn) {
warn("$filename:$linenum: warning: Nested comment found [1]. Ignoring.\n");
}
# This isn't really a problem.
# Don't warn to avoid bogus
# warnings for apple_ref and
# URL markup in comments.
}
# warn("XX $cpp_in_argparse XX $inputCounter XX $fileoffset XX\n");
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Standard comment handlers: soc = start of comment,
# eoc = end of comment.
($part eq $soc) && do {
print STDERR "START OF MULTILINE COMMENT: CASE 26\n" if ($liteDebug);
print STDERR "SOC\n" if ($localDebug);
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{inComment} = 4;
$curline = spacefix($curline, $part, $lastchar);
if (!$parserState->{seenBraces}) {
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [14]\n"; }
# print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug);
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild("", 0);
# bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif ($parserState->{inComment}) {
my $linenum = $inputCounter + $fileoffset;
# Modern compilers shouldn't have trouble with this. It occurs |
# frequently in apple_ref markup (e.g. //apple_ref/C/instm/ \|/
# IOFireWireDeviceInterface/AddIsochCallbackDispatcherToRunLoop/*Add
# IsochCallbackDispatcherToRunLoopIOFireWireLibDeviceRefCFRunLoopRef)
if ($nestedcommentwarn) {
warn("$filename:$linenum: warning: Nested comment found [2]. Ignoring.\n");
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
($part eq $eoc) && do {
print STDERR "END OF MULTILINE COMMENT: CASE 27\n" if ($liteDebug);
print STDERR "EOC\n" if ($localDebug);
if ($parserState->{inComment} && !($parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{inComment} = 0;
$curline = spacefix($curline, $part, $lastchar);
$ppSkipOneToken = 1;
if (!$parserState->{seenBraces}) {
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
} elsif (!$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && !$inRegexp) {
my $linenum = $inputCounter + $fileoffset;
warn("$filename:$linenum: warning: Unmatched close comment tag found. Ignoring.\n");
} elsif ($parserState->{inInlineComment}) {
my $linenum = $inputCounter + $fileoffset;
# We'll leave this one on for now.
if ((1 || $nestedcommentwarn) && (!$HeaderDoc::test_mode)) {
warn("$filename:$linenum: warning: Nested comment found [3]. Ignoring.\n");
}
}
$parserState->{lastsymbol} = "";
$lastchar = $part;
last SWITCH;
};
# Parenthesis and brace handlers.
($part eq "(") && do {
print STDERR "OPEN PAREN: CASE 28\n" if ($liteDebug);
my @tempppl = undef;
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
if (!(scalar(@braceStack)-$parserState->{initbsCount})) {
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
print STDERR "parsedParamList wiped\n" if ($parmDebug);
@tempppl = @{$parserState->{parsedParamList}};
@{$parserState->{parsedParamList}} = ();
$parsedParam = "";
}
$parserState->{onlyComments} = 0;
print STDERR "[i]onlyComments -> 0\n" if ($macroDebug);
if ($parserState->{simpleTypedef} && !(scalar(@braceStack)- $parserState->{initbsCount})) {
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "Setting typedef sodname to ".$parserState->{lastsymbol}."\n" if ($localDebug || $sodDebug);
$parserState->{sodname} = $parserState->{lastsymbol};
$parserState->{sodclass} = "function";
# DAG: changed to respect freezereturn
# and hollow, but in the unlikely event
# that we should start seeing any weird
# "missing return type info" bugs,
# this next line might need to be
# put back in rather than the lines
# that follow it.
# $parserState->{returntype} = "$declaration$curline";
if (!$parserState->{freezereturn} && $parserState->{hollow}) {
$parserState->{returntype} = "$declaration$curline";
} elsif (!$parserState->{freezereturn} && !$parserState->{hollow}) {
$parserState->{returntype} = "$curline";
$declaration = "";
}
}
$parserState->{posstypesPending} = 0;
if ($parserState->{callbackNamePending} == 2) {
$parserState->{callbackNamePending} = 3;
print STDERR "callbackNamePending -> 3\n" if ($localDebug || $cbnDebug);
}
print STDERR "lparen\n" if ($localDebug);
if ($parserState->{cbsodname} && (scalar(@braceStack)-$parserState->{initbsCount}) == 0) {
if (!$parserState->{functionReturnsCallback}) {
# At the top level, if we see a second open parenthesis after setting a callback
# name, the first token in the first set of open parentheses is the name of
# the callback, so clear cbsodname.
#
# Until this point, the value in cbsodname was a copy of the already-cleared
# sodname field, and would replace the callbackName field at the end of
# processing.
$parserState->{cbsodname} = "";
} else {
# If we are in a function that returns a callback, everything from here on
# is a list of parameters for the callback, not the function, so the
# previous parameter list should be discarded (though it is useful to
# add these parameters as valid things to comment about)
@{$parserState->{parsedParamList}} = @tempppl;
$parserState->{functionReturnsCallback}--;
print STDERR "parsedParamList restored\n" if ($parmDebug);
}
}
if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) {
if ($parserState->{callbackName}) {
$parserState->{cbsodname} = $parserState->{callbackName};
$parserState->{sodclass} = "function";
# $parserState->{callbackName} = "";
$parserState->{functionReturnsCallback}++;
print "Function returning callback. NAME: $parserState->{cbsodname}\n" if ($parmDebug || $localDebug || $parseDebug);
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
print STDERR "parsedParamList wiped\n" if ($parmDebug);
@tempppl = @{$parserState->{parsedParamList}};
@{$parserState->{parsedParamList}} = ();
$parsedParam = "";
}
}
if ($parserState->{inOperator} == 1) {
$parserState->{inOperator} = 2;
}
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [15]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
print STDERR "LASTCHARCHECK: \"$lastchar\" \"$lastnspart\" \"$curline\".\n" if ($localDebug);
if ($lastnspart eq ")") { # || $curline =~ /\)\s*$/so
print STDERR "HERE: DEC IS $declaration\nENDDEC\nCURLINE IS $curline\nENDCURLINE\n" if ($localDebug);
# print STDERR "CALLBACKMAYBE: $parserState->{callbackNamePending} $parserState->{sodclass} ".scalar(@braceStack)."\n";
print STDERR "SBS: ".scalar(@braceStack)."\n" if ($localDebug);
### if (!$parserState->{callbackNamePending} && ($parserState->{sodclass} eq "function") && ((scalar(@braceStack)-$parserState->{initbsCount}) == 1)) { # && $argparse
### # Guess it must be a callback anyway.
### my $temp = pop(@tempppl);
### $parserState->{callbackName} = $temp;
### $parserState->{name} = "";
### $parserState->{sodclass} = "";
### $parserState->{sodname} = "";
### print STDERR "CALLBACKHERE ($temp)!\n" if ($cbnDebug || $parseDebug);
### }
if ($declaration =~ /.*\n(.*?)\n$/so) {
my $lastline = $1;
print STDERR "LL: $lastline\nLLDEC: $declaration" if ($localDebug);
$declaration =~ s/(.*)\n(.*?)\n$/$1\n/so;
$curline = "$lastline $curline";
$curline =~ s/^\s*//so;
$prespace -= 4;
$prespaceadjust += 4;
$forcenobreak = 1;
print STDERR "NEWDEC: $declaration\nNEWCURLINE: $curline\n" if ($localDebug);
} elsif (length($declaration) && $callback_typedef_and_name_on_one_line) {
print STDERR "SCARYCASE\n" if ($localDebug);
$declaration =~ s/\n$//so;
$curline = "$declaration $curline";
$declaration = "";
$prespace -= 4;
$prespaceadjust += 4;
$forcenobreak = 1;
}
} else { print STDERR "OPARENLC: \"$lastchar\"\nCURLINE IS: \"$curline\"\n" if ($localDebug);}
$parserState->{lastsymbol} = "";
$lastchar = $part;
if ($parserState->{startOfDec} == 2) {
$parserState->{sodclass} = "function";
$parserState->{freezereturn} = 1;
$parserState->{returntype} =~ s/^\s*//so;
$parserState->{returntype} =~ s/\s*$//so;
}
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
print STDERR "OUTGOING CURLINE: \"$curline\"\n" if ($localDebug);
last SWITCH;
};
($part eq ")") && do {
print STDERR "CLOSE PAREN: CASE 29\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate && (peek(\@regexpStack) ne "("))) {
if ((scalar(@braceStack)-$parserState->{initbsCount} - $parserState->{functionReturnsCallback}) == 1) {
# stop parameter parsing
$parsedParamParse = 0;
print STDERR "parsedParamParse -> 0\n" if ($parmDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if ($parsedParam ne "void") {
# ignore foo(void)
push(@{$parserState->{parsedParamList}}, $parsedParam);
print STDERR "pushed $parsedParam into parsedParamList [1]\n" if ($parmDebug);
}
$parsedParam = "";
}
$parserState->{onlyComments} = 0;
print STDERR "[j]onlyComments -> 0\n" if ($macroDebug);
print STDERR "rparen\n" if ($localDebug);
my $test = pop(@braceStack); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6a]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if (!($test eq "(")) { # ) brace hack for vi
warn("$filename:$inputCounter: warning: Parentheses do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
# cluck("backtrace follows\n");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace -= 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust -= 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
(casecmp($part, $lbrace, $case_sensitive)) && do {
print STDERR "LEFT BRACE: CASE 30\n" if ($liteDebug);
if ($parserState->{onlyComments} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inChar} && !($inRegexp && $regexpNoInterpolate) && scalar(@parserStack)) {
# Somebody put in a brace in the middle of
# a class or else we're seeing ObjC private
# class bits. Either way, throw away the
# curly brace.
print STDERR "NOINSERT\n" if ($parserStackDebug);
$pushParserStateAtBrace = 1;
# $setNoInsert = 1;
$parserState->{noInsert} = 1;
}
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate)) {
$parserState->{bracePending} = 0;
print STDERR "bracePending -> 0 [brace]\n" if ($localDebug);
$parserState->{onlyComments} = 0;
print STDERR "[k]onlyComments -> 0\n" if ($macroDebug);
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
# print STDERR "statecheck: ".$parserState->{inClass}."X".$parserState->{sodclass}."X".$parserState->{inOperator}."X".$parserState->{occmethod}."\n"; # @@@ CHECKME - Do this for Obj-C methods too?
if (!$parserState->{inClass} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator} || $parserState->{occmethod})) {
# This is the opening brace of a function. Start ignoring everything
# until the matching brace is encountered.
print "seenBraces -> 1\n" if ($parseDebug);
$parserState->{seenBraces} = 1;
if (!$parserState->{stackFrozen}) {
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
@{$parserState->{pplStack}} = ();
}
$parserState->{posstypesPending} = 0;
$parserState->{namePending} = 0;
$parserState->{callbackNamePending} = -1;
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "callbackNamePending -> -1\n" if ($localDebug || $cbnDebug);
print STDERR "lbrace\n" if ($localDebug);
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [16]\n"; }
print STDERR "TN -> 1\n" if ($localDebug);
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
if ($parserState->{INMODULE} == 2) {
# Drop token on the floor.
$treepart = " ";
}
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
(casecmp($part, $rbrace, $case_sensitive)) && do {
print STDERR "RIGHT BRACE: CASE 31\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && !($inRegexp && $regexpNoInterpolate && (peek(\@regexpStack) ne "$lbrace"))) {
my $oldOC = $parserState->{onlyComments};
print STDERR "rbrace???\n" if ($localDebug);
# $parserState->{onlyComments} = 0; # If this is all we've seen, there's either a bug or we're
# unrolling a class or similar anyway.
print STDERR "[l]onlyComments -> 0\n" if ($macroDebug);
my $bsCount = scalar(@braceStack);
if (scalar(@parserStack) && !($bsCount - $parserState->{initbsCount})) {
print STDERR "parserState: ENDOFSTATE\n" if ($parserStackDebug);
if ($parserState->{noInsert} || $oldOC) {
print STDERR "parserState insertion skipped[RBRACE]\n" if ($parserStackDebug || $parserStateInsertDebug);
} elsif ($parserState->{hollow}) {
print STDERR "inserted parser state into tree [RBRACE]\n" if ($parserStateInsertDebug);
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[1].\n";
}
print STDERR "parserState popped from parserStack[rbrace]\n" if ($parserStackDebug);
# print STDERR "PREINMODULE: ".$parserState->{INMODULE}."\n";
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
# print STDERR "INMODULE: ".$parserState->{INMODULE}."\n";
if ($parserState->{INMODULE} == 2) {
# Drop token on the floor.
print STDERR "CURRENT: ".$treeCur->{TOKEN}."\n" if ($localDebug);
$part = "";
print STDERR "INMODULE -> 3\n" if ($localDebug || $moduleDebug);
$parserState->{INMODULE} = 3;
print STDERR "continue -> 0 [1a]\n" if ($localDebug || $liteDebug);
$parserState->{noInsert} = 0;
$continue = 0;
print STDERR "AT END: REALPS IS ".$parserState->{REALPS}."\n" if ($parserStackDebug || $localDebug);
print STDERR "STACK COUNT: ".scalar(@parserStack)."\n" if ($parserStackDebug || $localDebug);
}
if ($lang eq "php" || ($lang eq "C" && $sublang eq "IDL")) {
# print STDERR "PHP OUT OF BRACES?: ".scalar(@braceStack)."\n";
if (scalar(@braceStack) == 1) {
# PHP and IDL classes end at
# the brace.
print STDERR "continue -> 0 [1a]\n" if ($localDebug || $liteDebug);
$continue = 0;
}
}
if ($parserState->{noInsert} && scalar(@parserStack)) {
# This is to handle the end of
# the private vars in an
# Objective C class.
print STDERR "parserState: Hit me.\n" if ($localDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
# It's about to go down by 1.
$parserState->{initbsCount} = scalar(@braceStack) - 1;
}
# $parserState->{onlyComments} = 1;
} else {
print STDERR "NO CHANGE IN PARSER STATE STACK (nPARSERSTACK = ".scalar(@parserStack).", $bsCount != $parserState->{initbsCount})\n" if ($parseDebug || $parserStackDebug);
}
if ((scalar(@braceStack)-$parserState->{initbsCount}) == 1) {
# stop parameter parsing
$parsedParamParse = 0;
print STDERR "parsedParamParse -> 0\n" if ($parmDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) {
# ignore foo(void)
push(@{$parserState->{parsedParamList}}, $parsedParam);
print STDERR "pushed $parsedParam into parsedParamList [1b]\n" if ($parmDebug);
}
$parsedParam = "";
} else {
# start parameter parsing after this token
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
$parsedParamParse = 2;
}
if (scalar(@{$parserState->{parsedParamList}})) {
foreach my $node (@{$parserState->{parsedParamList}}) {
$node =~ s/^\s*//so;
$node =~ s/\s*$//so;
if (length($node)) {
push(@{$parserState->{pplStack}}, $node)
}
}
@{$parserState->{parsedParamList}} = ();
print STDERR "parsedParamList pushed\n" if ($parmDebug);
}
print STDERR "rbrace\n" if ($localDebug);
my $test = pop(@braceStack); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [7]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
if (!($test eq "$lbrace") && (!length($structname) || (!($test eq $structname) && $structisbrace))) {
warn("$filename:$inputCounter: warning: Braces do not match.\nWe may have a problem.\n");
warn("Declaration to date: $declaration$curline\n");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace -= 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust -= 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
}
last SWITCH;
};
# Typedef, struct, enum, and union handlers.
# Merge the '@' symbol onto @protocol, @property, @public, and similar.
(length($part) && length($nextpart) && ((length($propname) && $propname =~ /\@/) || length($objcdynamicname) || length($objcsynthesizename) || length($classregexp) || (length($accessregexp) && $accessregexp =~ /\@/)) && $part =~ /^\@$/ && !$parserState->{inComment} && !$parserState->{inChar} && !$parserState->{inString} && !$parserState->{inInlineComment}) && do {
print STDERR "PROPERTY PREPEND AT (\@): CASE 32\n" if ($liteDebug);
my $temp = "\@".$nextpart;
# print STDERR "TEMP IS $temp PROPNAME is $propname\n";
if ($temp =~ /$accessregexp/) {
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
$parserState->{classIsObjC} = 1;
} elsif ($temp =~ /$classregexp/) {
$nextpart = "\@".$nextpart;
$parserState->{classIsObjC} = 1;
} elsif ($temp =~ /$classclosebraceregexp/) {
$nextpart = "\@".$nextpart;
} elsif ($temp eq $propname) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif (length($requiredregexp) && $temp =~ /$requiredregexp/) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif ($temp eq $objcdynamicname) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
} elsif ($temp eq $objcsynthesizename) {
# This shows up in a declaration, so delete the token
$part = "";
print STDERR "MERGE $part $nextpart\n" if ($localDebug);
$nextpart = "\@".$nextpart;
}
next SWITCH;
};
($modules_are_special && !$parserState->{inTemplate} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && length($moduleregexp) && $part =~ /$moduleregexp/) && do {
print STDERR "INMODULE -> 1\n" if ($localDebug || $moduleDebug);
$parserState->{INMODULE} = 1;
print STDERR "MODULE START TOKEN: CASE 32-M-1\n" if ($localDebug || $liteDebug);
};
(length($classclosebraceregexp) && ($part =~ /$classclosebraceregexp/) && !$parserState->{inComment} && !$parserState->{inChar} && !$parserState->{inString} && !$parserState->{inInlineComment}) && do {
print STDERR "CLASS CLOSE BRACE: CASE 33\n" if ($liteDebug);
if ($part ne peekmatch(\@braceStack, $filename, $inputCounter)) {
warn("$filename:inputCounter: warning: Class braces do not match.\nWe may have a problem.\n");
}
$parserState->{seenBraces} = 1;
pop(@braceStack);
$treeCur->addSibling($part, 0); $treeSkip = 1;
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [6]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
$part =~ s/^\@//s;
if ( 1 || $nextpart ne ";") {
# Objective C protocol/interface declarations end at the close curly brace.
# No ';' necessary (though we'll eat it if it's there.
# No, we won't. Deal with it.
if (scalar(@parserStack) == 1) {
# Throw away current parser state, since
# it will always be empty anyway.
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
$continue = 0;
print STDERR "continue -> 0 [occend]\n" if ($localDebug);
} else {
if (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[\@end]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
print STDERR "inserted parser state into tree [\@end]\n" if ($parserStateInsertDebug);
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[2].\n";
}
print STDERR "parserState: Created parser state[1].\n" if ($parserStackDebug);
print STDERR "CURLINE CLEAR[PRS2]\n" if ($localDebug);
$curline = "";
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
}
print STDERR "parserState popped from parserStack[\@end]\n" if ($parserStackDebug);
$parserState = pop(@parserStack) || $parserState;
$HeaderDoc::module = $parserState->{MODULE};
}
}
# fall through to next case. WHY???
};
(!$parserState->{inTemplate} && !$parserState->{inComment} && !$parserState->{inInlineComment} && !$parserState->{inString} && !$parserState->{inChar} && length($classregexp) && $part =~ /$classregexp/) && do {
print STDERR "START OF CLASS: CASE 34\n" if ($liteDebug);
### if ($parserState->{classIsObjC}) { $sublang = "occ"; }
### else { $sublang = "cpp"; }
### print STDERR "LANG $lang SUBLANG $sublang\n" if ($localDebug || $parseDebug || $classDebug);
### # Update the class regular expressions because our language has changed.
### ($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
### $soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
### $enumname,
### $typedefname, $varname, $constname, $structisbrace, $macronameref,
### $classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
### $requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
### print STDERR "PROPNAME NOW $propname\n" if ($localDebug || $parseDebug || $classDebug);
my $localclasstype = $1;
if ($part =~ /^\@/) { $part =~ s/^\@//s; }
if (!(scalar(@braceStack)-$parserState->{initbsCount})) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
print STDERR "ITISACLASS\n" if ($localDebug);
if (!length($parserState->{sodclass})) {
print STDERR "GOOD.\n" if ($localDebug);
$parserState->{inClass} = 1;
print STDERR "inClass -> 1 [7]\n" if ($classDebug);
$pushParserStateAtBrace = 1;
if ($localclasstype =~ /\@interface/) {
$parserState->{inClass} = 2;
print STDERR "inClass -> 2 [8]\n" if ($classDebug);
$pushParserStateAtBrace = 0;
} elsif ($localclasstype =~ /\@protocol/) {
$pushParserStateAtBrace = 0;
$pushParserStateAfterWordToken = 0;
$parserState->{inClass} = 0;
print STDERR "inClass -> 0 [9]\n" if ($classDebug);
$parserState->{inProtocol} = 1;
} elsif ($localclasstype =~ /\@implementation/) {
$pushParserStateAtBrace = 0;
$pushParserStateAfterWordToken = 2;
}
$parserState->{sodclass} = "class";
$parserState->{classtype} = $localclasstype;
$parserState->{preclasssodtype} = $parserState->{sodtype} . $part;
$parserState->{sodtype} = "";
$parserState->{startOfDec} = 1;
$parserState->{onlyComments} = 0;
print STDERR "[m]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
# Get the parse tokens from Utilities.pm.
if (length($classbraceregexp) && ($localclasstype =~ /$classbraceregexp/)) {
print STDERR "CLASS ($localclasstype) IS A BRACE.\n" if ($localDebug);
push(@braceStack, $localclasstype); pbs(@braceStack);
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [17]\n"; }
# } else {
# print STDERR "CBRE: \"$classbraceregexp\"\n";
}
($lang, $sublang) = getLangAndSublangFromClassType($localclasstype);
$HeaderDoc::lang = $lang;
$HeaderDoc::sublang = $sublang;
($sotemplate, $eotemplate, $operator, $soc, $eoc, $ilc, $ilc_b, $sofunction,
$soprocedure, $sopreproc, $lbrace, $rbrace, $unionname, $structname,
$enumname,
$typedefname, $varname, $constname, $structisbrace, $macronameref,
$classregexp, $classbraceregexp, $classclosebraceregexp, $accessregexp,
$requiredregexp, $propname, $objcdynamicname, $objcsynthesizename, $moduleregexp, $definename) = parseTokens($lang, $sublang);
my $macrore = macroRegexpFromList($macronameref);
# print STDERR "PROPNAME2: $propname\n";
print STDERR "ARP: $accessregexp\n" if ($localDebug);
last SWITCH;
}
}
}
};
($part eq $objcdynamicname) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $objcsynthesizename) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $propname) && do {
print STDERR "PROPERTY: CASE 35\n" if ($liteDebug);
print STDERR "PROPERTY FOUND\n" if ($localDebug);
$parserState->{isProperty} = 1; # Basically treat it like a normal variable, but flag it.
last SWITCH;
};
($part eq $structname || $part eq $enumname || $part eq $unionname) && do {
print STDERR "STRUCT/ENUM/UNION: CASE 36\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($structisbrace) {
if ($parserState->{sodclass} eq "function") {
$parserState->{seenBraces} = 1;
if (!$parserState->{stackFrozen}) {
@{$parserState->{freezeStack}} = @{$parserState->{pplStack}};
$parserState->{frozensodname} = $parserState->{sodname};
$parserState->{stackFrozen} = 1;
}
@{$parserState->{pplStack}} = ();
}
$parserState->{posstypesPending} = 0;
$parserState->{callbackNamePending} = -1;
$parserState->{simpleTypedef} = 0;
$parserState->{simpleTDcontents} = "";
print STDERR "callbackNamePending -> -1\n" if ($localDebug || $cbnDebug);
print STDERR "lbrace\n" if ($localDebug);
push(@braceStack, $part); pbs(@braceStack);
if (!$parserState->{seenBraces}) { # TREEDONE
$treeNest = 1;
if ($treeDebug) { print STDERR "TS TREENEST -> 1 [18]\n"; }
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
}
$curline = spacefix($curline, $part, $lastchar);
$parserState->{lastsymbol} = "";
$lastchar = $part;
$parserState->{startOfDec} = 0;
if ($curline !~ /\S/o) {
# This is the first symbol on the line.
# adjust immediately
$prespace += 4;
print STDERR "PS: $prespace immediate\n" if ($localDebug);
} else {
$prespaceadjust += 4;
print STDERR "PSA: $prespaceadjust\n" if ($localDebug);
}
} else {
if (!$parserState->{simpleTypedef}) {
print STDERR "simpleTypedef -> 2\n" if ($localDebug);
$parserState->{simpleTypedef} = 2;
}
# if (!$parserState->{seenBraces}) { # TREEDONE
# $treePopTwo++;
# $treeNest = 1;
# push(@treeStack, $treeCur);
# $treeCur = $treeCur->addChild($part, 0); $treeSkip = 1;
# bless($treeCur, "HeaderDoc::ParseTree");
# }
}
$parserState->{onlyComments} = 0;
print STDERR "[n]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
# $parserState->{simpleTypedef} = 0;
if ($parserState->{basetype} eq "") { $parserState->{basetype} = $part; }
# fall through to default case when we're done.
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString} || $parserState->{inChar})) {
$parserState->{namePending} = 2;
print STDERR "namePending -> 2 [2]\n" if ($parseDebug);
if ($parserState->{posstypesPending}) { $parserState->{posstypes} .=" $part"; }
}
if ($parserState->{sodclass} eq "") {
$parserState->{startOfDec} = 0; $parserState->{sodname} = "";
print STDERR "sodname cleared (seu)\n" if ($sodDebug);
}
$lastchar = $part;
}; # end if
}; # end do
($part =~ /^$typedefname$/) && do {
print STDERR "TYPEDEF: CASE 37\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (!(scalar(@braceStack)-$parserState->{initbsCount})) { $parserState->{callbackIsTypedef} = 1; $parserState->{inTypedef} = 1; }
$parserState->{onlyComments} = 0;
print STDERR "[o]onlyComments -> 0\n" if ($macroDebug);
$continuation = 1;
$parserState->{simpleTypedef} = 1; print STDERR "simpleTypedef -> 1\n" if ($localDebug);
# previous case falls through, so be explicit.
if ($part =~ /^$typedefname$/) {
if (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inString} || $parserState->{inChar})) {
if ($pascal) {
$parserState->{namePending} = 2;
$inPType = 1;
print STDERR "namePending -> 2 [3]\n" if ($parseDebug);
}
if ($parserState->{posstypesPending}) { $parserState->{posstypes} .=" $part"; }
if (!($parserState->{callbackNamePending})) {
print STDERR "callbackNamePending -> 1\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 1;
}
}
}
if ($parserState->{sodclass} eq "") {
$parserState->{startOfDec} = 0; $parserState->{sodname} = "";
print STDERR "sodname cleared ($typedefname)\n" if ($sodDebug);
}
$lastchar = $part;
}; # end if
}; # end do
# C++ operator keyword handler
($part eq "$operator") && do {
print STDERR "OPERATOR KEYWORD: CASE 38\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{inOperator} = 1;
$parserState->{sodname} = "";
}
$parserState->{lastsymbol} = $part;
$lastchar = $part;
last SWITCH;
# next;
};
# Punctuation handlers
($part =~ /;/o) && do {
print STDERR "SEMICOLON: CASE 39\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if ($parsedParamParse) {
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) { push(@{$parserState->{parsedParamList}}, $parsedParam); }
print STDERR "pushed $parsedParam into parsedParamList [2semi]\n" if ($parmDebug);
$parsedParam = "";
}
# skip this token
$parsedParamParse = 2;
$parserState->{freezereturn} = 1;
# $parserState->{onlyComments} = 0; # If this is all we've seen, there's either a bug or we're
# unrolling a class or similar anyway.
$parserState->{temponlyComments} = $parserState->{onlyComments};
print STDERR "[p]onlyComments -> 0\n" if ($macroDebug);
print STDERR "valuepending -> 0\n" if ($valueDebug);
$parserState->{valuepending} = 0;
$continuation = 1;
if ($parserState->{occmethod}) {
$prespaceadjust = -$prespace;
}
# previous case falls through, so be explicit.
if ($part =~ /;/o && !$parserState->{inMacroLine} && !$parserState->{inMacro}) {
my $bsCount = scalar(@braceStack)-$parserState->{initbsCount};
if (!$bsCount && !$parserState->{kr_c_function}) {
if ($parserState->{startOfDec} == 2) {
$parserState->{sodclass} = "constant";
$parserState->{startOfDec} = 1;
} elsif (!($parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{inString})) {
$parserState->{startOfDec} = 1;
}
# $parserState->{lastsymbol} .= $part;
}
if (!$bsCount) {
$treeCur = $treeCur->addSibling(";"); $treepart = " "; # $treeSkip = 1;
if (0) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [8]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
# $parserState->{lastTreeNode} = $treeCur;
# print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n";
while ($parserState->{treePopTwo}--) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [9]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
$parserState->{treePopTwo} = 0;
}
}
$lastchar = $part;
}; # end if
}; # end do
($part eq "=" && ($parserState->{lastsymbol} ne "operator") && (!(($parserState->{inOperator} == 1) && $parserState->{lastsymbol} =~ /\W/ && $parserState->{lastsymbol} =~ /\S/)) && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) && do {
print STDERR "EQUALS: CASE 40\n" if ($liteDebug);
$parserState->{onlyComments} = 0;
print STDERR "[q]onlyComments -> 0\n" if ($macroDebug);
if ($part =~ /=/o && !(scalar(@braceStack)-$parserState->{initbsCount}) &&
$nextpart !~ /=/o && $lastchar !~ /=/o &&
$parserState->{sodclass} ne "function" && !$inPType) {
print STDERR "valuepending -> 1\n" if ($valueDebug);
$parserState->{valuepending} = 1;
$parserState->{preEqualsSymbol} = $parserState->{lastsymbol};
$parserState->{sodclass} = "constant";
$parserState->{startOfDec} = 0;
}; # end if
}; # end do
($part =~ /,/o) && do {
print STDERR "COMMA: CASE 41\n" if ($liteDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
$parserState->{onlyComments} = 0;
print STDERR "[r]onlyComments -> 0\n" if ($macroDebug);
}
if ($part =~ /,/o && $parsedParamParse && !($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) && ((scalar(@braceStack)-$parserState->{initbsCount}-$parserState->{functionReturnsCallback}) == 1) && (peek(\@braceStack) eq '(' || peek(\@braceStack) eq '{')) {
print STDERR "$part is a comma\n" if ($localDebug || $parseDebug);
$parsedParam =~ s/^\s*//so; # trim leading space
$parsedParam =~ s/\s*$//so; # trim trailing space
if (length($parsedParam)) { push(@{$parserState->{parsedParamList}}, $parsedParam); }
print STDERR "pushed $parsedParam into parsedParamList [2]\n" if ($parmDebug);
$parsedParam = "";
# skip this token
$parsedParamParse = 2;
print STDERR "parsedParamParse -> 2\n" if ($parmDebug);
}; # end if
}; # end do
($part =~ /[*^]/) && do {
if ($lastnspart eq "(" && # ")"
!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) &&
!$parserState->{callbackNamePending} &&
((scalar(@braceStack)-$parserState->{initbsCount}) == 1)) {
# print "CBNP\n";
$parserState->{callbackNamePending} = 3;
}
# Fall through to the default case.
}; # end star/asterisk/caret case
{ # SWITCH default case
print STDERR "DEFAULT CASE: CASE 42\n" if ($liteDebug);
# Handler for all other text (data types, string contents,
# comment contents, character contents, etc.)
print STDERR "DEFAULT CASE\n" if ($localDebug || $parseDebug);
# print STDERR "TEST CURLINE IS \"$curline\".\n";
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar})) {
if (!ignore($part, $ignoreref, $perheaderignoreref)) {
if ($part =~ /\S/o) {
$parserState->{onlyComments} = 0;
print STDERR "[s]onlyComments -> 0\n" if ($macroDebug);
}
if (!$continuation && !$occspace) {
$curline = spacefix($curline, $part, $lastchar);
} else {
$continuation = 0;
$occspace = 0;
}
# print STDERR "BAD CURLINE IS \"$curline\".\n";
if (length($part) && !($parserState->{inComment} || $parserState->{inInlineComment})) {
if ($localDebug && $lastchar eq ")") {print STDERR "LC: $lastchar\nPART: $part\n";}
# print STDERR "XXX LC: $lastchar SC: $parserState->{sodclass} LG: $lang\n";
if ($lastchar eq ")" && $parserState->{sodclass} eq "function" && ($lang eq "C" || $lang eq "Csource") && !(scalar(@braceStack)-$parserState->{initbsCount})) {
if ($part !~ /^\s*;/o) {
# warn "K&R C FUNCTION FOUND.\n";
# warn "NAME: $parserState->{sodname}\n";
if (!isKeyword($part, $keywordhashref, $case_sensitive)) {
my $tempavail = ignore($part, $ignoreref, $perheaderignoreref);
if (!$tempavail) {
print STDERR "K&R C FUNCTION FOUND [2].\n" if ($localDebug);
print STDERR "TOKEN: \"$part\"\n" if ($localDebug);
print STDERR "TA: \"$tempavail\"\n" if ($localDebug);
$parserState->{kr_c_function} = 1;
$parserState->{kr_c_name} = $parserState->{sodname};
$parsedParamParse = 1;
print STDERR "parsedParamParse -> 1\n" if ($parmDebug);
}
}
}
}
$lastchar = $part;
if ($part =~ /\w/o || $part eq "::") {
if ($parserState->{callbackNamePending} == 1) {
if (!($part eq $structname || $part eq $enumname || $part eq $unionname || $part eq $typedefname)) {
# we've seen the initial type. The name of
# the callback is after the next open
# parenthesis.
print STDERR "callbackNamePending -> 2\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 2;
}
} elsif ($parserState->{callbackNamePending} == 3) {
print STDERR "callbackNamePending -> 4\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 4;
$parserState->{callbackName} = $part;
$parserState->{name} = "";
$parserState->{sodclass} = "";
$parserState->{cbsodname} = $parserState->{sodname};
$parserState->{sodname} = "";
} elsif ($parserState->{callbackNamePending} == 4) {
if ($part eq "::") {
print STDERR "callbackNamePending -> 5\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 5;
$parserState->{callbackName} .= $part;
} elsif ($part !~ /\s/o) {
print STDERR "callbackNamePending -> 0\n" if ($localDebug || $cbnDebug);
$parserState->{callbackNamePending} = 0;
}
} elsif ($parserState->{callbackNamePending} == 5) {
if ($part !~ /\s/o) {
print STDERR "callbackNamePending -> 4\n" if ($localDebug || $cbnDebug);
if ($part !~ /\*/ && $part !~ /\^/) {
$parserState->{callbackNamePending} = 4;
}
$parserState->{callbackName} .= $part;
}
}
if ($parserState->{namePending} == 2) {
$parserState->{namePending} = 1;
print STDERR "namePending -> 1 [4]\n" if ($parseDebug);
if (!(scalar(@braceStack)-$parserState->{initbsCount}) && ($parserState->{simpleTypedef} == 2)) {
print STDERR "bracePending -> 1\n" if ($localDebug);
$parserState->{bracePending} = 1;
}
} elsif ($parserState->{namePending}) {
if ($parserState->{name} eq "") { $parserState->{name} = $part; }
$parserState->{namePending} = 0;
print STDERR "namePending -> 0 [5]\n" if ($parseDebug);
} elsif ($parserState->{bracePending} == 1) {
if ($part eq "::") {
# struct foo::bar ....
# "foo::bar" is the name of
# the struct and should not
# trigger this (though we might
# trigger it on the following
# word.
print STDERR "bracePending -> 2 [classmember]\n" if ($localDebug);
$parserState->{bracePending} = 2;
} else {
# Word token when brace pending. It's
# a variable.
print STDERR "IT'S A VARIABLE! NAME WAS \"$part\".\n" if ($localDebug);
print STDERR "Word token before brace. Setting sodname to ".$parserState->{lastsymbol}."\n" if ($localDebug || $sodDebug);
$parserState->{sodname} = $part;
# $parserState->{sodtype} = $parserState->{returntype}; # . " " . $parserState->{name};
$parserState->{sodtype} = "$declaration$curline";
$parserState->{sodclass} = "constant";
$parserState->{frozensodname} = $part;
print STDERR "bracePending -> 0 [word]\n" if ($localDebug);
$parserState->{bracePending} = 0;
}
} elsif ($parserState->{bracePending} == 2) {
$parserState->{bracePending}--;
}
} # end if ($part =~ /\w/o)
if ($part !~ /[,;\[\]]/o && !$parserState->{inBrackets}) {
my $opttilde = "";
if ($parserState->{seenTilde}) { $opttilde = "~"; }
print STDERR "CHECKPOINT: INTEMPLATE IS ".$parserState->{inTemplate}." SOD IS ".$parserState->{startOfDec}."\n" if ($localDebug || $sodDebug);
if ($parserState->{startOfDec} == 1) { # @@@ FIXME DAG. This should not set sodname, but otherwise, we're losing classes!!!
if (!$parserState->{inTemplate}) {
print STDERR "Setting sodname (maybe type) to \"$part\"\n" if ($sodDebug);
$parserState->{sodname} = $opttilde.$part;
if ($part =~ /\w/o) {
$parserState->{startOfDec}++;
}
} else {
print STDERR "Not adjusting startOfDec or sodname because in template.\n" if ($localDebug || $sodDebug);
}
} elsif ($parserState->{startOfDec} == 2) {
if ($part =~ /\w/o && !$parserState->{inTemplate}) {
$parserState->{preTemplateSymbol} = "";
}
if (!$parserState->{inTemplate}) {
if ($parserState->{inOperator} == 1) {
$parserState->{sodname} .= $part;
} else {
if (length($parserState->{sodname})) {
$parserState->{sodtype} .= " $parserState->{sodname}";
}
$parserState->{sodname} = $opttilde.$part;
}
print STDERR "sodname set to $part\n" if ($sodDebug);
} else {
print STDERR "Not adjusting startOfDec or sodname because in template.\n" if ($localDebug || $sodDebug);
}
} else {
$parserState->{startOfDec} = 0;
}
} elsif ($part eq "[") { # if ($part !~ /[;\[\]]/o)
$parserState->{inBrackets} += 1;
print STDERR "inBrackets -> $parserState->{inBrackets}\n" if ($sodDebug);
} elsif ($part eq "]") {
$parserState->{inBrackets} -= 1;
print STDERR "inBrackets -> $parserState->{inBrackets}\n" if ($sodDebug);
} # end if ($part !~ /[;\[\]]/o)
if (!($part eq $eoc)) {
print STDERR "SETTING LS ($part)\n" if ($parseDebug);
if ($parserState->{typestring} eq "") { $parserState->{typestring} = $part; }
if ($parserState->{lastsymbol} =~ /\,\s*$/o) {
$parserState->{lastsymbol} .= $part;
} elsif ($parserState->{inTypedef} && !(scalar(@braceStack)-$parserState->{initbsCount}) && $part =~ /,/) {
$parserState->{lastsymbol} .= $part;
} elsif ($part =~ /^\s*\;\s*$/o) {
$parserState->{lastsymbol} .= $part;
} elsif (length($part)) {
# warn("replacing lastsymbol with \"$part\"\n");
$parserState->{lastsymbol} = $part;
}
} # end if (!($part eq $eoc))
} # end if (length($part) && !($parserState->{inComment} || $parserState->{inInlineComment}))
}
} # end if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}))
} # end SWITCH default case
} # end SWITCH
if ($parserState->{seenBraces}) {
# print "SEENBRACES. TP: $treepart PT: $part\n";
if ($treepart) {
$parserState->{functionContents} .= $treepart;
} else {
$parserState->{functionContents} .= $part;
}
# print "SEENBRACES. FC: ".$parserState->{functionContents}."\n";
}
if ($part !~ /\\/o) {
if (!($parserState->{inMacro} || $parserState->{inMacroLine}) || $part !~ /\s/) {
$parserState->resetBackslash();
}
}
if (length($part)) { $lasttoken = $part; }
if (length($part) && $inRegexpTrailer) { --$inRegexpTrailer; }
if ($postPossNL) { --$postPossNL; }
if (($parserState->{simpleTypedef} == 1) && ($part ne $typedefname) &&
!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} ||
$inRegexp)) {
# print STDERR "NP: $parserState->{namePending} PTP: $parserState->{posstypesPending} PART: $part\n";
$parserState->{simpleTDcontents} .= $part;
}
my $ignoretoken = ignore($part, $ignoreref, $perheaderignoreref);
my $hide = ( $hideTokenAndMaybeContents ||
( $ignoretoken &&
!( $parserState->{inString} || $parserState->{inComment} ||
$parserState->{inInlineComment} || $parserState->{inChar}
)
)
);
print STDERR "TPONL: $treePopOnNewLine TPTWO: ".$parserState->{treePopTwo}."\n" if ($tsDebug);
print STDERR "TN: $treeNest TS: $treeSkip nTS: ".scalar(@treeStack)."\n" if ($tsDebug || $parserStateInsertDebug);
print STDERR "sethollow: $sethollow\n" if ($parserStateInsertDebug);
if (!$treeSkip) {
if (!$parserState->{seenBraces}) { # TREEDONE
if ($treeNest != 2) {
# If we really want to skip and nest, set treeNest to 2.
if (length($treepart)) {
if ((($parserState->{inComment} == 1) || ($parserState->{inInlineComment} == 1)) && $treepart !~ /[\r\n!]/) {
$treeCur->token($treeCur->token() . $treepart);
# print STDERR "SHORT\n";
} else {
$treeCur = $treeCur->addSibling($treepart, $hide);
}
$treepart = "";
} else {
if ((($parserState->{inComment} == 1) || ($parserState->{inInlineComment} == 1)) && $treepart !~ /[\r\n!]/) {
$treeCur->token($treeCur->token() . $part);
# print STDERR "SHORT\n";
} else {
$treeCur = $treeCur->addSibling($part, $hide);
}
}
bless($treeCur, "HeaderDoc::ParseTree");
}
# print STDERR "TC IS $treeCur\n";
# $treeCur = %{$treeCur};
if ($treeNest) {
if ($sethollow) {
print STDERR "WILL INSERT STATE $parserState (SETHOLLOW) at ".$treeCur->token()."\n" if ($parserStackDebug);
# $parserState->{hollow} = $treeCur;
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$sethollow = 0;
}
print STDERR "TSPUSH\n" if ($tsDebug || $treeDebug);
push(@treeStack, $treeCur);
$treeCur = $treeCur->addChild("", 0);
bless($treeCur, "HeaderDoc::ParseTree");
}
}
}
if ($parserState->{inComment} > 1) { $parserState->{inComment}--; }
if ($parserState->{inInlineComment} > 1) { $parserState->{inInlineComment}--; }
if (($parserState->{inComment} == 1) && $treepart eq "!") {
$parserState->{inComment} = 3;
}
if (($parserState->{inInlineComment} == 1) && $treepart eq "!") {
$parserState->{inInlineComment} = 3;
}
$treeNest = 0;
if ($treeDebug) { print STDERR "TS TREENEST -> 0 [19]\n"; }
if (!$parserState->{freezereturn} && $parserState->{hollow}) {
# print STDERR "WARNING: RETURN TYPE CHANGE[A]".$parserState->{returntype}." CHANGED TO $declaration$curline.\n";
$parserState->{returntype} = "$declaration$curline";
} elsif (!$parserState->{freezereturn} && !$parserState->{hollow}) {
# print STDERR "WARNING: RETURN TYPE CHANGE[B]".$parserState->{returntype}." CHANGED TO $curline.\n";
$parserState->{returntype} = "$curline";
$declaration = "";
# } else {
# print STDERR "WARNING: LEAVING RETURN TYPE ALONE: ".$parserState->{returntype}." NOT CHANGED TO $curline.\n";
}
# From here down is... magic. This is where we figure out how
# to handle parsed parameters, K&R C types, and in general,
# determine whether we've received a complete declaration or not.
#
# About 90% of this is legacy code to handle proper spacing.
# Those bits got effectively replaced by the parseTree class.
# The only way you ever see this output is if you don't have
# any styles defined in your config file.
if (($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) ||
!$ignoretoken) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar}) &&
!$ppSkipOneToken) {
if ($parsedParamParse == 1) {
$parsedParam .= $part;
} elsif ($parsedParamParse == 2) {
$parsedParamParse = 1;
print STDERR "parsedParamParse -> 1\n" if ($parmDebug);
}
}
if ($ppSkipOneToken) {
$hollowskip = $ppSkipOneToken;
print STDERR "hollowskip -> $ppSkipOneToken (ppSkipOneToken)\n" if ($parserStateInsertDebug);
}
$ppSkipOneToken = 0;
print STDERR "MIDPOINT CL: $curline\nDEC:$declaration\nSCR: \"$scratch\"\n" if ($localDebug);
if (!$parserState->{seenBraces}) {
# Add to current line (but don't put inline function/macro
# declarations in.
if ($parserState->{inString}) {
$curstring .= $part;
} else {
if (length($curstring)) {
if (length($curline) + length($curstring) >
$HeaderDoc::maxDecLen) {
$scratch = nspaces($prespace);
# Was != /\n/ which is clearly
# wrong. Suspect the next line
# if we start losing leading spaces
# where we shouldn't (or don't where
# we should). Also was just /g.
if ($curline !~ /^\s*\n/so) { $curline =~ s/^\s*//sgo; }
# NEWLINE INSERT
print STDERR "CURLINE CLEAR [1]\n" if ($localDebug);
$declaration .= "$scratch$curline\n";
$curline = "";
$prespace += $prespaceadjust;
$prespaceadjust = 0;
$prespaceadjust -= 4;
$prespace += 4;
} else {
# no wrap, so maybe add a space.
if ($lastchar =~ /\=$/o) {
$curline .= " ";
}
}
$curline .= $curstring;
$curstring = "";
}
if ((length($curline) + length($part) > $HeaderDoc::maxDecLen)) {
$scratch = nspaces($prespace);
# Was != /\n/ which is clearly
# wrong. Suspect the next line
# if we start losing leading spaces
# where we shouldn't (or don't where
# we should). Also was /g instead of /sg.
if ($curline !~ /^\s*\n/so) { $curline =~ s/^\s*//sgo; }
# NEWLINE INSERT
$declaration .= "$scratch$curline\n";
print STDERR "CURLINE CLEAR [2]\n" if ($localDebug);
$curline = "";
$prespace += $prespaceadjust;
$prespaceadjust = 0;
$prespaceadjust -= 4;
$prespace += 4;
}
if (length($curline) || $part ne " ") {
# Add it to curline unless it's a space that
# has inadvertently been wrapped to the
# start of a line.
$curline .= $part;
}
}
if (peek(\@braceStack) ne "<") {
if ($part =~ /\n/o || ($part =~ /[\(;,]/o && $nextpart !~ /\n/o &&
!$parserState->{occmethod}) ||
($part =~ /[:;.]/o && $nextpart !~ /\n/o &&
$parserState->{occmethod})) {
if ($curline !~ /\n/o && !($parserState->{inMacro} || ($pascal && (scalar(@braceStack)-$parserState->{initbsCount})) || $parserState->{inInlineComment} || $parserState->{inComment} || $parserState->{inString})) {
# NEWLINE INSERT
$curline .= "\n";
}
# Add the current line to the declaration.
$scratch = nspaces($prespace);
if ($curline !~ /\n/o) { $curline =~ s/^\s*//go; }
if ($declaration !~ /\n\s*$/o) {
$scratch = " ";
if ($localDebug) {
my $zDec = $declaration;
$zDec = s/ /z/sg;
$zDec = s/\t/Z/sg;
print STDERR "ZEROSCRATCH\n";
print STDERR "zDec: \"$zDec\"\n";
}
}
$declaration .= "$scratch$curline";
print STDERR "CURLINE CLEAR [3]\n" if ($localDebug);
$curline = "";
# $curline = nspaces($prespace);
print STDERR "PS: $prespace -> " . $prespace + $prespaceadjust . "\n" if ($localDebug);
$prespace += $prespaceadjust;
$prespaceadjust = 0;
} elsif ($part =~ /[\(;,]/o && $nextpart !~ /\n/o &&
($parserState->{occmethod} == 1)) {
print STDERR "SPC\n" if ($localDebug);
$curline .= " "; $occspace = 1;
} else {
print STDERR "NOSPC: $part:$nextpart:$parserState->{occmethod}\n" if ($localDebug);
}
}
}
if ($parserState->{temponlyComments}) {
# print STDERR "GOT TOC: ".$parserState->{temponlyComments}."\n";
$parserState->{onlyComments} = $parserState->{temponlyComments};
$parserState->{temponlyComments} = undef;
}
print STDERR "CURLINE IS \"$curline\".\n" if ($localDebug);
my $bsCount = scalar(@braceStack);
print STDERR "ENDTEST: $bsCount \"$parserState->{lastsymbol}\"\n" if ($localDebug);
print STDERR "KRC: $parserState->{kr_c_function} SB: $parserState->{seenBraces}\n" if ($localDebug);
if (!($bsCount - $parserState->{initbsCount}) && $parserState->{lastsymbol} =~ /;\s*$/o) {
# print STDERR "DPA\n";
if ((!$parserState->{kr_c_function} || $parserState->{seenBraces}) && !$parserState->{inMacro}) {
# print STDERR "DPB\n";
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [3]\n" if ($localDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[SEMI-1]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} elsif ($parserState->{classtype} && length($parserState->{classtype})) {
warn "Couldn't insert info into parse tree[3class].\n" if ($localDebug);
} else {
warn "Couldn't insert info into parse tree[3].\n";
print STDERR "Printing tree.\n";
$parserState->print();
$treeTop->dbprint();
}
print STDERR "parserState: Created parser state[2].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "NEWRETURNTYPE: $parserState->{returntype}\n" if ($localDebug);
print STDERR "CURLINE CLEAR[PRS2]\n" if ($localDebug);
$curline = "";
}
}
} else {
print STDERR "bsCount: $bsCount - $parserState->{initbsCount}, ls: $parserState->{lastsymbol}\n" if ($localDebug);
pbs(@braceStack);
}
if (!($bsCount - $parserState->{initbsCount}) && $parserState->{seenBraces} && ($parserState->{sodclass} eq "function" || $parserState->{inOperator}) &&
($nextpart ne ";")) {
# Function declarations end at the close curly brace.
# No ';' necessary (though we'll eat it if it's there.
if ($parserState->{treePopTwo}) {
# Fix nesting.
# print STDERR "LASTTREENODE -> $treeCur (".$treeCur->token().")\n";
while ($parserState->{treePopTwo}--) {
$treeCur = pop(@treeStack) || $treeTop;
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
$treeCur = $treeCur->lastSibling();
$treeCur->parsedParamCopy(\@{$parserState->{parsedParamList}});
print STDERR "TSPOP [13]\n" if ($tsDebug || $treeDebug);
bless($treeCur, "HeaderDoc::ParseTree");
}
$treeCur = $treeCur->addSibling(";", 0);
$parserState->{lastTreeNode} = $treeCur;
$parserState->{treePopTwo} = 0;
}
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [4]\n" if ($localDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped[SEMI-2]\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[4].\n";
}
print STDERR "parserState: Created parser state[3].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "CURLINE CLEAR[PRS3]\n" if ($localDebug);
$curline = "";
}
}
print STDERR "INMACRO: ".$parserState->{inMacro}."\n" if ($localDebug || $cppDebug || $cppDebug);
# $parserState->{lastsymbol} ne "\\"
print STDERR "IM: ".$parserState->{inMacro}." IQ: ".$parserState->isQuoted($lang, $sublang)."\n" if ($localDebug);
if (($parserState->{inMacro} == 3 && !$parserState->isQuoted($lang, $sublang)) || $parserState->{inMacro} == 4) {
print STDERR "CHECKPART AGAINST NEWLINE\n" if ($localDebug || $cppDebug);
if ($part =~ /[\n\r]/o && !$parserState->{inComment}) {
print STDERR "MLS: $parserState->{lastsymbol}\n" if ($macroDebug);
print STDERR "PARSER STACK CONTAINS ".scalar(@parserStack)." FRAMES\n" if ($cppDebug || $parserStackDebug);
if (!scalar(@parserStack)) {
$continue = 0;
print STDERR "continue -> 0 [5]\n" if ($localDebug || $liteDebug);
} elsif (!$parserState->{onlyComments}) {
# Process entry here
print STDERR "NOT setting continue to 0 for macro: parser stack nonempty\n" if ($liteDebug);
print STDERR "DONE WITH MACRO. HANDLING.\n" if ($localDebug || $parseDebug);
if ($parserState->{inMacro} == 3) {
if (!$HeaderDoc::skipNextPDefine) {
cpp_add($parserState->{hollow});
} else {
cpp_add($parserState->{hollow}, 1);
$HeaderDoc::skipNextPDefine = 0;
}
}
if ($parserState->{noInsert}) {
print STDERR "parserState insertion skipped\n" if ($parserStackDebug);
} elsif ($parserState->{hollow}) {
my $treeRef = $parserState->{hollow};
$parserState->{lastTreeNode} = $treeCur;
$treeRef->addRawParsedParams(\@{$parserState->{parsedParamList}});
$treeRef->parserState($parserState);
} else {
warn "Couldn't insert info into parse tree[5].\n";
}
print STDERR "parserState: Created parser state[4].\n" if ($parserStackDebug);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
print STDERR "CURLINE CLEAR[PRS4]\n" if ($localDebug);
$curline = "";
}
}
} elsif ($parserState->{inMacro} == 2) {
my $linenum = $inputCounter + $fileoffset;
warn "$filename:$linenum: warning: Declaration starts with # but is not preprocessor macro\n";
warn "PART: $part\n";
} elsif ($parserState->{inMacro} == 3 && $parserState->isQuoted($lang, $sublang)) {
# $parserState->{lastsymbol} eq "\\"
print STDERR "TAIL BACKSLASH ($continue)\n" if ($localDebug || $macroDebug);
}
if ($parserState->{valuepending} == 2) {
# skip the "=" part;
$parserState->{value} .= $part;
} elsif ($parserState->{valuepending}) {
$parserState->{valuepending} = 2;
print STDERR "valuepending -> 2\n" if ($valueDebug);
}
} # end if "we're not ignoring this token"
print STDERR "OOGABOOGA\n" if ($parserStackDebug);
if ($pushParserStateAfterToken == 1) {
print STDERR "parserState pushed onto stack[token]\n" if ($parserStackDebug);
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterToken = 0;
$pushParserStateAtBrace = 0;
} elsif ($pushParserStateAfterWordToken == 1) {
if ($part =~ /\w/) {
print STDERR "parserState pushed onto stack[word]\n" if ($parserStackDebug);
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$pushParserStateAfterWordToken = 0;
}
} elsif ($pushParserStateAfterWordToken) {
print STDERR "PPSAFTERWT CHANGED $pushParserStateAfterWordToken -> " if ($parserStackDebug);
$pushParserStateAfterWordToken--;
print STDERR "$pushParserStateAfterWordToken\n" if ($parserStackDebug);
} elsif ($pushParserStateAtBrace) {
print STDERR "PPSatBrace?\n" if ($parserStackDebug);
if (casecmp($part, $lbrace, $case_sensitive)) {
$parserState->{ISFORWARDDECLARATION} = 0;
print STDERR "parserState pushed onto stack[brace]\n" if ($parserStackDebug);
# if ($pushParserStateAtBrace == 2) {
# print STDERR "NOINSERT parserState: $parserState\n" if ($parserStackDebug);
# $parserState->{hollow} = undef;
# $parserState->{noInsert} = 1;
# }
$parserState->{lastTreeNode} = $treeCur;
$curline = "";
push(@parserStack, $parserState);
$parserState = HeaderDoc::ParserState->new();
$parserState->{skiptoken} = 1;
$parserState->{lang} = $lang;
$parserState->{inputCounter} = $inputCounter;
$parserState->{initbsCount} = scalar(@braceStack);
$parserState->{noInsert} = $setNoInsert;
$setNoInsert = 0;
$pushParserStateAtBrace = 0;
} elsif ($pushParserStateAtBrace) {
if ($part =~ /\;/) {
# It's a class instance declaration. Whoops.
$pushParserStateAtBrace = 0;
$parserState->{inClass} = 0;
print STDERR "inClass -> 0 [10]\n" if ($classDebug);
}
# if ($part =~ /\S/) { $pushParserStateAtBrace = 0; }
}
if (!$parserState->{hollow}) {
my $tok = $part; # $treeCur->token();
print STDERR "parserState: NOT HOLLOW [1]\n" if ($parserStackDebug);
print STDERR "IS: $parserState->{inString}\nICom: $parserState->{inComment}\nISLC: $parserState->{inInlineComment}\nIChar: $parserState->{inChar}\nSkipToken: $parserState->{skiptoken}\nHollowSkip: $hollowskip\n" if ($parserStackDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
print STDERR "parserState: NOT STRING/CHAR/COMMENT\n" if ($parserStackDebug);
if ($tok =~ /\S/) {
print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug);
print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug);
if (!casecmp($tok, $rbrace, $case_sensitive) && $part !~ /\)/) {
# $parserState->{hollow} = $treeCur;
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$HeaderDoc::curParserState = $parserState;
print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-1) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug);
}
}
}
$hollowskip = 0;
print STDERR "hollowskip -> 0 (NOTHOLLOW - 1)\n" if ($parserStateInsertDebug);
$parserState->{skiptoken} = 0;
}
} else {
if (!$parserState->{hollow}) {
my $tok = $part; # $treeCur->token();
print STDERR "parserState: NOT HOLLOW [2]\n" if ($parserStackDebug);
print STDERR "IS: $parserState->{inString}\nICom: $parserState->{inComment}\nISLC: $parserState->{inInlineComment}\nIChar: $parserState->{inChar}\nSkipToken: $parserState->{skiptoken}\nHollowSkip: $hollowskip\n" if ($parserStackDebug);
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
print STDERR "parserState: NOT STRING/CHAR/COMMENT\n" if ($parserStackDebug);
if ($tok =~ /\S/) {
print STDERR "parserState: PS IS $parserState\n" if ($parserStackDebug);
print STDERR "parserState: NOT WHITESPACE : ".$parserState->{hollow}." -> $treeCur\n" if ($parserStackDebug);
if (!casecmp($tok, $rbrace, $case_sensitive) && $part !~ /\)/) {
setHollowWithLineNumbers(\$parserState, $treeCur, $fileoffset, $inputCounter);
$HeaderDoc::curParserState = $parserState;
print STDERR "parserState: WILL INSERT STATE $parserState (HOLLOW-AUTO-2) AT TOKEN \"$part\"/\"".$treeCur->token()."\"\n" if ($parserStackDebug);
}
}
}
$hollowskip = 0;
print STDERR "hollowskip -> 0 (NOTHOLLOW - 2)\n" if ($parserStateInsertDebug);
$parserState->{skiptoken} = 0;
}
}
if ($part =~ /\w+/) {
if (!($parserState->{inString} || $parserState->{inComment} || $parserState->{inInlineComment} || $parserState->{inChar} || $parserState->{skiptoken} || $hollowskip)) {
if ($parserState->{occparmlabelfound} == -2) {
if (!($parserState->{initbsCount} - scalar(@braceStack) )) { # Skip types
$parserState->{occparmlabelfound} = 0; # Next token is the label for the next parameter.
if ($HeaderDoc::useParmNameForUnlabeledParms) {
$parserState->{occmethodname} .= "$part:";
} else {
$parserState->{occmethodname} .= ":";
}
if ($occMethodNameDebug) {
print STDERR "OCC parameter name substituted; OCC method name now ".$parserState->{occmethodname}." (lastsymbol was \"".$parserState->{lastsymbol}."\", part was \"".$part."\").\n";
}
}
} else {
if (!($parserState->{initbsCount} - scalar(@braceStack) )) { # Skip types
$parserState->{occparmlabelfound}++;
if ($occMethodNameDebug && ($parserState->{occparmlabelfound} > 0)) {
print STDERR "OCC possible label: \"$part\".\n";
}
}
}
}
}
if (length($part) && $part =~ /\S/o) { $lastnspart = $part; }
if ($parserState->{seenTilde} && length($part) && $part !~ /\s/o) { $parserState->{seenTilde}--; }
$part = $nextpart;
} # end foreach (parts of the current line)
} # end while (continue && ...)
print STDERR "RETURNING DECLARATION\n" if ($localDebug);
# Format and insert curline into the declaration. This handles the
# trailing line. (Deprecated.)
if ($curline !~ /\n/) { $curline =~ s/^\s*//go; }
if ($curline =~ /\S/o) {
$scratch = nspaces($prespace);
$declaration .= "$scratch$curline\n";
}
print STDERR "($parserState->{typestring}, $parserState->{basetype})\n" if ($localDebug || $listDebug);
print STDERR "LS: $parserState->{lastsymbol}\n" if ($localDebug);
$parserState->{lastTreeNode} = $treeCur;
$parserState->{inputCounter} = $inputCounter;
print STDERR "PARSERSTATE: $parserState\n" if ($localDebug);
if ($parserState->{inMacro} == 3) {
if (!$HeaderDoc::skipNextPDefine) {
cpp_add($treeTop);
} else {
cpp_add($treeTop, 1);
$HeaderDoc::skipNextPDefine = 0;
}
}
print STDERR "LEFTBPMAIN\n" if ($localDebug || $hangDebug);
if ($argparse && $apwarn) {
print STDERR "end argparse\n";
}
# Return the top parser context even if we got interrupted.
my $tempParserState = pop(@parserStack);
while ($tempParserState) {
$parserState = $tempParserState;
$tempParserState = pop(@parserStack);
}
$HeaderDoc::module = $parserState->{MODULE};
if ($localDebug || $apDebug || $liteDebug || $parseDebug) {
print STDERR "LEAVING BLOCKPARSE\n";
}
if (0) {
print STDERR "Returning the following parse tree:\n";
$treeTop->dbprint();
print STDERR "End of parse tree.\n";
}
# print "FC: ".$parserState->{functionContents}."\n";
return blockParseReturnState($parserState, $treeTop, $argparse, $declaration, $inPrivateParamTypes, $publicDeclaration, $lastACS, $retDebug, $fileoffset, 0, $definename, $inputCounter);
}
extendsClass:
implementsClass:
-=: LIST OF PARSED PARAMETERS :=-
-=: DUMP OF PARSE TREE :=-
+---sub
+---
+---blockParse
+---[ NEWLINE ]
-=: COMPUTED VALUE :=-
SUCCESS: 0
VALUE: 0
-=: CPP CHANGES :=-
NO CPP CHANGES
-=: FOUND MATCH :=-
1
-=: NAMED OBJECTS :=-
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::Header
NAME: Perl function 2
APIUID: //test_ref/doc/header/Perl_function_2.test
ABSTRACT: ""
DISCUSSION: "<p></p>"
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::Header"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 1
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::Function
NAME: blockParse
APIUID: //test_ref/perl/func/blockParse
ABSTRACT: ""
DISCUSSION: "<p>The blockParse function is the core of HeaderDoc's parse engine.
"
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: "default_function_group"
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::Function"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: "0"
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TAGGED PARAMETERS:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: filename
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/filename
ABSTRACT: ""
DISCUSSION: "<p>the filename being parser."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: fileoffset
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/fileoffset
ABSTRACT: ""
DISCUSSION: "<p>the line number where the current block begins. The line number printed is (fileoffset + inputCounter)."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: inputLinesRef
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/inputLinesRef
ABSTRACT: ""
DISCUSSION: "<p>a reference to an array of code lines."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: inputCounter
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/inputCounter
ABSTRACT: ""
DISCUSSION: "<p>the offset within the array. This is added to fileoffset when printing the line number."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: argparse
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/argparse
ABSTRACT: ""
DISCUSSION: "<p>disable warnings when parsing arguments to avoid seeing them twice."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: ignoreref
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/ignoreref
ABSTRACT: ""
DISCUSSION: "<p>a reference to a hash of tokens to ignore on all headers."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: perheaderignoreref
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/perheaderignoreref
ABSTRACT: ""
DISCUSSION: "<p>a reference to a hash of tokens, generated from @ignore headerdoc comments."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: perheaderignorefuncmacrosref
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/perheaderignorefuncmacrosref
ABSTRACT: ""
DISCUSSION: "<p>a reference to a hash of tokens, generated from @ignorefunmacro headerdoc comments."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: keywordhashref
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/keywordhashref
ABSTRACT: ""
DISCUSSION: "<p>a reference to a hash of keywords."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
TREE COUNT: 0
INDEX GROUP:
IS BLOCK:
OBJECT TYPE: HeaderDoc::MinorAPIElement
NAME: case_sensitive
TYPE:
APIUID: //test_ref/doc/functionparam/blockParse/case_sensitive
ABSTRACT: ""
DISCUSSION: "<p>boolean: controls whether keywords should be processed in a case-sensitive fashion."
UPDATED: ""
COPYRIGHT: ""
HTMLMETA: ""
PRIVATEDECLARATION: ""
GROUP: ""
INDEXGROUP: ""
THROWS: ""
XMLTHROWS: ""
UPDATED: ""
LINKAGESTATE: ""
ACCESSCONTROL: ""
AVAILABILITY: ""
LINKUID: ""
ORIGCLASS: ""
ISDEFINE: ""
ISTEMPLATE: ""
VALUE: "UNKNOWN"
RETURNTYPE: ""
LINENUM: ""
CLASS: "HeaderDoc::MinorAPIElement"
MASTERENUM: ""
APIREFSETUPDONE: "1"
TPCDONE: ""
NOREGISTERUID: ""
SUPPRESSCHILDREN: ""
NAMELINE_DISCUSSION: ""
HIDEDOC: ""
HIDESINGLETONS: ""
HIDECONTENTS: ""
MAINOBJECT: ""
LIST ATTRIBUTES:
SHORT ATTRIBUTES:
LONG ATTRIBUTES:
-=: NAMED OBJECT PARSE TREES :=-
OBJECT: blockParse (HeaderDoc::Function)
+---sub
+---
+---blockParse
+---[ NEWLINE ]
END OF OBJECT
-=: HTML OUTPUT OF PARSE TREES :=-
OBJECT: blockParse (HeaderDoc::Function)
<span class="keyword">sub</span> <!-- a logicalPath="//test_ref/perl/instm/blockParse //test_ref/perl/clm/blockParse //test_ref/perl/intfcm/blockParse //test_ref/perl/intfm/blockParse //test_ref/perl/func/blockParse //test_ref/perl/ftmplt/blockParse //test_ref/perl/defn/blockParse //test_ref/perl/macro/blockParse //test_ref/doc/anysymbol/blockParse" machineGenerated="true" --><span class="function">blockParse</span><!-- /a -->
END OF OBJECT
_$97|/Users/dg/headerdoc-techpubs/Modules/HeaderDoc//../../testsuite/parser_tests/Perl_function_2.test$4|perl$15|Perl function 2$4|perl$6|parser