Perl_function_2.test   [plain text]


FrT;@1|>>0|$15|HeaderDoc::Test%26|$4|CODE$7|COMMENT$7|CPPCODE$15|EXPECTED_RESULT$23|EXPECTED_RESULT_ALLDECS$7|FAILMSG$8|FILENAME$4|LANG$4|NAME$6|RESULT$14|RESULT_ALLDECS$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|$496291|-=: 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->{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} => 1
$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->{parsedParamList} => ARRAY(OBJID)
$parserState->{parsedParamParse} => 0
$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->{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: <p></p>
LONG ATTRIBUTES: <p></p>
    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: "1"
    NAMELINE_DISCUSSION: ""
    HIDEDOC: ""
    HIDESINGLETONS: ""
    HIDECONTENTS: ""
    MAINOBJECT: ""
    LIST ATTRIBUTES: 
    SHORT ATTRIBUTES: <p></p>
    LONG ATTRIBUTES: <p></p>
    TAGGED PARAMETERS:
        TREE COUNT: 0
        INDEX GROUP: 
        IS BLOCK: 
        OBJECT TYPE: HeaderDoc::MinorAPIElement
        NAME: filename
        TYPE: 
        APIUID: 
        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: <p></p>
        LONG ATTRIBUTES: <p></p>
        TREE COUNT: 0
        INDEX GROUP: 
        IS BLOCK: 
        OBJECT TYPE: HeaderDoc::MinorAPIElement
        NAME: fileoffset
        TYPE: 
        APIUID: 
        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: <p></p>
        LONG ATTRIBUTES: <p></p>
        TREE COUNT: 0
        INDEX GROUP: 
        IS BLOCK: 
        OBJECT TYPE: HeaderDoc::MinorAPIElement
        NAME: inputLinesRef
        TYPE: 
        APIUID: 
        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: <p></p>
        LONG ATTRIBUTES: <p></p>
        TREE COUNT: 0
        INDEX GROUP: 
        IS BLOCK: 
        OBJECT TYPE: HeaderDoc::MinorAPIElement
        NAME: inputCounter
        TYPE: 
        APIUID: 
        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: <p></p>
        LONG ATTRIBUTES: <p></p>
        TREE COUNT: 0
        INDEX GROUP: 
        IS BLOCK: 
        OBJECT TYPE: HeaderDoc::MinorAPIElement
        NAME: argparse
        TYPE: 
        APIUID: 
        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: <p></p>
        LONG ATTRIBUTES: <p></p>
        TREE COUNT: 0
        INDEX GROUP: 
        IS BLOCK: 
        OBJECT TYPE: HeaderDoc::MinorAPIElement
        NAME: ignoreref
        TYPE: 
        APIUID: 
        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: <p></p>
        LONG ATTRIBUTES: <p></p>
        TREE COUNT: 0
        INDEX GROUP: 
        IS BLOCK: 
        OBJECT TYPE: HeaderDoc::MinorAPIElement
        NAME: perheaderignoreref
        TYPE: 
        APIUID: 
        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: <p></p>
        LONG ATTRIBUTES: <p></p>
        TREE COUNT: 0
        INDEX GROUP: 
        IS BLOCK: 
        OBJECT TYPE: HeaderDoc::MinorAPIElement
        NAME: perheaderignorefuncmacrosref
        TYPE: 
        APIUID: 
        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: <p></p>
        LONG ATTRIBUTES: <p></p>
        TREE COUNT: 0
        INDEX GROUP: 
        IS BLOCK: 
        OBJECT TYPE: HeaderDoc::MinorAPIElement
        NAME: keywordhashref
        TYPE: 
        APIUID: 
        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: <p></p>
        LONG ATTRIBUTES: <p></p>
        TREE COUNT: 0
        INDEX GROUP: 
        IS BLOCK: 
        OBJECT TYPE: HeaderDoc::MinorAPIElement
        NAME: case_sensitive
        TYPE: 
        APIUID: 
        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: <p></p>
        LONG ATTRIBUTES: <p></p>
-=: 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" --><span class="function">blockParse</span><!-- /a --> 
END OF OBJECT



$496291|-=: 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->{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} => 1
$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->{parsedParamList} => ARRAY(OBJID)
$parserState->{parsedParamParse} => 0
$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->{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;