"Fossies" - the Fresh Open Source Software Archive

Member "highlight-3.57-x64/src/core/astyle/ASFormatter.cpp" (12 May 2020, 237182 Bytes) of package /windows/www/highlight-3.57-x64.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "ASFormatter.cpp": 3.53_vs_3.54.

    1 // ASFormatter.cpp
    2 // Copyright (c) 2018 by Jim Pattee <jimp03@email.com>.
    3 // This code is licensed under the MIT License.
    4 // License.md describes the conditions under which this software may be distributed.
    5 
    6 //-----------------------------------------------------------------------------
    7 // headers
    8 //-----------------------------------------------------------------------------
    9 
   10 #include "astyle/astyle.h"
   11 
   12 #include <algorithm>
   13 #include <fstream>
   14 
   15 //-----------------------------------------------------------------------------
   16 // astyle namespace
   17 //-----------------------------------------------------------------------------
   18 
   19 namespace astyle {
   20 //
   21 //-----------------------------------------------------------------------------
   22 // ASFormatter class
   23 //-----------------------------------------------------------------------------
   24 
   25 /**
   26  * Constructor of ASFormatter
   27  */
   28 ASFormatter::ASFormatter()
   29 {
   30     sourceIterator = nullptr;
   31     enhancer = new ASEnhancer;
   32     preBraceHeaderStack = nullptr;
   33     braceTypeStack = nullptr;
   34     parenStack = nullptr;
   35     structStack = nullptr;
   36     questionMarkStack = nullptr;
   37     lineCommentNoIndent = false;
   38     formattingStyle = STYLE_NONE;
   39     braceFormatMode = NONE_MODE;
   40     pointerAlignment = PTR_ALIGN_NONE;
   41     referenceAlignment = REF_SAME_AS_PTR;
   42     objCColonPadMode = COLON_PAD_NO_CHANGE;
   43     lineEnd = LINEEND_DEFAULT;
   44     maxCodeLength = string::npos;
   45     shouldPadCommas = false;
   46     shouldPadOperators = false;
   47     shouldPadParensOutside = false;
   48     shouldPadFirstParen = false;
   49     shouldPadParensInside = false;
   50     shouldPadHeader = false;
   51     shouldStripCommentPrefix = false;
   52     shouldUnPadParens = false;
   53     attachClosingBraceMode = false;
   54     shouldBreakOneLineBlocks = true;
   55     shouldBreakOneLineHeaders = false;
   56     shouldBreakOneLineStatements = true;
   57     shouldConvertTabs = false;
   58     shouldIndentCol1Comments = false;
   59     shouldIndentPreprocBlock = false;
   60     shouldCloseTemplates = false;
   61     shouldAttachExternC = false;
   62     shouldAttachNamespace = false;
   63     shouldAttachClass = false;
   64     shouldAttachClosingWhile = false;
   65     shouldAttachInline = false;
   66     shouldBreakBlocks = false;
   67     shouldBreakClosingHeaderBlocks = false;
   68     shouldBreakClosingHeaderBraces = false;
   69     shouldDeleteEmptyLines = false;
   70     shouldBreakReturnType = false;
   71     shouldBreakReturnTypeDecl = false;
   72     shouldAttachReturnType = false;
   73     shouldAttachReturnTypeDecl = false;
   74     shouldBreakElseIfs = false;
   75     shouldBreakLineAfterLogical = false;
   76     shouldAddBraces = false;
   77     shouldAddOneLineBraces = false;
   78     shouldRemoveBraces = false;
   79     shouldPadMethodColon = false;
   80     shouldPadMethodPrefix = false;
   81     shouldUnPadMethodPrefix = false;
   82     shouldPadReturnType = false;
   83     shouldUnPadReturnType = false;
   84     shouldPadParamType = false;
   85     shouldUnPadParamType = false;
   86 
   87     // initialize ASFormatter member vectors
   88     formatterFileType = 9;      // reset to an invalid type
   89     headers = new vector<const string*>;
   90     nonParenHeaders = new vector<const string*>;
   91     preDefinitionHeaders = new vector<const string*>;
   92     preCommandHeaders = new vector<const string*>;
   93     operators = new vector<const string*>;
   94     assignmentOperators = new vector<const string*>;
   95     castOperators = new vector<const string*>;
   96 
   97     // initialize ASEnhancer member vectors
   98     indentableMacros = new vector<const pair<const string, const string>* >;
   99 }
  100 
  101 /**
  102  * Destructor of ASFormatter
  103  */
  104 ASFormatter::~ASFormatter()
  105 {
  106     // delete ASFormatter stack vectors
  107     deleteContainer(preBraceHeaderStack);
  108     deleteContainer(braceTypeStack);
  109     deleteContainer(parenStack);
  110     deleteContainer(structStack);
  111     deleteContainer(questionMarkStack);
  112 
  113     // delete ASFormatter member vectors
  114     formatterFileType = 9;      // reset to an invalid type
  115     delete headers;
  116     delete nonParenHeaders;
  117     delete preDefinitionHeaders;
  118     delete preCommandHeaders;
  119     delete operators;
  120     delete assignmentOperators;
  121     delete castOperators;
  122 
  123     // delete ASEnhancer member vectors
  124     delete indentableMacros;
  125 
  126     // must be done when the ASFormatter object is deleted (not ASBeautifier)
  127     // delete ASBeautifier member vectors
  128     ASBeautifier::deleteBeautifierVectors();
  129 
  130     delete enhancer;
  131 }
  132 
  133 /**
  134  * initialize the ASFormatter.
  135  *
  136  * init() should be called every time a ASFormatter object is to start
  137  * formatting a NEW source file.
  138  * init() receives a pointer to a ASSourceIterator object that will be
  139  * used to iterate through the source code.
  140  *
  141  * @param si        a pointer to the ASSourceIterator or ASStreamIterator object.
  142  */
  143 void ASFormatter::init(ASSourceIterator* si)
  144 {
  145     buildLanguageVectors();
  146     fixOptionVariableConflicts();
  147     ASBeautifier::init(si);
  148     sourceIterator = si;
  149 
  150     enhancer->init(getFileType(),
  151                    getIndentLength(),
  152                    getTabLength(),
  153                    getIndentString() == "\t",
  154                    getForceTabIndentation(),
  155                    getNamespaceIndent(),
  156                    getCaseIndent(),
  157                    shouldIndentPreprocBlock,
  158                    getPreprocDefineIndent(),
  159                    getEmptyLineFill(),
  160                    indentableMacros);
  161 
  162     initContainer(preBraceHeaderStack, new vector<const string*>);
  163     initContainer(parenStack, new vector<int>);
  164     initContainer(structStack, new vector<bool>);
  165     initContainer(questionMarkStack, new vector<bool>);
  166     parenStack->emplace_back(0);               // parenStack must contain this default entry
  167     initContainer(braceTypeStack, new vector<BraceType>);
  168     braceTypeStack->emplace_back(NULL_TYPE);   // braceTypeStack must contain this default entry
  169     clearFormattedLineSplitPoints();
  170 
  171     currentHeader = nullptr;
  172     currentLine = "";
  173     readyFormattedLine = "";
  174     formattedLine = "";
  175     verbatimDelimiter = "";
  176     currentChar = ' ';
  177     previousChar = ' ';
  178     previousCommandChar = ' ';
  179     previousNonWSChar = ',';    // not a potential name or operator
  180     quoteChar = '"';
  181     preprocBlockEnd = 0;
  182     charNum = 0;
  183     checksumIn = 0;
  184     checksumOut = 0;
  185     currentLineFirstBraceNum = string::npos;
  186     formattedLineCommentNum = 0;
  187     leadingSpaces = 0;
  188     previousReadyFormattedLineLength = string::npos;
  189     preprocBraceTypeStackSize = 0;
  190     spacePadNum = 0;
  191     methodAttachCharNum = string::npos;
  192     methodAttachLineNum = 0;
  193     methodBreakCharNum = string::npos;
  194     methodBreakLineNum = 0;
  195     nextLineSpacePadNum = 0;
  196     objCColonAlign = 0;
  197     templateDepth = 0;
  198     squareBracketCount = 0;
  199     runInIndentChars = 0;
  200     tabIncrementIn = 0;
  201     previousBraceType = NULL_TYPE;
  202 
  203     isVirgin = true;
  204     isInVirginLine = true;
  205     isInLineComment = false;
  206     isInComment = false;
  207     isInCommentStartLine = false;
  208     noTrimCommentContinuation = false;
  209     isInPreprocessor = false;
  210     isInPreprocessorBeautify = false;
  211     doesLineStartComment = false;
  212     lineEndsInCommentOnly = false;
  213     lineIsCommentOnly = false;
  214     lineIsLineCommentOnly = false;
  215     lineIsEmpty = false;
  216     isImmediatelyPostCommentOnly = false;
  217     isImmediatelyPostEmptyLine = false;
  218     isInClassInitializer = false;
  219     isInQuote = false;
  220     isInVerbatimQuote = false;
  221     haveLineContinuationChar = false;
  222     isInQuoteContinuation = false;
  223     isHeaderInMultiStatementLine = false;
  224     isSpecialChar = false;
  225     isNonParenHeader = false;
  226     foundNamespaceHeader = false;
  227     foundClassHeader = false;
  228     foundStructHeader = false;
  229     foundInterfaceHeader = false;
  230     foundPreDefinitionHeader = false;
  231     foundPreCommandHeader = false;
  232     foundPreCommandMacro = false;
  233     foundTrailingReturnType = false;
  234     foundCastOperator = false;
  235     foundQuestionMark = false;
  236     isInLineBreak = false;
  237     endOfAsmReached = false;
  238     endOfCodeReached = false;
  239     isFormattingModeOff = false;
  240     isInEnum = false;
  241     isInExecSQL = false;
  242     isInAsm = false;
  243     isInAsmOneLine = false;
  244     isInAsmBlock = false;
  245     isLineReady = false;
  246     elseHeaderFollowsComments = false;
  247     caseHeaderFollowsComments = false;
  248     isPreviousBraceBlockRelated = false;
  249     isInPotentialCalculation = false;
  250     needHeaderOpeningBrace = false;
  251     shouldBreakLineAtNextChar = false;
  252     shouldKeepLineUnbroken = false;
  253     shouldReparseCurrentChar = false;
  254     passedSemicolon = false;
  255     passedColon = false;
  256     isImmediatelyPostNonInStmt = false;
  257     isCharImmediatelyPostNonInStmt = false;
  258     isInTemplate = false;
  259     isImmediatelyPostComment = false;
  260     isImmediatelyPostLineComment = false;
  261     isImmediatelyPostEmptyBlock = false;
  262     isImmediatelyPostObjCMethodPrefix = false;
  263     isImmediatelyPostPreprocessor = false;
  264     isImmediatelyPostReturn = false;
  265     isImmediatelyPostThrow = false;
  266     isImmediatelyPostNewDelete = false;
  267     isImmediatelyPostOperator = false;
  268     isImmediatelyPostTemplate = false;
  269     isImmediatelyPostPointerOrReference = false;
  270     isCharImmediatelyPostReturn = false;
  271     isCharImmediatelyPostThrow = false;
  272     isCharImmediatelyPostNewDelete = false;
  273     isCharImmediatelyPostOperator = false;
  274     isCharImmediatelyPostComment = false;
  275     isPreviousCharPostComment = false;
  276     isCharImmediatelyPostLineComment = false;
  277     isCharImmediatelyPostOpenBlock = false;
  278     isCharImmediatelyPostCloseBlock = false;
  279     isCharImmediatelyPostTemplate = false;
  280     isCharImmediatelyPostPointerOrReference = false;
  281     isInObjCInterface = false;
  282     isInObjCMethodDefinition = false;
  283     isInObjCReturnType = false;
  284     isInObjCParam = false;
  285     isInObjCSelector = false;
  286     breakCurrentOneLineBlock = false;
  287     shouldRemoveNextClosingBrace = false;
  288     isInBraceRunIn = false;
  289     returnTypeChecked = false;
  290     currentLineBeginsWithBrace = false;
  291     isPrependPostBlockEmptyLineRequested = false;
  292     isAppendPostBlockEmptyLineRequested = false;
  293     isIndentableProprocessor = false;
  294     isIndentableProprocessorBlock = false;
  295     prependEmptyLine = false;
  296     appendOpeningBrace = false;
  297     foundClosingHeader = false;
  298     isImmediatelyPostHeader = false;
  299     isInHeader = false;
  300     isInCase = false;
  301     isFirstPreprocConditional = false;
  302     processedFirstConditional = false;
  303     isJavaStaticConstructor = false;
  304 }
  305 
  306 /**
  307  * build vectors for each programming language
  308  * depending on the file extension.
  309  */
  310 void ASFormatter::buildLanguageVectors()
  311 {
  312     if (getFileType() == formatterFileType)  // don't build unless necessary
  313         return;
  314 
  315     formatterFileType = getFileType();
  316 
  317     headers->clear();
  318     nonParenHeaders->clear();
  319     preDefinitionHeaders->clear();
  320     preCommandHeaders->clear();
  321     operators->clear();
  322     assignmentOperators->clear();
  323     castOperators->clear();
  324     indentableMacros->clear();  // ASEnhancer
  325 
  326     ASResource::buildHeaders(headers, getFileType());
  327     ASResource::buildNonParenHeaders(nonParenHeaders, getFileType());
  328     ASResource::buildPreDefinitionHeaders(preDefinitionHeaders, getFileType());
  329     ASResource::buildPreCommandHeaders(preCommandHeaders, getFileType());
  330     ASResource::buildOperators(operators, getFileType());
  331     ASResource::buildAssignmentOperators(assignmentOperators);
  332     ASResource::buildCastOperators(castOperators);
  333     ASResource::buildIndentableMacros(indentableMacros);    //ASEnhancer
  334 }
  335 
  336 /**
  337  * set the variables for each predefined style.
  338  * this will override any previous settings.
  339  */
  340 void ASFormatter::fixOptionVariableConflicts()
  341 {
  342     if (formattingStyle == STYLE_ALLMAN)
  343     {
  344         setBraceFormatMode(BREAK_MODE);
  345     }
  346     else if (formattingStyle == STYLE_JAVA)
  347     {
  348         setBraceFormatMode(ATTACH_MODE);
  349     }
  350     else if (formattingStyle == STYLE_KR)
  351     {
  352         setBraceFormatMode(LINUX_MODE);
  353     }
  354     else if (formattingStyle == STYLE_STROUSTRUP)
  355     {
  356         setBraceFormatMode(LINUX_MODE);
  357         setBreakClosingHeaderBracesMode(true);
  358     }
  359     else if (formattingStyle == STYLE_WHITESMITH)
  360     {
  361         setBraceFormatMode(BREAK_MODE);
  362         setBraceIndent(true);
  363         setClassIndent(true);           // avoid hanging indent with access modifiers
  364         setSwitchIndent(true);          // avoid hanging indent with case statements
  365     }
  366     else if (formattingStyle == STYLE_VTK)
  367     {
  368         // the unindented class brace does NOT cause a hanging indent like Whitesmith
  369         setBraceFormatMode(BREAK_MODE);
  370         setBraceIndentVtk(true);        // sets both braceIndent and braceIndentVtk
  371         setSwitchIndent(true);          // avoid hanging indent with case statements
  372     }
  373     else if (formattingStyle == STYLE_RATLIFF)
  374     {
  375         // attached braces can have hanging indents with the closing brace
  376         setBraceFormatMode(ATTACH_MODE);
  377         setBraceIndent(true);
  378         setClassIndent(true);           // avoid hanging indent with access modifiers
  379         setSwitchIndent(true);          // avoid hanging indent with case statements
  380     }
  381     else if (formattingStyle == STYLE_GNU)
  382     {
  383         setBraceFormatMode(BREAK_MODE);
  384         setBlockIndent(true);
  385     }
  386     else if (formattingStyle == STYLE_LINUX)
  387     {
  388         setBraceFormatMode(LINUX_MODE);
  389         // always for Linux style
  390         setMinConditionalIndentOption(MINCOND_ONEHALF);
  391     }
  392     else if (formattingStyle == STYLE_HORSTMANN)
  393     {
  394         setBraceFormatMode(RUN_IN_MODE);
  395         setSwitchIndent(true);
  396     }
  397     else if (formattingStyle == STYLE_1TBS)
  398     {
  399         setBraceFormatMode(LINUX_MODE);
  400         setAddBracesMode(true);
  401         setRemoveBracesMode(false);
  402     }
  403     else if (formattingStyle == STYLE_GOOGLE)
  404     {
  405         setBraceFormatMode(ATTACH_MODE);
  406         setModifierIndent(true);
  407         setClassIndent(false);
  408     }
  409     else if (formattingStyle == STYLE_MOZILLA)
  410     {
  411         setBraceFormatMode(LINUX_MODE);
  412     }
  413     else if (formattingStyle == STYLE_WEBKIT)
  414     {
  415         setBraceFormatMode(LINUX_MODE);
  416     }
  417     else if (formattingStyle == STYLE_PICO)
  418     {
  419         setBraceFormatMode(RUN_IN_MODE);
  420         setAttachClosingBraceMode(true);
  421         setSwitchIndent(true);
  422         setBreakOneLineBlocksMode(false);
  423         setBreakOneLineStatementsMode(false);
  424         // add-braces won't work for pico, but it could be fixed if necessary
  425         // both options should be set to true
  426         if (shouldAddBraces)
  427             shouldAddOneLineBraces = true;
  428     }
  429     else if (formattingStyle == STYLE_LISP)
  430     {
  431         setBraceFormatMode(ATTACH_MODE);
  432         setAttachClosingBraceMode(true);
  433         setBreakOneLineStatementsMode(false);
  434         // add-one-line-braces won't work for lisp
  435         // only shouldAddBraces should be set to true
  436         if (shouldAddOneLineBraces)
  437         {
  438             shouldAddBraces = true;
  439             shouldAddOneLineBraces = false;
  440         }
  441     }
  442     setMinConditionalIndentLength();
  443     // if not set by indent=force-tab-x set equal to indentLength
  444     if (getTabLength() == 0)
  445         setDefaultTabLength();
  446     // add-one-line-braces implies keep-one-line-blocks
  447     if (shouldAddOneLineBraces)
  448         setBreakOneLineBlocksMode(false);
  449     // don't allow add-braces and remove-braces
  450     if (shouldAddBraces || shouldAddOneLineBraces)
  451         setRemoveBracesMode(false);
  452     // don't allow break-return-type and attach-return-type
  453     if (shouldBreakReturnType)
  454         shouldAttachReturnType = false;
  455     if (shouldBreakReturnTypeDecl)
  456         shouldAttachReturnTypeDecl = false;
  457     // don't allow indent-classes and indent-modifiers
  458     if (getClassIndent())
  459         setModifierIndent(false);
  460 }
  461 
  462 /**
  463  * get the next formatted line.
  464  *
  465  * @return    formatted line.
  466  */
  467 string ASFormatter::nextLine()
  468 {
  469     const string* newHeader = nullptr;
  470     isInVirginLine = isVirgin;
  471     isCharImmediatelyPostComment = false;
  472     isPreviousCharPostComment = false;
  473     isCharImmediatelyPostLineComment = false;
  474     isCharImmediatelyPostOpenBlock = false;
  475     isCharImmediatelyPostCloseBlock = false;
  476     isCharImmediatelyPostTemplate = false;
  477 
  478     while (!isLineReady)
  479     {
  480         if (shouldReparseCurrentChar)
  481             shouldReparseCurrentChar = false;
  482         else if (!getNextChar())
  483         {
  484             breakLine();
  485             continue;
  486         }
  487         else // stuff to do when reading a new character...
  488         {
  489             // make sure that a virgin '{' at the beginning of the file will be treated as a block...
  490             if (isInVirginLine && currentChar == '{'
  491                     && currentLineBeginsWithBrace
  492                     && previousCommandChar == ' ')
  493                 previousCommandChar = '{';
  494             if (isInClassInitializer
  495                     && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
  496                 isInClassInitializer = false;
  497             if (isInBraceRunIn)
  498                 isInLineBreak = false;
  499             if (!isWhiteSpace(currentChar))
  500                 isInBraceRunIn = false;
  501             isPreviousCharPostComment = isCharImmediatelyPostComment;
  502             isCharImmediatelyPostComment = false;
  503             isCharImmediatelyPostTemplate = false;
  504             isCharImmediatelyPostReturn = false;
  505             isCharImmediatelyPostThrow = false;
  506             isCharImmediatelyPostNewDelete = false;
  507             isCharImmediatelyPostOperator = false;
  508             isCharImmediatelyPostPointerOrReference = false;
  509             isCharImmediatelyPostOpenBlock = false;
  510             isCharImmediatelyPostCloseBlock = false;
  511         }
  512 
  513         if ((lineIsLineCommentOnly || lineIsCommentOnly)
  514                 && currentLine.find("*INDENT-ON*", charNum) != string::npos
  515                 && isFormattingModeOff)
  516         {
  517             isFormattingModeOff = false;
  518             breakLine();
  519             formattedLine = currentLine;
  520             charNum = (int) currentLine.length() - 1;
  521             continue;
  522         }
  523         if (isFormattingModeOff)
  524         {
  525             breakLine();
  526             formattedLine = currentLine;
  527             charNum = (int) currentLine.length() - 1;
  528             continue;
  529         }
  530         if ((lineIsLineCommentOnly || lineIsCommentOnly)
  531                 && currentLine.find("*INDENT-OFF*", charNum) != string::npos)
  532         {
  533             isFormattingModeOff = true;
  534             if (isInLineBreak)          // is true if not the first line
  535                 breakLine();
  536             formattedLine = currentLine;
  537             charNum = (int) currentLine.length() - 1;
  538             continue;
  539         }
  540 
  541         if (shouldBreakLineAtNextChar)
  542         {
  543             if (isWhiteSpace(currentChar) && !lineIsEmpty)
  544                 continue;
  545             isInLineBreak = true;
  546             shouldBreakLineAtNextChar = false;
  547         }
  548 
  549         if (isInExecSQL && !passedSemicolon)
  550         {
  551             if (currentChar == ';')
  552                 passedSemicolon = true;
  553             appendCurrentChar();
  554             continue;
  555         }
  556 
  557         if (isInLineComment)
  558         {
  559             formatLineCommentBody();
  560             continue;
  561         }
  562 
  563         if (isInComment)
  564         {
  565             formatCommentBody();
  566             continue;
  567         }
  568 
  569         if (isInQuote)
  570         {
  571             formatQuoteBody();
  572             continue;
  573         }
  574 
  575         // not in quote or comment or line comment
  576 
  577         if (isSequenceReached("//"))
  578         {
  579             formatLineCommentOpener();
  580             testForTimeToSplitFormattedLine();
  581             continue;
  582         }
  583         if (isSequenceReached("/*"))
  584         {
  585             formatCommentOpener();
  586             testForTimeToSplitFormattedLine();
  587             continue;
  588         }
  589         if (currentChar == '"'
  590                 || (currentChar == '\'' && !isDigitSeparator(currentLine, charNum)))
  591         {
  592             formatQuoteOpener();
  593             testForTimeToSplitFormattedLine();
  594             continue;
  595         }
  596         // treat these preprocessor statements as a line comment
  597         if (currentChar == '#'
  598                 && currentLine.find_first_not_of(" \t") == (size_t) charNum)
  599         {
  600             string preproc = trim(currentLine.c_str() + charNum + 1);
  601             if (preproc.length() > 0
  602                     && isCharPotentialHeader(preproc, 0)
  603                     && (findKeyword(preproc, 0, "region")
  604                         || findKeyword(preproc, 0, "endregion")
  605                         || findKeyword(preproc, 0, "error")
  606                         || findKeyword(preproc, 0, "warning")
  607                         || findKeyword(preproc, 0, "line")))
  608             {
  609                 currentLine = rtrim(currentLine);   // trim the end only
  610                 // check for run-in
  611                 if (formattedLine.length() > 0 && formattedLine[0] == '{')
  612                 {
  613                     isInLineBreak = true;
  614                     isInBraceRunIn = false;
  615                 }
  616                 if (previousCommandChar == '}')
  617                     currentHeader = nullptr;
  618                 isInLineComment = true;
  619                 appendCurrentChar();
  620                 continue;
  621             }
  622         }
  623 
  624         if (isInPreprocessor)
  625         {
  626             appendCurrentChar();
  627             continue;
  628         }
  629 
  630         if (isInTemplate && shouldCloseTemplates)
  631         {
  632             if (previousNonWSChar == '>' && isWhiteSpace(currentChar) && peekNextChar() == '>')
  633                 continue;
  634         }
  635 
  636         if (shouldRemoveNextClosingBrace && currentChar == '}')
  637         {
  638             currentLine[charNum] = currentChar = ' ';
  639             shouldRemoveNextClosingBrace = false;
  640             assert(adjustChecksumIn(-'}'));
  641             if (isEmptyLine(currentLine))
  642                 continue;
  643         }
  644 
  645         // handle white space - needed to simplify the rest.
  646         if (isWhiteSpace(currentChar))
  647         {
  648             appendCurrentChar();
  649             continue;
  650         }
  651 
  652         /* not in MIDDLE of quote or comment or SQL or white-space of any type ... */
  653 
  654         // check if in preprocessor
  655         // ** isInPreprocessor will be automatically reset at the beginning
  656         //    of a new line in getnextChar()
  657         if (currentChar == '#'
  658                 && currentLine.find_first_not_of(" \t") == (size_t) charNum
  659                 && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
  660         {
  661             isInPreprocessor = true;
  662             // check for run-in
  663             if (formattedLine.length() > 0 && formattedLine[0] == '{')
  664             {
  665                 isInLineBreak = true;
  666                 isInBraceRunIn = false;
  667             }
  668             processPreprocessor();
  669             // if top level it is potentially indentable
  670             if (shouldIndentPreprocBlock
  671                     && (isBraceType(braceTypeStack->back(), NULL_TYPE)
  672                         || isBraceType(braceTypeStack->back(), NAMESPACE_TYPE))
  673                     && !foundClassHeader
  674                     && !isInClassInitializer
  675                     && sourceIterator->tellg() > preprocBlockEnd)
  676             {
  677                 // indent the #if preprocessor blocks
  678                 string preproc = ASBeautifier::extractPreprocessorStatement(currentLine);
  679                 if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef
  680                 {
  681                     if (isImmediatelyPostPreprocessor)
  682                         breakLine();
  683                     isIndentableProprocessorBlock = isIndentablePreprocessorBlock(currentLine, charNum);
  684                     isIndentableProprocessor = isIndentableProprocessorBlock;
  685                 }
  686             }
  687             if (isIndentableProprocessorBlock
  688                     && charNum < (int) currentLine.length() - 1
  689                     && isWhiteSpace(currentLine[charNum + 1]))
  690             {
  691                 size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
  692                 if (nextText != string::npos)
  693                     currentLine.erase(charNum + 1, nextText - charNum - 1);
  694             }
  695             if (isIndentableProprocessorBlock
  696                     && sourceIterator->tellg() >= preprocBlockEnd)
  697                 isIndentableProprocessorBlock = false;
  698             //  need to fall thru here to reset the variables
  699         }
  700 
  701         /* not in preprocessor ... */
  702 
  703         if (isImmediatelyPostComment)
  704         {
  705             caseHeaderFollowsComments = false;
  706             isImmediatelyPostComment = false;
  707             isCharImmediatelyPostComment = true;
  708         }
  709 
  710         if (isImmediatelyPostLineComment)
  711         {
  712             caseHeaderFollowsComments = false;
  713             isImmediatelyPostLineComment = false;
  714             isCharImmediatelyPostLineComment = true;
  715         }
  716 
  717         if (isImmediatelyPostReturn)
  718         {
  719             isImmediatelyPostReturn = false;
  720             isCharImmediatelyPostReturn = true;
  721         }
  722 
  723         if (isImmediatelyPostThrow)
  724         {
  725             isImmediatelyPostThrow = false;
  726             isCharImmediatelyPostThrow = true;
  727         }
  728 
  729         if (isImmediatelyPostNewDelete)
  730         {
  731             isImmediatelyPostNewDelete = false;
  732             isCharImmediatelyPostNewDelete = true;
  733         }
  734 
  735         if (isImmediatelyPostOperator)
  736         {
  737             isImmediatelyPostOperator = false;
  738             isCharImmediatelyPostOperator = true;
  739         }
  740         if (isImmediatelyPostTemplate)
  741         {
  742             isImmediatelyPostTemplate = false;
  743             isCharImmediatelyPostTemplate = true;
  744         }
  745         if (isImmediatelyPostPointerOrReference)
  746         {
  747             isImmediatelyPostPointerOrReference = false;
  748             isCharImmediatelyPostPointerOrReference = true;
  749         }
  750 
  751         // reset isImmediatelyPostHeader information
  752         if (isImmediatelyPostHeader)
  753         {
  754             // should braces be added
  755             if (currentChar != '{'
  756                     && shouldAddBraces
  757                     && currentChar != '#'   // don't add to preprocessor
  758                     && (shouldBreakOneLineStatements || !isHeaderInMultiStatementLine)
  759                     && isOkToBreakBlock(braceTypeStack->back()))
  760             {
  761                 bool bracesAdded = addBracesToStatement();
  762                 if (bracesAdded && !shouldAddOneLineBraces)
  763                 {
  764                     size_t firstText = currentLine.find_first_not_of(" \t");
  765                     assert(firstText != string::npos);
  766                     if ((int) firstText == charNum || shouldBreakOneLineHeaders)
  767                         breakCurrentOneLineBlock = true;
  768                 }
  769             }
  770             // should braces be removed
  771             else if (currentChar == '{' && shouldRemoveBraces)
  772             {
  773                 bool bracesRemoved = removeBracesFromStatement();
  774                 if (bracesRemoved)
  775                 {
  776                     shouldRemoveNextClosingBrace = true;
  777                     if (isBeforeAnyLineEndComment(charNum))
  778                         spacePadNum--;
  779                     else if (shouldBreakOneLineBlocks
  780                              || (currentLineBeginsWithBrace
  781                                  && currentLine.find_first_not_of(" \t") != string::npos))
  782                         shouldBreakLineAtNextChar = true;
  783                     continue;
  784                 }
  785             }
  786 
  787             // break 'else-if' if shouldBreakElseIfs is requested
  788             if (shouldBreakElseIfs
  789                     && currentHeader == &AS_ELSE
  790                     && isOkToBreakBlock(braceTypeStack->back())
  791                     && !isBeforeAnyComment()
  792                     && (shouldBreakOneLineStatements || !isHeaderInMultiStatementLine))
  793             {
  794                 string nextText = peekNextText(currentLine.substr(charNum));
  795                 if (nextText.length() > 0
  796                         && isCharPotentialHeader(nextText, 0)
  797                         && ASBase::findHeader(nextText, 0, headers) == &AS_IF)
  798                 {
  799                     isInLineBreak = true;
  800                 }
  801             }
  802 
  803             // break a header (e.g. if, while, else) from the following statement
  804             if (shouldBreakOneLineHeaders
  805                     && peekNextChar() != ' '
  806                     && (shouldBreakOneLineStatements
  807                         || (!isHeaderInMultiStatementLine
  808                             && !isMultiStatementLine()))
  809                     && isOkToBreakBlock(braceTypeStack->back())
  810                     && !isBeforeAnyComment())
  811             {
  812                 if (currentChar == '{')
  813                 {
  814                     if (!currentLineBeginsWithBrace)
  815                     {
  816                         if (isOneLineBlockReached(currentLine, charNum) == 3)
  817                             isInLineBreak = false;
  818                         else
  819                             breakCurrentOneLineBlock = true;
  820                     }
  821                 }
  822                 else if (currentHeader == &AS_ELSE)
  823                 {
  824                     string nextText = peekNextText(currentLine.substr(charNum), true);
  825                     if (nextText.length() > 0
  826                             && ((isCharPotentialHeader(nextText, 0)
  827                                  && ASBase::findHeader(nextText, 0, headers) != &AS_IF)
  828                                 || nextText[0] == '{'))
  829                         isInLineBreak = true;
  830                 }
  831                 else
  832                 {
  833                     isInLineBreak = true;
  834                 }
  835             }
  836 
  837             isImmediatelyPostHeader = false;
  838         }
  839 
  840         if (passedSemicolon)    // need to break the formattedLine
  841         {
  842             passedSemicolon = false;
  843             if (parenStack->back() == 0 && !isCharImmediatelyPostComment && currentChar != ';') // allow ;;
  844             {
  845                 // does a one-line block have ending comments?
  846                 if (isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
  847                 {
  848                     size_t blockEnd = currentLine.rfind(AS_CLOSE_BRACE);
  849                     assert(blockEnd != string::npos);
  850                     // move ending comments to this formattedLine
  851                     if (isBeforeAnyLineEndComment(blockEnd))
  852                     {
  853                         size_t commentStart = currentLine.find_first_not_of(" \t", blockEnd + 1);
  854                         assert(commentStart != string::npos);
  855                         assert((currentLine.compare(commentStart, 2, "//") == 0)
  856                                || (currentLine.compare(commentStart, 2, "/*") == 0));
  857                         formattedLine.append(getIndentLength() - 1, ' ');
  858                         // append comment
  859                         int charNumSave = charNum;
  860                         charNum = commentStart;
  861                         while (charNum < (int) currentLine.length())
  862                         {
  863                             currentChar = currentLine[charNum];
  864                             if (currentChar == '\t' && shouldConvertTabs)
  865                                 convertTabToSpaces();
  866                             formattedLine.append(1, currentChar);
  867                             ++charNum;
  868                         }
  869                         size_t commentLength = currentLine.length() - commentStart;
  870                         currentLine.erase(commentStart, commentLength);
  871                         charNum = charNumSave;
  872                         currentChar = currentLine[charNum];
  873                         testForTimeToSplitFormattedLine();
  874                     }
  875                 }
  876                 isInExecSQL = false;
  877                 shouldReparseCurrentChar = true;
  878                 if (formattedLine.find_first_not_of(" \t") != string::npos)
  879                     isInLineBreak = true;
  880                 if (needHeaderOpeningBrace)
  881                 {
  882                     isCharImmediatelyPostCloseBlock = true;
  883                     needHeaderOpeningBrace = false;
  884                 }
  885                 continue;
  886             }
  887         }
  888 
  889         if (passedColon)
  890         {
  891             passedColon = false;
  892             if (parenStack->back() == 0
  893                     && !isBeforeAnyComment()
  894                     && (formattedLine.find_first_not_of(" \t") != string::npos))
  895             {
  896                 shouldReparseCurrentChar = true;
  897                 isInLineBreak = true;
  898                 continue;
  899             }
  900         }
  901 
  902         // Check if in template declaration, e.g. foo<bar> or foo<bar,fig>
  903         if (!isInTemplate && currentChar == '<')
  904         {
  905             checkIfTemplateOpener();
  906         }
  907 
  908         // Check for break return type
  909         if ((size_t) charNum >= methodBreakCharNum && methodBreakLineNum == 0)
  910         {
  911             if ((size_t) charNum == methodBreakCharNum)
  912                 isInLineBreak = true;
  913             methodBreakCharNum = string::npos;
  914             methodBreakLineNum = 0;
  915         }
  916         // Check for attach return type
  917         if ((size_t) charNum >= methodAttachCharNum && methodAttachLineNum == 0)
  918         {
  919             if ((size_t) charNum == methodAttachCharNum)
  920             {
  921                 int pa = pointerAlignment;
  922                 int ra = referenceAlignment;
  923                 int itemAlignment = (previousNonWSChar == '*' || previousNonWSChar == '^')
  924                                     ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra);
  925                 isInLineBreak = false;
  926                 if (previousNonWSChar == '*' || previousNonWSChar == '&' || previousNonWSChar == '^')
  927                 {
  928                     if (itemAlignment == REF_ALIGN_TYPE)
  929                     {
  930                         if (formattedLine.length() > 0
  931                                 && !isWhiteSpace(formattedLine[formattedLine.length() - 1]))
  932                             formattedLine.append(1, ' ');
  933                     }
  934                     else if (itemAlignment == REF_ALIGN_MIDDLE)
  935                     {
  936                         if (formattedLine.length() > 0
  937                                 && !isWhiteSpace(formattedLine[formattedLine.length() - 1]))
  938                             formattedLine.append(1, ' ');
  939                     }
  940                     else if (itemAlignment == REF_ALIGN_NAME)
  941                     {
  942                         if (formattedLine.length() > 0
  943                                 && isWhiteSpace(formattedLine[formattedLine.length() - 1]))
  944                             formattedLine.erase(formattedLine.length() - 1);
  945                     }
  946                     else
  947                     {
  948                         if (formattedLine.length() > 1
  949                                 && !isWhiteSpace(formattedLine[formattedLine.length() - 2]))
  950                             formattedLine.append(1, ' ');
  951                     }
  952                 }
  953                 else
  954                     formattedLine.append(1, ' ');
  955             }
  956             methodAttachCharNum = string::npos;
  957             methodAttachLineNum = 0;
  958         }
  959 
  960         // handle parens
  961         if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
  962         {
  963             questionMarkStack->push_back(foundQuestionMark);
  964             foundQuestionMark = false;
  965             parenStack->back()++;
  966             if (currentChar == '[')
  967             {
  968                 ++squareBracketCount;
  969                 if (getAlignMethodColon() && squareBracketCount == 1 && isCStyle())
  970                     objCColonAlign = findObjCColonAlignment();
  971             }
  972         }
  973         else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
  974         {
  975             foundPreCommandHeader = false;
  976             parenStack->back()--;
  977             // this can happen in preprocessor directives
  978             if (parenStack->back() < 0)
  979                 parenStack->back() = 0;
  980             if (!questionMarkStack->empty())
  981             {
  982                 foundQuestionMark = questionMarkStack->back();
  983                 questionMarkStack->pop_back();
  984             }
  985             if (isInTemplate && currentChar == '>')
  986             {
  987                 templateDepth--;
  988                 if (templateDepth == 0)
  989                 {
  990                     isInTemplate = false;
  991                     isImmediatelyPostTemplate = true;
  992                 }
  993             }
  994 
  995             // check if this parenthesis closes a header, e.g. if (...), while (...)
  996             if (isInHeader && parenStack->back() == 0)
  997             {
  998                 isInHeader = false;
  999                 isImmediatelyPostHeader = true;
 1000                 foundQuestionMark = false;
 1001             }
 1002             if (currentChar == ']')
 1003             {
 1004                 --squareBracketCount;
 1005                 if (squareBracketCount <= 0)
 1006                 {
 1007                     squareBracketCount = 0;
 1008                     objCColonAlign = 0;
 1009                 }
 1010             }
 1011             if (currentChar == ')')
 1012             {
 1013                 foundCastOperator = false;
 1014                 if (parenStack->back() == 0)
 1015                     endOfAsmReached = true;
 1016             }
 1017         }
 1018 
 1019         // handle braces
 1020         if (currentChar == '{' || currentChar == '}')
 1021         {
 1022             // if appendOpeningBrace this was already done for the original brace
 1023             if (currentChar == '{' && !appendOpeningBrace)
 1024             {
 1025                 BraceType newBraceType = getBraceType();
 1026                 breakCurrentOneLineBlock = false;
 1027                 foundNamespaceHeader = false;
 1028                 foundClassHeader = false;
 1029                 foundStructHeader = false;
 1030                 foundInterfaceHeader = false;
 1031                 foundPreDefinitionHeader = false;
 1032                 foundPreCommandHeader = false;
 1033                 foundPreCommandMacro = false;
 1034                 foundTrailingReturnType = false;
 1035                 isInPotentialCalculation = false;
 1036                 isInObjCMethodDefinition = false;
 1037                 isImmediatelyPostObjCMethodPrefix = false;
 1038                 isInObjCInterface = false;
 1039                 isInEnum = false;
 1040                 isJavaStaticConstructor = false;
 1041                 isCharImmediatelyPostNonInStmt = false;
 1042                 needHeaderOpeningBrace = false;
 1043                 shouldKeepLineUnbroken = false;
 1044                 returnTypeChecked = false;
 1045                 objCColonAlign = 0;
 1046                 //assert(methodBreakCharNum == string::npos);   // comment out
 1047                 //assert(methodBreakLineNum == 0);              // comment out
 1048                 methodBreakCharNum = string::npos;
 1049                 methodBreakLineNum = 0;
 1050                 methodAttachCharNum = string::npos;
 1051                 methodAttachLineNum = 0;
 1052 
 1053                 isPreviousBraceBlockRelated = !isBraceType(newBraceType, ARRAY_TYPE);
 1054                 braceTypeStack->emplace_back(newBraceType);
 1055                 preBraceHeaderStack->emplace_back(currentHeader);
 1056                 currentHeader = nullptr;
 1057                 structStack->push_back(isInIndentableStruct);
 1058                 if (isBraceType(newBraceType, STRUCT_TYPE) && isCStyle())
 1059                     isInIndentableStruct = isStructAccessModified(currentLine, charNum);
 1060                 else
 1061                     isInIndentableStruct = false;
 1062             }
 1063 
 1064             // this must be done before the braceTypeStack is popped
 1065             BraceType braceType = braceTypeStack->back();
 1066             bool isOpeningArrayBrace = (isBraceType(braceType, ARRAY_TYPE)
 1067                                         && braceTypeStack->size() >= 2
 1068                                         && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2], ARRAY_TYPE)
 1069                                        );
 1070 
 1071             if (currentChar == '}')
 1072             {
 1073                 // if a request has been made to append a post block empty line,
 1074                 // but the block exists immediately before a closing brace,
 1075                 // then there is no need for the post block empty line.
 1076                 isAppendPostBlockEmptyLineRequested = false;
 1077                 if (isInAsm)
 1078                     endOfAsmReached = true;
 1079                 isInAsmOneLine = isInQuote = false;
 1080                 shouldKeepLineUnbroken = false;
 1081                 squareBracketCount = 0;
 1082 
 1083                 if (braceTypeStack->size() > 1)
 1084                 {
 1085                     previousBraceType = braceTypeStack->back();
 1086                     braceTypeStack->pop_back();
 1087                     isPreviousBraceBlockRelated = !isBraceType(braceType, ARRAY_TYPE);
 1088                 }
 1089                 else
 1090                 {
 1091                     previousBraceType = NULL_TYPE;
 1092                     isPreviousBraceBlockRelated = false;
 1093                 }
 1094 
 1095                 if (!preBraceHeaderStack->empty())
 1096                 {
 1097                     currentHeader = preBraceHeaderStack->back();
 1098                     preBraceHeaderStack->pop_back();
 1099                 }
 1100                 else
 1101                     currentHeader = nullptr;
 1102 
 1103                 if (!structStack->empty())
 1104                 {
 1105                     isInIndentableStruct = structStack->back();
 1106                     structStack->pop_back();
 1107                 }
 1108                 else
 1109                     isInIndentableStruct = false;
 1110 
 1111                 if (isNonInStatementArray
 1112                         && (!isBraceType(braceTypeStack->back(), ARRAY_TYPE)    // check previous brace
 1113                             || peekNextChar() == ';'))                          // check for "};" added V2.01
 1114                     isImmediatelyPostNonInStmt = true;
 1115 
 1116                 if (!shouldBreakOneLineStatements
 1117                         && ASBeautifier::getNextWord(currentLine, charNum) == AS_ELSE)
 1118                 {
 1119                     // handle special case of "else" at the end of line
 1120                     size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
 1121                     if (ASBeautifier::peekNextChar(currentLine, nextText + 3) == ' ')
 1122                         shouldBreakLineAtNextChar = true;
 1123                 }
 1124             }
 1125 
 1126             // format braces
 1127             appendOpeningBrace = false;
 1128             if (isBraceType(braceType, ARRAY_TYPE))
 1129             {
 1130                 formatArrayBraces(braceType, isOpeningArrayBrace);
 1131             }
 1132             else
 1133             {
 1134                 if (currentChar == '{')
 1135                     formatOpeningBrace(braceType);
 1136                 else
 1137                     formatClosingBrace(braceType);
 1138             }
 1139             continue;
 1140         }
 1141 
 1142         if ((((previousCommandChar == '{' && isPreviousBraceBlockRelated)
 1143                 || ((previousCommandChar == '}'
 1144                      && !isImmediatelyPostEmptyBlock
 1145                      && isPreviousBraceBlockRelated
 1146                      && !isPreviousCharPostComment       // Fixes wrongly appended newlines after '}' immediately after comments
 1147                      && peekNextChar() != ' '
 1148                      && !isBraceType(previousBraceType, DEFINITION_TYPE))
 1149                     && !isBraceType(braceTypeStack->back(), DEFINITION_TYPE)))
 1150                 && isOkToBreakBlock(braceTypeStack->back()))
 1151                 // check for array
 1152                 || (previousCommandChar == '{'          // added 9/30/2010
 1153                     && isBraceType(braceTypeStack->back(), ARRAY_TYPE)
 1154                     && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
 1155                     && isNonInStatementArray)
 1156                 // check for pico one line braces
 1157                 || (formattingStyle == STYLE_PICO
 1158                     && (previousCommandChar == '{' && isPreviousBraceBlockRelated)
 1159                     && isBraceType(braceTypeStack->back(), COMMAND_TYPE)
 1160                     && isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
 1161                     && braceFormatMode == RUN_IN_MODE)
 1162            )
 1163         {
 1164             isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
 1165             isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
 1166 
 1167             if (isCharImmediatelyPostOpenBlock
 1168                     && !isCharImmediatelyPostComment
 1169                     && !isCharImmediatelyPostLineComment)
 1170             {
 1171                 previousCommandChar = ' ';
 1172 
 1173                 if (braceFormatMode == NONE_MODE)
 1174                 {
 1175                     if (isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
 1176                             && (isBraceType(braceTypeStack->back(), BREAK_BLOCK_TYPE)
 1177                                 || shouldBreakOneLineBlocks))
 1178                         isInLineBreak = true;
 1179                     else if (currentLineBeginsWithBrace)
 1180                         formatRunIn();
 1181                     else
 1182                         breakLine();
 1183                 }
 1184                 else if (braceFormatMode == RUN_IN_MODE
 1185                          && currentChar != '#')
 1186                     formatRunIn();
 1187                 else
 1188                     isInLineBreak = true;
 1189             }
 1190             else if (isCharImmediatelyPostCloseBlock
 1191                      && shouldBreakOneLineStatements
 1192                      && !isCharImmediatelyPostComment
 1193                      && ((isLegalNameChar(currentChar) && currentChar != '.')
 1194                          || currentChar == '+'
 1195                          || currentChar == '-'
 1196                          || currentChar == '*'
 1197                          || currentChar == '&'
 1198                          || currentChar == '('))
 1199             {
 1200                 previousCommandChar = ' ';
 1201                 isInLineBreak = true;
 1202             }
 1203         }
 1204 
 1205         // reset block handling flags
 1206         isImmediatelyPostEmptyBlock = false;
 1207 
 1208         // Objective-C method prefix with no return type
 1209         if (isImmediatelyPostObjCMethodPrefix && currentChar != '(')
 1210         {
 1211             if (shouldPadMethodPrefix || shouldUnPadMethodPrefix)
 1212                 padObjCMethodPrefix();
 1213             isImmediatelyPostObjCMethodPrefix = false;
 1214         }
 1215 
 1216         // look for headers
 1217         bool isPotentialHeader = isCharPotentialHeader(currentLine, charNum);
 1218 
 1219         if (isPotentialHeader && !isInTemplate && squareBracketCount == 0)
 1220         {
 1221             isNonParenHeader = false;
 1222             foundClosingHeader = false;
 1223 
 1224             newHeader = findHeader(headers);
 1225 
 1226             // java can have a 'default' not in a switch
 1227             if (newHeader == &AS_DEFAULT
 1228                     && ASBeautifier::peekNextChar(
 1229                         currentLine, charNum + (*newHeader).length() - 1) != ':')
 1230                 newHeader = nullptr;
 1231             // Qt headers may be variables in C++
 1232             if (isCStyle()
 1233                     && (newHeader == &AS_FOREVER || newHeader == &AS_FOREACH))
 1234             {
 1235                 if (currentLine.find_first_of("=;", charNum) != string::npos)
 1236                     newHeader = nullptr;
 1237             }
 1238             if (isJavaStyle()
 1239                     && (newHeader == &AS_SYNCHRONIZED))
 1240             {
 1241                 // want synchronized statements not synchronized methods
 1242                 if (!isBraceType(braceTypeStack->back(), COMMAND_TYPE))
 1243                     newHeader = nullptr;
 1244             }
 1245             else if (newHeader == &AS_USING
 1246                      && ASBeautifier::peekNextChar(
 1247                          currentLine, charNum + (*newHeader).length() - 1) != '(')
 1248                 newHeader = nullptr;
 1249 
 1250             if (newHeader != nullptr)
 1251             {
 1252                 foundClosingHeader = isClosingHeader(newHeader);
 1253 
 1254                 if (!foundClosingHeader)
 1255                 {
 1256                     // these are closing headers
 1257                     if ((newHeader == &AS_WHILE && currentHeader == &AS_DO)
 1258                             || (newHeader == &_AS_FINALLY && currentHeader == &_AS_TRY)
 1259                             || (newHeader == &_AS_EXCEPT && currentHeader == &_AS_TRY))
 1260                         foundClosingHeader = true;
 1261                     // don't append empty block for these related headers
 1262                     else if (isSharpStyle()
 1263                              && previousNonWSChar == '}'
 1264                              && ((newHeader == &AS_SET && currentHeader == &AS_GET)
 1265                                  || (newHeader == &AS_REMOVE && currentHeader == &AS_ADD))
 1266                              && isOkToBreakBlock(braceTypeStack->back()))
 1267                         isAppendPostBlockEmptyLineRequested = false;
 1268                 }
 1269 
 1270                 // TODO: this can be removed in a future release
 1271                 // version 3.0 - break erroneous attached header from previous versions
 1272                 if (isSharpStyle()
 1273                         && ((newHeader == &AS_SET && currentHeader == &AS_GET)
 1274                             || (newHeader == &AS_REMOVE && currentHeader == &AS_ADD))
 1275                         && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
 1276                         && currentLine[currentLine.find_first_not_of(" \t")] == '}')
 1277                     isInLineBreak = true;
 1278                 // END TODO
 1279 
 1280                 const string* previousHeader = currentHeader;
 1281                 currentHeader = newHeader;
 1282                 needHeaderOpeningBrace = true;
 1283 
 1284                 // is the previous statement on the same line?
 1285                 if ((previousNonWSChar == ';' || previousNonWSChar == ':')
 1286                         && !isInLineBreak
 1287                         && isOkToBreakBlock(braceTypeStack->back()))
 1288                 {
 1289                     // if breaking lines, break the line at the header
 1290                     // except for multiple 'case' statements on a line
 1291                     if (maxCodeLength != string::npos
 1292                             && previousHeader != &AS_CASE)
 1293                         isInLineBreak = true;
 1294                     else
 1295                         isHeaderInMultiStatementLine = true;
 1296                 }
 1297 
 1298                 if (foundClosingHeader && previousNonWSChar == '}')
 1299                 {
 1300                     if (isOkToBreakBlock(braceTypeStack->back()))
 1301                         isLineBreakBeforeClosingHeader();
 1302 
 1303                     // get the adjustment for a comment following the closing header
 1304                     if (isInLineBreak)
 1305                         nextLineSpacePadNum = getNextLineCommentAdjustment();
 1306                     else
 1307                         spacePadNum = getCurrentLineCommentAdjustment();
 1308                 }
 1309 
 1310                 // check if the found header is non-paren header
 1311                 isNonParenHeader = findHeader(nonParenHeaders) != nullptr;
 1312 
 1313                 if (isNonParenHeader
 1314                         && (currentHeader == &AS_CATCH
 1315                             || currentHeader == &AS_CASE))
 1316                 {
 1317                     int startChar = charNum + currentHeader->length() - 1;
 1318                     if (ASBeautifier::peekNextChar(currentLine, startChar) == '(')
 1319                         isNonParenHeader = false;
 1320                 }
 1321 
 1322                 // join 'else if' statements
 1323                 if (currentHeader == &AS_IF
 1324                         && previousHeader == &AS_ELSE
 1325                         && isInLineBreak
 1326                         && !shouldBreakElseIfs
 1327                         && !isCharImmediatelyPostLineComment
 1328                         && !isImmediatelyPostPreprocessor)
 1329                 {
 1330                     // 'else' must be last thing on the line
 1331                     size_t start = formattedLine.length() >= 6 ? formattedLine.length() - 6 : 0;
 1332                     if (formattedLine.find(AS_ELSE, start) != string::npos)
 1333                     {
 1334                         appendSpacePad();
 1335                         isInLineBreak = false;
 1336                     }
 1337                 }
 1338 
 1339                 appendSequence(*currentHeader);
 1340                 goForward(currentHeader->length() - 1);
 1341                 // if a paren-header is found add a space after it, if needed
 1342                 // this checks currentLine, appendSpacePad() checks formattedLine
 1343                 // in 'case' and C# 'catch' can be either a paren or non-paren header
 1344                 if (shouldPadHeader
 1345                         && !isNonParenHeader
 1346                         && charNum < (int) currentLine.length() - 1 && !isWhiteSpace(currentLine[charNum + 1]))
 1347                     appendSpacePad();
 1348 
 1349                 // Signal that a header has been reached
 1350                 // *** But treat a closing while() (as in do...while)
 1351                 //     as if it were NOT a header since a closing while()
 1352                 //     should never have a block after it!
 1353                 if (currentHeader != &AS_CASE && currentHeader != &AS_DEFAULT
 1354                         && !(foundClosingHeader && currentHeader == &AS_WHILE))
 1355                 {
 1356                     isInHeader = true;
 1357 
 1358                     // in C# 'catch' and 'delegate' can be a paren or non-paren header
 1359                     if (isNonParenHeader && !isSharpStyleWithParen(currentHeader))
 1360                     {
 1361                         isImmediatelyPostHeader = true;
 1362                         isInHeader = false;
 1363                     }
 1364                 }
 1365 
 1366                 if (shouldBreakBlocks
 1367                         && isOkToBreakBlock(braceTypeStack->back())
 1368                         && !isHeaderInMultiStatementLine)
 1369                 {
 1370                     if (previousHeader == nullptr
 1371                             && !foundClosingHeader
 1372                             && !isCharImmediatelyPostOpenBlock
 1373                             && !isImmediatelyPostCommentOnly)
 1374                     {
 1375                         isPrependPostBlockEmptyLineRequested = true;
 1376                     }
 1377 
 1378                     if (isClosingHeader(currentHeader)
 1379                             || foundClosingHeader)
 1380                     {
 1381                         isPrependPostBlockEmptyLineRequested = false;
 1382                     }
 1383 
 1384                     if (shouldBreakClosingHeaderBlocks
 1385                             && isCharImmediatelyPostCloseBlock
 1386                             && !isImmediatelyPostCommentOnly
 1387                             && !(currentHeader == &AS_WHILE         // do-while
 1388                                  && foundClosingHeader))
 1389                     {
 1390                         isPrependPostBlockEmptyLineRequested = true;
 1391                     }
 1392                 }
 1393 
 1394                 if (currentHeader == &AS_CASE
 1395                         || currentHeader == &AS_DEFAULT)
 1396                     isInCase = true;
 1397 
 1398                 continue;
 1399             }
 1400             if ((newHeader = findHeader(preDefinitionHeaders)) != nullptr
 1401                     && parenStack->back() == 0
 1402                     && !isInEnum)       // not C++11 enum class
 1403             {
 1404                 if (newHeader == &AS_NAMESPACE || newHeader == &AS_MODULE)
 1405                     foundNamespaceHeader = true;
 1406                 if (newHeader == &AS_CLASS)
 1407                     foundClassHeader = true;
 1408                 if (newHeader == &AS_STRUCT)
 1409                     foundStructHeader = true;
 1410                 if (newHeader == &AS_INTERFACE && !foundNamespaceHeader && !foundClassHeader)
 1411                     foundInterfaceHeader = true;
 1412                 foundPreDefinitionHeader = true;
 1413                 appendSequence(*newHeader);
 1414                 goForward(newHeader->length() - 1);
 1415 
 1416                 continue;
 1417             }
 1418             if ((newHeader = findHeader(preCommandHeaders)) != nullptr)
 1419             {
 1420                 // must be after function arguments
 1421                 if (previousNonWSChar == ')')
 1422                     foundPreCommandHeader = true;
 1423             }
 1424             else if ((newHeader = findHeader(castOperators)) != nullptr)
 1425             {
 1426                 foundCastOperator = true;
 1427                 appendSequence(*newHeader);
 1428                 goForward(newHeader->length() - 1);
 1429                 continue;
 1430             }
 1431         }   // (isPotentialHeader && !isInTemplate)
 1432 
 1433         if (isInLineBreak)          // OK to break line here
 1434         {
 1435             breakLine();
 1436             if (isInVirginLine)     // adjust for the first line
 1437             {
 1438                 lineCommentNoBeautify = lineCommentNoIndent;
 1439                 lineCommentNoIndent = false;
 1440                 if (isImmediatelyPostPreprocessor)
 1441                 {
 1442                     isInIndentablePreproc = isIndentableProprocessor;
 1443                     isIndentableProprocessor = false;
 1444                 }
 1445             }
 1446         }
 1447 
 1448         if (previousNonWSChar == '}' || currentChar == ';')
 1449         {
 1450             if (currentChar == ';')
 1451             {
 1452                 squareBracketCount = 0;
 1453                 //assert(methodBreakCharNum == string::npos);   // comment out
 1454                 //assert(methodBreakLineNum == 0);              // comment out
 1455                 methodBreakCharNum = string::npos;
 1456                 methodBreakLineNum = 0;
 1457                 methodAttachCharNum = string::npos;
 1458                 methodAttachLineNum = 0;
 1459 
 1460                 if (((shouldBreakOneLineStatements
 1461                         || isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
 1462                         && isOkToBreakBlock(braceTypeStack->back()))
 1463                         && !(attachClosingBraceMode && peekNextChar() == '}'))
 1464                 {
 1465                     passedSemicolon = true;
 1466                 }
 1467                 else if (!shouldBreakOneLineStatements
 1468                          && ASBeautifier::getNextWord(currentLine, charNum) == AS_ELSE)
 1469                 {
 1470                     // handle special case of "else" at the end of line
 1471                     size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
 1472                     if (ASBeautifier::peekNextChar(currentLine, nextText + 3) == ' ')
 1473                         passedSemicolon = true;
 1474                 }
 1475 
 1476                 if (shouldBreakBlocks
 1477                         && currentHeader != nullptr
 1478                         && currentHeader != &AS_CASE
 1479                         && currentHeader != &AS_DEFAULT
 1480                         && !isHeaderInMultiStatementLine
 1481                         && parenStack->back() == 0)
 1482                 {
 1483                     isAppendPostBlockEmptyLineRequested = true;
 1484                 }
 1485             }
 1486             if (currentChar != ';'
 1487                     || (needHeaderOpeningBrace && parenStack->back() == 0))
 1488                 currentHeader = nullptr;
 1489 
 1490             resetEndOfStatement();
 1491         }
 1492 
 1493         if (currentChar == ':'
 1494                 && previousChar != ':'         // not part of '::'
 1495                 && peekNextChar() != ':')      // not part of '::'
 1496         {
 1497             if (isInCase)
 1498             {
 1499                 isInCase = false;
 1500                 if (shouldBreakOneLineStatements)
 1501                     passedColon = true;
 1502             }
 1503             else if (isCStyle()                     // for C/C++ only
 1504                      && isOkToBreakBlock(braceTypeStack->back())
 1505                      && shouldBreakOneLineStatements
 1506                      && !foundQuestionMark          // not in a ?: sequence
 1507                      && !foundPreDefinitionHeader   // not in a definition block
 1508                      && previousCommandChar != ')'  // not after closing paren of a method header
 1509                      && !foundPreCommandHeader      // not after a 'noexcept'
 1510                      && squareBracketCount == 0     // not in objC method call
 1511                      && !isInObjCMethodDefinition   // not objC '-' or '+' method
 1512                      && !isInObjCInterface          // not objC @interface
 1513                      && !isInObjCSelector           // not objC @selector
 1514                      && !isDigit(peekNextChar())    // not a bit field
 1515                      && !isInEnum                   // not an enum with a base type
 1516                      && !isInAsm                    // not in extended assembler
 1517                      && !isInAsmOneLine             // not in extended assembler
 1518                      && !isInAsmBlock)              // not in extended assembler
 1519             {
 1520                 passedColon = true;
 1521             }
 1522 
 1523             if (isCStyle()
 1524                     && (squareBracketCount > 0 || isInObjCMethodDefinition || isInObjCSelector)
 1525                     && !foundQuestionMark)          // not in a ?: sequence
 1526             {
 1527                 isImmediatelyPostObjCMethodPrefix = false;
 1528                 isInObjCReturnType = false;
 1529                 isInObjCParam = true;
 1530                 if (shouldPadMethodColon)
 1531                     padObjCMethodColon();
 1532             }
 1533 
 1534             if (isInObjCInterface)
 1535             {
 1536                 appendSpacePad();
 1537                 if ((int) currentLine.length() > charNum + 1
 1538                         && !isWhiteSpace(currentLine[charNum + 1]))
 1539                     currentLine.insert(charNum + 1, " ");
 1540             }
 1541 
 1542             if (isClassInitializer())
 1543                 isInClassInitializer = true;
 1544         }
 1545 
 1546         if (currentChar == '?')
 1547             foundQuestionMark = true;
 1548 
 1549         if (isPotentialHeader && !isInTemplate)
 1550         {
 1551             if (findKeyword(currentLine, charNum, AS_NEW)
 1552                     || findKeyword(currentLine, charNum, AS_DELETE))
 1553             {
 1554                 isInPotentialCalculation = false;
 1555                 isImmediatelyPostNewDelete = true;
 1556             }
 1557 
 1558             if (findKeyword(currentLine, charNum, AS_RETURN))
 1559             {
 1560                 isInPotentialCalculation = true;
 1561                 isImmediatelyPostReturn = true;     // return is the same as an = sign
 1562             }
 1563 
 1564             if (findKeyword(currentLine, charNum, AS_OPERATOR))
 1565                 isImmediatelyPostOperator = true;
 1566 
 1567             if (findKeyword(currentLine, charNum, AS_ENUM))
 1568             {
 1569                 size_t firstNum = currentLine.find_first_of("(){},/");
 1570                 if (firstNum == string::npos
 1571                         || currentLine[firstNum] == '{'
 1572                         || currentLine[firstNum] == '/')
 1573                     isInEnum = true;
 1574             }
 1575 
 1576             if (isCStyle()
 1577                     && findKeyword(currentLine, charNum, AS_THROW)
 1578                     && previousCommandChar != ')'
 1579                     && !foundPreCommandHeader)      // 'const' throw()
 1580                 isImmediatelyPostThrow = true;
 1581 
 1582             if (isCStyle() && findKeyword(currentLine, charNum, AS_EXTERN) && isExternC())
 1583                 isInExternC = true;
 1584 
 1585             if (isCStyle() && findKeyword(currentLine, charNum, AS_AUTO)
 1586                     && (isBraceType(braceTypeStack->back(), NULL_TYPE)
 1587                         || isBraceType(braceTypeStack->back(), DEFINITION_TYPE)))
 1588                 foundTrailingReturnType = true;
 1589 
 1590             // check for break/attach return type
 1591             if (shouldBreakReturnType || shouldBreakReturnTypeDecl
 1592                     || shouldAttachReturnType || shouldAttachReturnTypeDecl)
 1593             {
 1594                 if ((isBraceType(braceTypeStack->back(), NULL_TYPE)
 1595                         || isBraceType(braceTypeStack->back(), DEFINITION_TYPE))
 1596                         && !returnTypeChecked
 1597                         && !foundNamespaceHeader
 1598                         && !foundClassHeader
 1599                         && !isInObjCMethodDefinition
 1600                         // bypass objective-C and java @ character
 1601                         && charNum == (int) currentLine.find_first_not_of(" \t")
 1602                         && !(isCStyle() && isCharPotentialHeader(currentLine, charNum)
 1603                              && (findKeyword(currentLine, charNum, AS_PUBLIC)
 1604                                  || findKeyword(currentLine, charNum, AS_PRIVATE)
 1605                                  || findKeyword(currentLine, charNum, AS_PROTECTED))))
 1606                 {
 1607                     findReturnTypeSplitPoint(currentLine);
 1608                     returnTypeChecked = true;
 1609                 }
 1610             }
 1611 
 1612             // Objective-C NSException macros are preCommandHeaders
 1613             if (isCStyle() && findKeyword(currentLine, charNum, AS_NS_DURING))
 1614                 foundPreCommandMacro = true;
 1615             if (isCStyle() && findKeyword(currentLine, charNum, AS_NS_HANDLER))
 1616                 foundPreCommandMacro = true;
 1617 
 1618             if (isCStyle() && isExecSQL(currentLine, charNum))
 1619                 isInExecSQL = true;
 1620 
 1621             if (isCStyle())
 1622             {
 1623                 if (findKeyword(currentLine, charNum, AS_ASM)
 1624                         || findKeyword(currentLine, charNum, AS__ASM__))
 1625                 {
 1626                     isInAsm = true;
 1627                 }
 1628                 else if (findKeyword(currentLine, charNum, AS_MS_ASM)       // microsoft specific
 1629                          || findKeyword(currentLine, charNum, AS_MS__ASM))
 1630                 {
 1631                     int index = 4;
 1632                     if (peekNextChar() == '_')  // check for __asm
 1633                         index = 5;
 1634 
 1635                     char peekedChar = ASBase::peekNextChar(currentLine, charNum + index);
 1636                     if (peekedChar == '{' || peekedChar == ' ')
 1637                         isInAsmBlock = true;
 1638                     else
 1639                         isInAsmOneLine = true;
 1640                 }
 1641             }
 1642 
 1643             if (isJavaStyle()
 1644                     && (findKeyword(currentLine, charNum, AS_STATIC)
 1645                         && isNextCharOpeningBrace(charNum + 6)))
 1646                 isJavaStaticConstructor = true;
 1647 
 1648             if (isSharpStyle()
 1649                     && (findKeyword(currentLine, charNum, AS_DELEGATE)
 1650                         || findKeyword(currentLine, charNum, AS_UNCHECKED)))
 1651                 isSharpDelegate = true;
 1652 
 1653             // append the entire name
 1654             string name = getCurrentWord(currentLine, charNum);
 1655             // must pad the 'and' and 'or' operators if required
 1656             if (name == "and" || name == "or")
 1657             {
 1658                 if (shouldPadOperators && previousNonWSChar != ':')
 1659                 {
 1660                     appendSpacePad();
 1661                     appendOperator(name);
 1662                     goForward(name.length() - 1);
 1663                     if (!isBeforeAnyComment()
 1664                             && !(currentLine.compare(charNum + 1, 1, AS_SEMICOLON) == 0)
 1665                             && !(currentLine.compare(charNum + 1, 2, AS_SCOPE_RESOLUTION) == 0))
 1666                         appendSpaceAfter();
 1667                 }
 1668                 else
 1669                 {
 1670                     appendOperator(name);
 1671                     goForward(name.length() - 1);
 1672                 }
 1673             }
 1674             else
 1675             {
 1676                 appendSequence(name);
 1677                 goForward(name.length() - 1);
 1678             }
 1679 
 1680             continue;
 1681 
 1682         }   // (isPotentialHeader &&  !isInTemplate)
 1683 
 1684         // determine if this is an Objective-C statement
 1685 
 1686         if (currentChar == '@'
 1687                 && isCStyle()
 1688                 && (int) currentLine.length() > charNum + 1
 1689                 && !isWhiteSpace(currentLine[charNum + 1])
 1690                 && isCharPotentialHeader(currentLine, charNum + 1)
 1691                 && findKeyword(currentLine, charNum + 1, AS_INTERFACE)
 1692                 && isBraceType(braceTypeStack->back(), NULL_TYPE))
 1693         {
 1694             isInObjCInterface = true;
 1695             string name = '@' + AS_INTERFACE;
 1696             appendSequence(name);
 1697             goForward(name.length() - 1);
 1698             continue;
 1699         }
 1700         if (currentChar == '@'
 1701                 && isCStyle()
 1702                 && (int) currentLine.length() > charNum + 1
 1703                 && !isWhiteSpace(currentLine[charNum + 1])
 1704                 && isCharPotentialHeader(currentLine, charNum + 1)
 1705                 && findKeyword(currentLine, charNum + 1, AS_SELECTOR))
 1706         {
 1707             isInObjCSelector = true;
 1708             string name = '@' + AS_SELECTOR;
 1709             appendSequence(name);
 1710             goForward(name.length() - 1);
 1711             continue;
 1712         }
 1713         if ((currentChar == '-' || currentChar == '+')
 1714                 && isCStyle()
 1715                 && (int) currentLine.find_first_not_of(" \t") == charNum
 1716                 && !isInPotentialCalculation
 1717                 && !isInObjCMethodDefinition
 1718                 && (isBraceType(braceTypeStack->back(), NULL_TYPE)
 1719                     || (isBraceType(braceTypeStack->back(), EXTERN_TYPE))))
 1720         {
 1721             isInObjCMethodDefinition = true;
 1722             isImmediatelyPostObjCMethodPrefix = true;
 1723             isInObjCParam = false;
 1724             isInObjCInterface = false;
 1725             if (getAlignMethodColon())
 1726                 objCColonAlign = findObjCColonAlignment();
 1727             appendCurrentChar();
 1728             continue;
 1729         }
 1730 
 1731         // determine if this is a potential calculation
 1732 
 1733         bool isPotentialOperator = isCharPotentialOperator(currentChar);
 1734         newHeader = nullptr;
 1735 
 1736         if (isPotentialOperator)
 1737         {
 1738             newHeader = findOperator(operators);
 1739 
 1740             // check for Java ? wildcard
 1741             if (newHeader != nullptr
 1742                     && newHeader == &AS_GCC_MIN_ASSIGN
 1743                     && isJavaStyle()
 1744                     && isInTemplate)
 1745                 newHeader = nullptr;
 1746 
 1747             if (newHeader != nullptr)
 1748             {
 1749                 if (newHeader == &AS_LAMBDA)
 1750                     foundPreCommandHeader = true;
 1751 
 1752                 // correct mistake of two >> closing a template
 1753                 if (isInTemplate && (newHeader == &AS_GR_GR || newHeader == &AS_GR_GR_GR))
 1754                     newHeader = &AS_GR;
 1755 
 1756                 if (!isInPotentialCalculation)
 1757                 {
 1758                     // must determine if newHeader is an assignment operator
 1759                     // do NOT use findOperator - the length must be exact!!!
 1760                     if (find(begin(*assignmentOperators), end(*assignmentOperators), newHeader)
 1761                             != end(*assignmentOperators))
 1762                     {
 1763                         foundPreCommandHeader = false;
 1764                         char peekedChar = peekNextChar();
 1765                         isInPotentialCalculation = !(newHeader == &AS_EQUAL && peekedChar == '*')
 1766                                                    && !(newHeader == &AS_EQUAL && peekedChar == '&')
 1767                                                    && !isCharImmediatelyPostOperator;
 1768                     }
 1769                 }
 1770             }
 1771         }
 1772 
 1773         // process pointers and references
 1774         // check newHeader to eliminate things like '&&' sequence
 1775         if (newHeader != nullptr && !isJavaStyle()
 1776                 && (newHeader == &AS_MULT
 1777                     || newHeader == &AS_BIT_AND
 1778                     || newHeader == &AS_BIT_XOR
 1779                     || newHeader == &AS_AND)
 1780                 && isPointerOrReference())
 1781         {
 1782             if (!isDereferenceOrAddressOf() && !isOperatorPaddingDisabled())
 1783                 formatPointerOrReference();
 1784             else
 1785             {
 1786                 appendOperator(*newHeader);
 1787                 goForward(newHeader->length() - 1);
 1788             }
 1789             isImmediatelyPostPointerOrReference = true;
 1790             continue;
 1791         }
 1792 
 1793         if (shouldPadOperators && newHeader != nullptr && !isOperatorPaddingDisabled())
 1794         {
 1795             padOperators(newHeader);
 1796             continue;
 1797         }
 1798 
 1799         // remove spaces before commas
 1800         if (currentChar == ',')
 1801         {
 1802             const size_t len = formattedLine.length();
 1803             size_t lastText = formattedLine.find_last_not_of(' ');
 1804             if (lastText != string::npos && lastText < len - 1)
 1805             {
 1806                 formattedLine.resize(lastText + 1);
 1807                 int size_diff = len - (lastText + 1);
 1808                 spacePadNum -= size_diff;
 1809             }
 1810         }
 1811 
 1812         // pad commas and semi-colons
 1813         if (currentChar == ';'
 1814                 || (currentChar == ',' && (shouldPadOperators || shouldPadCommas)))
 1815         {
 1816             char nextChar = ' ';
 1817             if (charNum + 1 < (int) currentLine.length())
 1818                 nextChar = currentLine[charNum + 1];
 1819             if (!isWhiteSpace(nextChar)
 1820                     && nextChar != '}'
 1821                     && nextChar != ')'
 1822                     && nextChar != ']'
 1823                     && nextChar != '>'
 1824                     && nextChar != ';'
 1825                     && !isBeforeAnyComment()
 1826                     /* && !(isBraceType(braceTypeStack->back(), ARRAY_TYPE)) */
 1827                )
 1828             {
 1829                 appendCurrentChar();
 1830                 appendSpaceAfter();
 1831                 continue;
 1832             }
 1833         }
 1834 
 1835         // pad parens
 1836         if (currentChar == '(' || currentChar == ')')
 1837         {
 1838             if (currentChar == '(')
 1839             {
 1840                 if (shouldPadHeader
 1841                         && (isCharImmediatelyPostReturn
 1842                             || isCharImmediatelyPostThrow
 1843                             || isCharImmediatelyPostNewDelete))
 1844                     appendSpacePad();
 1845             }
 1846 
 1847             if (shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen)
 1848                 padParens();
 1849             else
 1850                 appendCurrentChar();
 1851 
 1852             if (isInObjCMethodDefinition)
 1853             {
 1854                 if (currentChar == '(' && isImmediatelyPostObjCMethodPrefix)
 1855                 {
 1856                     if (shouldPadMethodPrefix || shouldUnPadMethodPrefix)
 1857                         padObjCMethodPrefix();
 1858                     isImmediatelyPostObjCMethodPrefix = false;
 1859                     isInObjCReturnType = true;
 1860                 }
 1861                 else if (currentChar == ')' && isInObjCReturnType)
 1862                 {
 1863                     if (shouldPadReturnType || shouldUnPadReturnType)
 1864                         padObjCReturnType();
 1865                     isInObjCReturnType = false;
 1866                 }
 1867                 else if (isInObjCParam
 1868                          && (shouldPadParamType || shouldUnPadParamType))
 1869                     padObjCParamType();
 1870             }
 1871             continue;
 1872         }
 1873 
 1874         // bypass the entire operator
 1875         if (newHeader != nullptr)
 1876         {
 1877             appendOperator(*newHeader);
 1878             goForward(newHeader->length() - 1);
 1879             continue;
 1880         }
 1881 
 1882         appendCurrentChar();
 1883 
 1884     }   // end of while loop  *  end of while loop  *  end of while loop  *  end of while loop
 1885 
 1886     // return a beautified (i.e. correctly indented) line.
 1887 
 1888     string beautifiedLine;
 1889     size_t readyFormattedLineLength = trim(readyFormattedLine).length();
 1890     bool isInNamespace = isBraceType(braceTypeStack->back(), NAMESPACE_TYPE);
 1891 
 1892     if (prependEmptyLine        // prepend a blank line before this formatted line
 1893             && readyFormattedLineLength > 0
 1894             && previousReadyFormattedLineLength > 0)
 1895     {
 1896         isLineReady = true;     // signal a waiting readyFormattedLine
 1897         beautifiedLine = beautify("");
 1898         previousReadyFormattedLineLength = 0;
 1899         // call the enhancer for new empty lines
 1900         enhancer->enhance(beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL);
 1901     }
 1902     else        // format the current formatted line
 1903     {
 1904         isLineReady = false;
 1905         runInIndentContinuation = runInIndentChars;
 1906         beautifiedLine = beautify(readyFormattedLine);
 1907         previousReadyFormattedLineLength = readyFormattedLineLength;
 1908         // the enhancer is not called for no-indent line comments
 1909         if (!lineCommentNoBeautify && !isFormattingModeOff)
 1910             enhancer->enhance(beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL);
 1911         runInIndentChars = 0;
 1912         lineCommentNoBeautify = lineCommentNoIndent;
 1913         lineCommentNoIndent = false;
 1914         isInIndentablePreproc = isIndentableProprocessor;
 1915         isIndentableProprocessor = false;
 1916         isElseHeaderIndent = elseHeaderFollowsComments;
 1917         isCaseHeaderCommentIndent = caseHeaderFollowsComments;
 1918         objCColonAlignSubsequent = objCColonAlign;
 1919         if (isCharImmediatelyPostNonInStmt)
 1920         {
 1921             isNonInStatementArray = false;
 1922             isCharImmediatelyPostNonInStmt = false;
 1923         }
 1924         isInPreprocessorBeautify = isInPreprocessor;    // used by ASEnhancer
 1925         isInBeautifySQL = isInExecSQL;                  // used by ASEnhancer
 1926     }
 1927 
 1928     prependEmptyLine = false;
 1929     assert(computeChecksumOut(beautifiedLine));
 1930     return beautifiedLine;
 1931 }
 1932 
 1933 /**
 1934  * check if there are any indented lines ready to be read by nextLine()
 1935  *
 1936  * @return    are there any indented lines ready?
 1937  */
 1938 bool ASFormatter::hasMoreLines() const
 1939 {
 1940     return !endOfCodeReached;
 1941 }
 1942 
 1943 /**
 1944  * comparison function for BraceType enum
 1945  */
 1946 bool ASFormatter::isBraceType(BraceType a, BraceType b) const
 1947 {
 1948     if (a == NULL_TYPE || b == NULL_TYPE)
 1949         return (a == b);
 1950     return ((a & b) == b);
 1951 }
 1952 
 1953 /**
 1954  * set the formatting style.
 1955  *
 1956  * @param style         the formatting style.
 1957  */
 1958 void ASFormatter::setFormattingStyle(FormatStyle style)
 1959 {
 1960     formattingStyle = style;
 1961 }
 1962 
 1963 /**
 1964  * set the add braces mode.
 1965  * options:
 1966  *    true     braces added to headers for single line statements.
 1967  *    false    braces NOT added to headers for single line statements.
 1968  *
 1969  * @param state         the add braces state.
 1970  */
 1971 void ASFormatter::setAddBracesMode(bool state)
 1972 {
 1973     shouldAddBraces = state;
 1974 }
 1975 
 1976 /**
 1977  * set the add one line braces mode.
 1978  * options:
 1979  *    true     one line braces added to headers for single line statements.
 1980  *    false    one line braces NOT added to headers for single line statements.
 1981  *
 1982  * @param state         the add one line braces state.
 1983  */
 1984 void ASFormatter::setAddOneLineBracesMode(bool state)
 1985 {
 1986     shouldAddBraces = state;
 1987     shouldAddOneLineBraces = state;
 1988 }
 1989 
 1990 /**
 1991  * set the remove braces mode.
 1992  * options:
 1993  *    true     braces removed from headers for single line statements.
 1994  *    false    braces NOT removed from headers for single line statements.
 1995  *
 1996  * @param state         the remove braces state.
 1997  */
 1998 void ASFormatter::setRemoveBracesMode(bool state)
 1999 {
 2000     shouldRemoveBraces = state;
 2001 }
 2002 
 2003 // retained for compatibility with release 2.06
 2004 // "Brackets" have been changed to "Braces" in 3.0
 2005 // it is referenced only by the old "bracket" options
 2006 void ASFormatter::setAddBracketsMode(bool state)
 2007 {
 2008     setAddBracesMode(state);
 2009 }
 2010 
 2011 // retained for compatibility with release 2.06
 2012 // "Brackets" have been changed to "Braces" in 3.0
 2013 // it is referenced only by the old "bracket" options
 2014 void ASFormatter::setAddOneLineBracketsMode(bool state)
 2015 {
 2016     setAddOneLineBracesMode(state);
 2017 }
 2018 
 2019 // retained for compatibility with release 2.06
 2020 // "Brackets" have been changed to "Braces" in 3.0
 2021 // it is referenced only by the old "bracket" options
 2022 void ASFormatter::setRemoveBracketsMode(bool state)
 2023 {
 2024     setRemoveBracesMode(state);
 2025 }
 2026 
 2027 // retained for compatibility with release 2.06
 2028 // "Brackets" have been changed to "Braces" in 3.0
 2029 // it is referenced only by the old "bracket" options
 2030 void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
 2031 {
 2032     setBreakClosingHeaderBracesMode(state);
 2033 }
 2034 
 2035 /**
 2036  * set the brace formatting mode.
 2037  * options:
 2038  *
 2039  * @param mode         the brace formatting mode.
 2040  */
 2041 void ASFormatter::setBraceFormatMode(BraceMode mode)
 2042 {
 2043     braceFormatMode = mode;
 2044 }
 2045 
 2046 /**
 2047  * set 'break after' mode for maximum code length
 2048  *
 2049  * @param state         the 'break after' mode.
 2050  */
 2051 void ASFormatter::setBreakAfterMode(bool state)
 2052 {
 2053     shouldBreakLineAfterLogical = state;
 2054 }
 2055 
 2056 /**
 2057  * set closing header brace breaking mode
 2058  * options:
 2059  *    true     braces just before closing headers (e.g. 'else', 'catch')
 2060  *             will be broken, even if standard braces are attached.
 2061  *    false    closing header braces will be treated as standard braces.
 2062  *
 2063  * @param state         the closing header brace breaking mode.
 2064  */
 2065 void ASFormatter::setBreakClosingHeaderBracesMode(bool state)
 2066 {
 2067     shouldBreakClosingHeaderBraces = state;
 2068 }
 2069 
 2070 /**
 2071  * set 'else if()' breaking mode
 2072  * options:
 2073  *    true     'else' headers will be broken from their succeeding 'if' headers.
 2074  *    false    'else' headers will be attached to their succeeding 'if' headers.
 2075  *
 2076  * @param state         the 'else if()' breaking mode.
 2077  */
 2078 void ASFormatter::setBreakElseIfsMode(bool state)
 2079 {
 2080     shouldBreakElseIfs = state;
 2081 }
 2082 
 2083 /**
 2084 * set comma padding mode.
 2085 * options:
 2086 *    true     statement commas and semicolons will be padded with spaces around them.
 2087 *    false    statement commas and semicolons will not be padded.
 2088 *
 2089 * @param state         the padding mode.
 2090 */
 2091 void ASFormatter::setCommaPaddingMode(bool state)
 2092 {
 2093     shouldPadCommas = state;
 2094 }
 2095 
 2096 /**
 2097  * set maximum code length
 2098  *
 2099  * @param max         the maximum code length.
 2100  */
 2101 void ASFormatter::setMaxCodeLength(int max)
 2102 {
 2103     maxCodeLength = max;
 2104 }
 2105 
 2106 /**
 2107  * set operator padding mode.
 2108  * options:
 2109  *    true     statement operators will be padded with spaces around them.
 2110  *    false    statement operators will not be padded.
 2111  *
 2112  * @param state         the padding mode.
 2113  */
 2114 void ASFormatter::setOperatorPaddingMode(bool state)
 2115 {
 2116     shouldPadOperators = state;
 2117 }
 2118 
 2119 /**
 2120  * set parenthesis outside padding mode.
 2121  * options:
 2122  *    true     statement parentheses will be padded with spaces around them.
 2123  *    false    statement parentheses will not be padded.
 2124  *
 2125  * @param state         the padding mode.
 2126  */
 2127 void ASFormatter::setParensOutsidePaddingMode(bool state)
 2128 {
 2129     shouldPadParensOutside = state;
 2130 }
 2131 
 2132 /**
 2133  * set parenthesis inside padding mode.
 2134  * options:
 2135  *    true     statement parenthesis will be padded with spaces around them.
 2136  *    false    statement parenthesis will not be padded.
 2137  *
 2138  * @param state         the padding mode.
 2139  */
 2140 void ASFormatter::setParensInsidePaddingMode(bool state)
 2141 {
 2142     shouldPadParensInside = state;
 2143 }
 2144 
 2145 /**
 2146  * set padding mode before one or more open parentheses.
 2147  * options:
 2148  *    true     first open parenthesis will be padded with a space before.
 2149  *    false    first open parenthesis will not be padded.
 2150  *
 2151  * @param state         the padding mode.
 2152  */
 2153 void ASFormatter::setParensFirstPaddingMode(bool state)
 2154 {
 2155     shouldPadFirstParen = state;
 2156 }
 2157 
 2158 /**
 2159  * set header padding mode.
 2160  * options:
 2161  *    true     headers will be padded with spaces around them.
 2162  *    false    headers will not be padded.
 2163  *
 2164  * @param state         the padding mode.
 2165  */
 2166 void ASFormatter::setParensHeaderPaddingMode(bool state)
 2167 {
 2168     shouldPadHeader = state;
 2169 }
 2170 
 2171 /**
 2172  * set parenthesis unpadding mode.
 2173  * options:
 2174  *    true     statement parenthesis will be unpadded with spaces removed around them.
 2175  *    false    statement parenthesis will not be unpadded.
 2176  *
 2177  * @param state         the padding mode.
 2178  */
 2179 void ASFormatter::setParensUnPaddingMode(bool state)
 2180 {
 2181     shouldUnPadParens = state;
 2182 }
 2183 
 2184 /**
 2185 * set the state of the preprocessor indentation option.
 2186 * If true, #ifdef blocks at level 0 will be indented.
 2187 *
 2188 * @param   state             state of option.
 2189 */
 2190 void ASFormatter::setPreprocBlockIndent(bool state)
 2191 {
 2192     shouldIndentPreprocBlock = state;
 2193 }
 2194 
 2195 /**
 2196  * Set strip comment prefix mode.
 2197  * options:
 2198  *    true     strip leading '*' in a comment.
 2199  *    false    leading '*' in a comment will be left unchanged.
 2200  *
 2201  * @param state         the strip comment prefix mode.
 2202  */
 2203 void ASFormatter::setStripCommentPrefix(bool state)
 2204 {
 2205     shouldStripCommentPrefix = state;
 2206 }
 2207 
 2208 /**
 2209  * set objective-c '-' or '+' class prefix padding mode.
 2210  * options:
 2211  *    true     class prefix will be padded a spaces after them.
 2212  *    false    class prefix will be left unchanged.
 2213  *
 2214  * @param state         the padding mode.
 2215  */
 2216 void ASFormatter::setMethodPrefixPaddingMode(bool state)
 2217 {
 2218     shouldPadMethodPrefix = state;
 2219 }
 2220 
 2221 /**
 2222  * set objective-c '-' or '+' class prefix unpadding mode.
 2223  * options:
 2224  *    true     class prefix will be unpadded with spaces after them removed.
 2225  *    false    class prefix will left unchanged.
 2226  *
 2227  * @param state         the unpadding mode.
 2228  */
 2229 void ASFormatter::setMethodPrefixUnPaddingMode(bool state)
 2230 {
 2231     shouldUnPadMethodPrefix = state;
 2232 }
 2233 
 2234 // set objective-c '-' or '+' return type padding mode.
 2235 void ASFormatter::setReturnTypePaddingMode(bool state)
 2236 {
 2237     shouldPadReturnType = state;
 2238 }
 2239 
 2240 // set objective-c '-' or '+' return type unpadding mode.
 2241 void ASFormatter::setReturnTypeUnPaddingMode(bool state)
 2242 {
 2243     shouldUnPadReturnType = state;
 2244 }
 2245 
 2246 // set objective-c method parameter type padding mode.
 2247 void ASFormatter::setParamTypePaddingMode(bool state)
 2248 {
 2249     shouldPadParamType = state;
 2250 }
 2251 
 2252 // set objective-c method parameter type unpadding mode.
 2253 void ASFormatter::setParamTypeUnPaddingMode(bool state)
 2254 {
 2255     shouldUnPadParamType = state;
 2256 }
 2257 
 2258 /**
 2259  * set objective-c method colon padding mode.
 2260  *
 2261  * @param mode         objective-c colon padding mode.
 2262  */
 2263 void ASFormatter::setObjCColonPaddingMode(ObjCColonPad mode)
 2264 {
 2265     shouldPadMethodColon = true;
 2266     objCColonPadMode = mode;
 2267 }
 2268 
 2269 /**
 2270  * set option to attach closing braces
 2271  *
 2272  * @param state        true = attach, false = don't attach.
 2273  */
 2274 void ASFormatter::setAttachClosingBraceMode(bool state)
 2275 {
 2276     attachClosingBraceMode = state;
 2277 }
 2278 
 2279 /**
 2280  * set option to attach class braces
 2281  *
 2282  * @param state        true = attach, false = use style default.
 2283  */
 2284 void ASFormatter::setAttachClass(bool state)
 2285 {
 2286     shouldAttachClass = state;
 2287 }
 2288 
 2289 /**
 2290  * set option to attach extern "C" braces
 2291  *
 2292  * @param state        true = attach, false = use style default.
 2293  */
 2294 void ASFormatter::setAttachExternC(bool state)
 2295 {
 2296     shouldAttachExternC = state;
 2297 }
 2298 
 2299 /**
 2300  * set option to attach namespace braces
 2301  *
 2302  * @param state        true = attach, false = use style default.
 2303  */
 2304 void ASFormatter::setAttachNamespace(bool state)
 2305 {
 2306     shouldAttachNamespace = state;
 2307 }
 2308 
 2309 /**
 2310  * set option to attach inline braces
 2311  *
 2312  * @param state        true = attach, false = use style default.
 2313  */
 2314 void ASFormatter::setAttachInline(bool state)
 2315 {
 2316     shouldAttachInline = state;
 2317 }
 2318 
 2319 void ASFormatter::setAttachClosingWhile(bool state)
 2320 {
 2321     shouldAttachClosingWhile = state;
 2322 }
 2323 
 2324 /**
 2325  * set option to break/not break one-line blocks
 2326  *
 2327  * @param state        true = break, false = don't break.
 2328  */
 2329 void ASFormatter::setBreakOneLineBlocksMode(bool state)
 2330 {
 2331     shouldBreakOneLineBlocks = state;
 2332 }
 2333 
 2334 /**
 2335 * set one line headers breaking mode
 2336 */
 2337 void ASFormatter::setBreakOneLineHeadersMode(bool state)
 2338 {
 2339     shouldBreakOneLineHeaders = state;
 2340 }
 2341 
 2342 /**
 2343 * set option to break/not break lines consisting of multiple statements.
 2344 *
 2345 * @param state        true = break, false = don't break.
 2346 */
 2347 void ASFormatter::setBreakOneLineStatementsMode(bool state)
 2348 {
 2349     shouldBreakOneLineStatements = state;
 2350 }
 2351 
 2352 void ASFormatter::setCloseTemplatesMode(bool state)
 2353 {
 2354     shouldCloseTemplates = state;
 2355 }
 2356 
 2357 /**
 2358  * set option to convert tabs to spaces.
 2359  *
 2360  * @param state        true = convert, false = don't convert.
 2361  */
 2362 void ASFormatter::setTabSpaceConversionMode(bool state)
 2363 {
 2364     shouldConvertTabs = state;
 2365 }
 2366 
 2367 /**
 2368  * set option to indent comments in column 1.
 2369  *
 2370  * @param state        true = indent, false = don't indent.
 2371  */
 2372 void ASFormatter::setIndentCol1CommentsMode(bool state)
 2373 {
 2374     shouldIndentCol1Comments = state;
 2375 }
 2376 
 2377 /**
 2378  * set option to force all line ends to a particular style.
 2379  *
 2380  * @param fmt           format enum value
 2381  */
 2382 void ASFormatter::setLineEndFormat(LineEndFormat fmt)
 2383 {
 2384     lineEnd = fmt;
 2385 }
 2386 
 2387 /**
 2388  * set option to break unrelated blocks of code with empty lines.
 2389  *
 2390  * @param state        true = convert, false = don't convert.
 2391  */
 2392 void ASFormatter::setBreakBlocksMode(bool state)
 2393 {
 2394     shouldBreakBlocks = state;
 2395 }
 2396 
 2397 /**
 2398  * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
 2399  *
 2400  * @param state        true = convert, false = don't convert.
 2401  */
 2402 void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
 2403 {
 2404     shouldBreakClosingHeaderBlocks = state;
 2405 }
 2406 
 2407 /**
 2408  * set option to delete empty lines.
 2409  *
 2410  * @param state        true = delete, false = don't delete.
 2411  */
 2412 void ASFormatter::setDeleteEmptyLinesMode(bool state)
 2413 {
 2414     shouldDeleteEmptyLines = state;
 2415 }
 2416 
 2417 void ASFormatter::setBreakReturnType(bool state)
 2418 {
 2419     shouldBreakReturnType = state;
 2420 }
 2421 
 2422 void ASFormatter::setBreakReturnTypeDecl(bool state)
 2423 {
 2424     shouldBreakReturnTypeDecl = state;
 2425 }
 2426 
 2427 void ASFormatter::setAttachReturnType(bool state)
 2428 {
 2429     shouldAttachReturnType = state;
 2430 }
 2431 
 2432 void ASFormatter::setAttachReturnTypeDecl(bool state)
 2433 {
 2434     shouldAttachReturnTypeDecl = state;
 2435 }
 2436 
 2437 /**
 2438  * set the pointer alignment.
 2439  *
 2440  * @param alignment    the pointer alignment.
 2441  */
 2442 void ASFormatter::setPointerAlignment(PointerAlign alignment)
 2443 {
 2444     pointerAlignment = alignment;
 2445 }
 2446 
 2447 void ASFormatter::setReferenceAlignment(ReferenceAlign alignment)
 2448 {
 2449     referenceAlignment = alignment;
 2450 }
 2451 
 2452 /**
 2453  * jump over several characters.
 2454  *
 2455  * @param i       the number of characters to jump over.
 2456  */
 2457 void ASFormatter::goForward(int i)
 2458 {
 2459     while (--i >= 0)
 2460         getNextChar();
 2461 }
 2462 
 2463 /**
 2464  * peek at the next unread character.
 2465  *
 2466  * @return     the next unread character.
 2467  */
 2468 char ASFormatter::peekNextChar() const
 2469 {
 2470     char ch = ' ';
 2471     size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
 2472 
 2473     if (peekNum == string::npos)
 2474         return ch;
 2475 
 2476     ch = currentLine[peekNum];
 2477 
 2478     return ch;
 2479 }
 2480 
 2481 /**
 2482  * check if current placement is before a comment
 2483  *
 2484  * @return     is before a comment.
 2485  */
 2486 bool ASFormatter::isBeforeComment() const
 2487 {
 2488     bool foundComment = false;
 2489     size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
 2490 
 2491     if (peekNum == string::npos)
 2492         return foundComment;
 2493 
 2494     foundComment = (currentLine.compare(peekNum, 2, "/*") == 0);
 2495 
 2496     return foundComment;
 2497 }
 2498 
 2499 /**
 2500  * check if current placement is before a comment or line-comment
 2501  *
 2502  * @return     is before a comment or line-comment.
 2503  */
 2504 bool ASFormatter::isBeforeAnyComment() const
 2505 {
 2506     bool foundComment = false;
 2507     size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
 2508 
 2509     if (peekNum == string::npos)
 2510         return foundComment;
 2511 
 2512     foundComment = (currentLine.compare(peekNum, 2, "/*") == 0
 2513                     || currentLine.compare(peekNum, 2, "//") == 0);
 2514 
 2515     return foundComment;
 2516 }
 2517 
 2518 /**
 2519  * check if current placement is before a comment or line-comment
 2520  * if a block comment it must be at the end of the line
 2521  *
 2522  * @return     is before a comment or line-comment.
 2523  */
 2524 bool ASFormatter::isBeforeAnyLineEndComment(int startPos) const
 2525 {
 2526     bool foundLineEndComment = false;
 2527     size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
 2528 
 2529     if (peekNum != string::npos)
 2530     {
 2531         if (currentLine.compare(peekNum, 2, "//") == 0)
 2532             foundLineEndComment = true;
 2533         else if (currentLine.compare(peekNum, 2, "/*") == 0)
 2534         {
 2535             // comment must be closed on this line with nothing after it
 2536             size_t endNum = currentLine.find("*/", peekNum + 2);
 2537             if (endNum != string::npos)
 2538             {
 2539                 size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2);
 2540                 if (nextChar == string::npos)
 2541                     foundLineEndComment = true;
 2542             }
 2543         }
 2544     }
 2545     return foundLineEndComment;
 2546 }
 2547 
 2548 /**
 2549  * check if current placement is before a comment followed by a line-comment
 2550  *
 2551  * @return     is before a multiple line-end comment.
 2552  */
 2553 bool ASFormatter::isBeforeMultipleLineEndComments(int startPos) const
 2554 {
 2555     bool foundMultipleLineEndComment = false;
 2556     size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
 2557 
 2558     if (peekNum != string::npos)
 2559     {
 2560         if (currentLine.compare(peekNum, 2, "/*") == 0)
 2561         {
 2562             // comment must be closed on this line with nothing after it
 2563             size_t endNum = currentLine.find("*/", peekNum + 2);
 2564             if (endNum != string::npos)
 2565             {
 2566                 size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2);
 2567                 if (nextChar != string::npos
 2568                         && currentLine.compare(nextChar, 2, "//") == 0)
 2569                     foundMultipleLineEndComment = true;
 2570             }
 2571         }
 2572     }
 2573     return foundMultipleLineEndComment;
 2574 }
 2575 
 2576 /**
 2577  * get the next character, increasing the current placement in the process.
 2578  * the new character is inserted into the variable currentChar.
 2579  *
 2580  * @return   whether succeeded to receive the new character.
 2581  */
 2582 bool ASFormatter::getNextChar()
 2583 {
 2584     isInLineBreak = false;
 2585     previousChar = currentChar;
 2586 
 2587     if (!isWhiteSpace(currentChar))
 2588     {
 2589         previousNonWSChar = currentChar;
 2590         if (!isInComment && !isInLineComment && !isInQuote
 2591                 && !isImmediatelyPostComment
 2592                 && !isImmediatelyPostLineComment
 2593                 && !isInPreprocessor
 2594                 && !isSequenceReached("/*")
 2595                 && !isSequenceReached("//"))
 2596             previousCommandChar = currentChar;
 2597     }
 2598 
 2599     if (charNum + 1 < (int) currentLine.length()
 2600             && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
 2601     {
 2602         currentChar = currentLine[++charNum];
 2603 
 2604         if (currentChar == '\t' && shouldConvertTabs)
 2605             convertTabToSpaces();
 2606 
 2607         return true;
 2608     }
 2609 
 2610     // end of line has been reached
 2611     return getNextLine();
 2612 }
 2613 
 2614 /**
 2615  * get the next line of input, increasing the current placement in the process.
 2616  *
 2617  * @param emptyLineWasDeleted         an empty line was deleted.
 2618  * @return   whether succeeded in reading the next line.
 2619  */
 2620 bool ASFormatter::getNextLine(bool emptyLineWasDeleted /*false*/)
 2621 {
 2622     if (!sourceIterator->hasMoreLines())
 2623     {
 2624         endOfCodeReached = true;
 2625         return false;
 2626     }
 2627     if (appendOpeningBrace)
 2628         currentLine = "{";      // append brace that was removed from the previous line
 2629     else
 2630     {
 2631         currentLine = sourceIterator->nextLine(emptyLineWasDeleted);
 2632         assert(computeChecksumIn(currentLine));
 2633     }
 2634     // reset variables for new line
 2635     inLineNumber++;
 2636     if (endOfAsmReached)
 2637         endOfAsmReached = isInAsmBlock = isInAsm = false;
 2638     shouldKeepLineUnbroken = false;
 2639     isInCommentStartLine = false;
 2640     isInCase = false;
 2641     isInAsmOneLine = false;
 2642     isHeaderInMultiStatementLine = false;
 2643     isInQuoteContinuation = isInVerbatimQuote || haveLineContinuationChar;
 2644     haveLineContinuationChar = false;
 2645     isImmediatelyPostEmptyLine = lineIsEmpty;
 2646     previousChar = ' ';
 2647 
 2648     if (currentLine.length() == 0)
 2649         currentLine = string(" ");        // a null is inserted if this is not done
 2650 
 2651     if (methodBreakLineNum > 0)
 2652         --methodBreakLineNum;
 2653     if (methodAttachLineNum > 0)
 2654         --methodAttachLineNum;
 2655 
 2656     // unless reading in the first line of the file, break a new line.
 2657     if (!isVirgin)
 2658         isInLineBreak = true;
 2659     else
 2660         isVirgin = false;
 2661 
 2662     if (isImmediatelyPostNonInStmt)
 2663     {
 2664         isCharImmediatelyPostNonInStmt = true;
 2665         isImmediatelyPostNonInStmt = false;
 2666     }
 2667 
 2668     // check if is in preprocessor before line trimming
 2669     // a blank line after a \ will remove the flag
 2670     isImmediatelyPostPreprocessor = isInPreprocessor;
 2671     if (!isInComment
 2672             && (previousNonWSChar != '\\'
 2673                 || isEmptyLine(currentLine)))
 2674         isInPreprocessor = false;
 2675 
 2676     if (passedSemicolon)
 2677         isInExecSQL = false;
 2678     initNewLine();
 2679 
 2680     currentChar = currentLine[charNum];
 2681     if (isInBraceRunIn && previousNonWSChar == '{' && !isInComment)
 2682         isInLineBreak = false;
 2683     isInBraceRunIn = false;
 2684 
 2685     if (currentChar == '\t' && shouldConvertTabs)
 2686         convertTabToSpaces();
 2687 
 2688     // check for an empty line inside a command brace.
 2689     // if yes then read the next line (calls getNextLine recursively).
 2690     // must be after initNewLine.
 2691     if (shouldDeleteEmptyLines
 2692             && lineIsEmpty
 2693             && isBraceType((*braceTypeStack)[braceTypeStack->size() - 1], COMMAND_TYPE))
 2694     {
 2695         if (!shouldBreakBlocks || previousNonWSChar == '{' || !commentAndHeaderFollows())
 2696         {
 2697             isInPreprocessor = isImmediatelyPostPreprocessor;       // restore
 2698             lineIsEmpty = false;
 2699             return getNextLine(true);
 2700         }
 2701     }
 2702     return true;
 2703 }
 2704 
 2705 /**
 2706  * jump over the leading white space in the current line,
 2707  * IF the line does not begin a comment or is in a preprocessor definition.
 2708  */
 2709 void ASFormatter::initNewLine()
 2710 {
 2711     size_t len = currentLine.length();
 2712     size_t tabSize = getTabLength();
 2713     charNum = 0;
 2714 
 2715     // don't trim these
 2716     if (isInQuoteContinuation
 2717             || (isInPreprocessor && !getPreprocDefineIndent()))
 2718         return;
 2719 
 2720     // SQL continuation lines must be adjusted so the leading spaces
 2721     // is equivalent to the opening EXEC SQL
 2722     if (isInExecSQL)
 2723     {
 2724         // replace leading tabs with spaces
 2725         // so that continuation indent will be spaces
 2726         size_t tabCount_ = 0;
 2727         size_t i;
 2728         for (i = 0; i < currentLine.length(); i++)
 2729         {
 2730             if (!isWhiteSpace(currentLine[i]))      // stop at first text
 2731                 break;
 2732             if (currentLine[i] == '\t')
 2733             {
 2734                 size_t numSpaces = tabSize - ((tabCount_ + i) % tabSize);
 2735                 currentLine.replace(i, 1, numSpaces, ' ');
 2736                 tabCount_++;
 2737                 i += tabSize - 1;
 2738             }
 2739         }
 2740         // this will correct the format if EXEC SQL is not a hanging indent
 2741         trimContinuationLine();
 2742         return;
 2743     }
 2744 
 2745     // comment continuation lines must be adjusted so the leading spaces
 2746     // is equivalent to the opening comment
 2747     if (isInComment)
 2748     {
 2749         if (noTrimCommentContinuation)
 2750             leadingSpaces = tabIncrementIn = 0;
 2751         trimContinuationLine();
 2752         return;
 2753     }
 2754 
 2755     // compute leading spaces
 2756     isImmediatelyPostCommentOnly = lineIsLineCommentOnly || lineEndsInCommentOnly;
 2757     lineIsCommentOnly = false;
 2758     lineIsLineCommentOnly = false;
 2759     lineEndsInCommentOnly = false;
 2760     doesLineStartComment = false;
 2761     currentLineBeginsWithBrace = false;
 2762     lineIsEmpty = false;
 2763     currentLineFirstBraceNum = string::npos;
 2764     tabIncrementIn = 0;
 2765 
 2766     // bypass whitespace at the start of a line
 2767     // preprocessor tabs are replaced later in the program
 2768     for (charNum = 0; isWhiteSpace(currentLine[charNum]) && charNum + 1 < (int) len; charNum++)
 2769     {
 2770         if (currentLine[charNum] == '\t' && !isInPreprocessor)
 2771             tabIncrementIn += tabSize - 1 - ((tabIncrementIn + charNum) % tabSize);
 2772     }
 2773     leadingSpaces = charNum + tabIncrementIn;
 2774 
 2775     if (isSequenceReached("/*"))
 2776     {
 2777         doesLineStartComment = true;
 2778         if ((int) currentLine.length() > charNum + 2
 2779                 && currentLine.find("*/", charNum + 2) != string::npos)
 2780             lineIsCommentOnly = true;
 2781     }
 2782     else if (isSequenceReached("//"))
 2783     {
 2784         lineIsLineCommentOnly = true;
 2785     }
 2786     else if (isSequenceReached("{"))
 2787     {
 2788         currentLineBeginsWithBrace = true;
 2789         currentLineFirstBraceNum = charNum;
 2790         size_t firstText = currentLine.find_first_not_of(" \t", charNum + 1);
 2791         if (firstText != string::npos)
 2792         {
 2793             if (currentLine.compare(firstText, 2, "//") == 0)
 2794                 lineIsLineCommentOnly = true;
 2795             else if (currentLine.compare(firstText, 2, "/*") == 0
 2796                      || isExecSQL(currentLine, firstText))
 2797             {
 2798                 // get the extra adjustment
 2799                 size_t j;
 2800                 for (j = charNum + 1; j < firstText && isWhiteSpace(currentLine[j]); j++)
 2801                 {
 2802                     if (currentLine[j] == '\t')
 2803                         tabIncrementIn += tabSize - 1 - ((tabIncrementIn + j) % tabSize);
 2804                 }
 2805                 leadingSpaces = j + tabIncrementIn;
 2806                 if (currentLine.compare(firstText, 2, "/*") == 0)
 2807                     doesLineStartComment = true;
 2808             }
 2809         }
 2810     }
 2811     else if (isWhiteSpace(currentLine[charNum]) && !(charNum + 1 < (int) currentLine.length()))
 2812     {
 2813         lineIsEmpty = true;
 2814     }
 2815 
 2816     // do not trim indented preprocessor define (except for comment continuation lines)
 2817     if (isInPreprocessor)
 2818     {
 2819         if (!doesLineStartComment)
 2820             leadingSpaces = 0;
 2821         charNum = 0;
 2822     }
 2823 }
 2824 
 2825 /**
 2826  * Append a character to the current formatted line.
 2827  * The formattedLine split points are updated.
 2828  *
 2829  * @param ch               the character to append.
 2830  * @param canBreakLine     if true, a registered line-break
 2831  */
 2832 void ASFormatter::appendChar(char ch, bool canBreakLine)
 2833 {
 2834     if (canBreakLine && isInLineBreak)
 2835         breakLine();
 2836 
 2837     formattedLine.append(1, ch);
 2838     isImmediatelyPostCommentOnly = false;
 2839     if (maxCodeLength != string::npos)
 2840     {
 2841         // These compares reduce the frequency of function calls.
 2842         if (isOkToSplitFormattedLine())
 2843             updateFormattedLineSplitPoints(ch);
 2844         if (formattedLine.length() > maxCodeLength)
 2845             testForTimeToSplitFormattedLine();
 2846     }
 2847 }
 2848 
 2849 /**
 2850  * Append a string sequence to the current formatted line.
 2851  * The formattedLine split points are NOT updated.
 2852  * But the formattedLine is checked for time to split.
 2853  *
 2854  * @param sequence         the sequence to append.
 2855  * @param canBreakLine     if true, a registered line-break
 2856  */
 2857 void ASFormatter::appendSequence(const string& sequence, bool canBreakLine)
 2858 {
 2859     if (canBreakLine && isInLineBreak)
 2860         breakLine();
 2861     formattedLine.append(sequence);
 2862     if (formattedLine.length() > maxCodeLength)
 2863         testForTimeToSplitFormattedLine();
 2864 }
 2865 
 2866 /**
 2867  * Append an operator sequence to the current formatted line.
 2868  * The formattedLine split points are updated.
 2869  *
 2870  * @param sequence         the sequence to append.
 2871  * @param canBreakLine     if true, a registered line-break
 2872  */
 2873 void ASFormatter::appendOperator(const string& sequence, bool canBreakLine)
 2874 {
 2875     if (canBreakLine && isInLineBreak)
 2876         breakLine();
 2877     formattedLine.append(sequence);
 2878     if (maxCodeLength != string::npos)
 2879     {
 2880         // These compares reduce the frequency of function calls.
 2881         if (isOkToSplitFormattedLine())
 2882             updateFormattedLineSplitPointsOperator(sequence);
 2883         if (formattedLine.length() > maxCodeLength)
 2884             testForTimeToSplitFormattedLine();
 2885     }
 2886 }
 2887 
 2888 /**
 2889  * append a space to the current formattedline, UNLESS the
 2890  * last character is already a white-space character.
 2891  */
 2892 void ASFormatter::appendSpacePad()
 2893 {
 2894     int len = formattedLine.length();
 2895     if (len > 0 && !isWhiteSpace(formattedLine[len - 1]))
 2896     {
 2897         formattedLine.append(1, ' ');
 2898         spacePadNum++;
 2899         if (maxCodeLength != string::npos)
 2900         {
 2901             // These compares reduce the frequency of function calls.
 2902             if (isOkToSplitFormattedLine())
 2903                 updateFormattedLineSplitPoints(' ');
 2904             if (formattedLine.length() > maxCodeLength)
 2905                 testForTimeToSplitFormattedLine();
 2906         }
 2907     }
 2908 }
 2909 
 2910 /**
 2911  * append a space to the current formattedline, UNLESS the
 2912  * next character is already a white-space character.
 2913  */
 2914 void ASFormatter::appendSpaceAfter()
 2915 {
 2916     int len = currentLine.length();
 2917     if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum + 1]))
 2918     {
 2919         formattedLine.append(1, ' ');
 2920         spacePadNum++;
 2921         if (maxCodeLength != string::npos)
 2922         {
 2923             // These compares reduce the frequency of function calls.
 2924             if (isOkToSplitFormattedLine())
 2925                 updateFormattedLineSplitPoints(' ');
 2926             if (formattedLine.length() > maxCodeLength)
 2927                 testForTimeToSplitFormattedLine();
 2928         }
 2929     }
 2930 }
 2931 
 2932 /**
 2933  * register a line break for the formatted line.
 2934  */
 2935 void ASFormatter::breakLine(bool isSplitLine /*false*/)
 2936 {
 2937     isLineReady = true;
 2938     isInLineBreak = false;
 2939     spacePadNum = nextLineSpacePadNum;
 2940     nextLineSpacePadNum = 0;
 2941     readyFormattedLine = formattedLine;
 2942     formattedLine.erase();
 2943     // queue an empty line prepend request if one exists
 2944     prependEmptyLine = isPrependPostBlockEmptyLineRequested;
 2945 
 2946     if (!isSplitLine)
 2947     {
 2948         formattedLineCommentNum = string::npos;
 2949         clearFormattedLineSplitPoints();
 2950 
 2951         if (isAppendPostBlockEmptyLineRequested)
 2952         {
 2953             isAppendPostBlockEmptyLineRequested = false;
 2954             isPrependPostBlockEmptyLineRequested = true;
 2955         }
 2956         else
 2957             isPrependPostBlockEmptyLineRequested = false;
 2958     }
 2959 }
 2960 
 2961 /**
 2962  * check if the currently reached open-brace (i.e. '{')
 2963  * opens a:
 2964  * - a definition type block (such as a class or namespace),
 2965  * - a command block (such as a method block)
 2966  * - a static array
 2967  * this method takes for granted that the current character
 2968  * is an opening brace.
 2969  *
 2970  * @return    the type of the opened block.
 2971  */
 2972 BraceType ASFormatter::getBraceType()
 2973 {
 2974     assert(currentChar == '{');
 2975 
 2976     BraceType returnVal = NULL_TYPE;
 2977 
 2978     if ((previousNonWSChar == '='
 2979             || isBraceType(braceTypeStack->back(), ARRAY_TYPE))
 2980             && previousCommandChar != ')'
 2981             && !isNonParenHeader)
 2982         returnVal = ARRAY_TYPE;
 2983     else if (foundPreDefinitionHeader && previousCommandChar != ')')
 2984     {
 2985         returnVal = DEFINITION_TYPE;
 2986         if (foundNamespaceHeader)
 2987             returnVal = (BraceType)(returnVal | NAMESPACE_TYPE);
 2988         else if (foundClassHeader)
 2989             returnVal = (BraceType)(returnVal | CLASS_TYPE);
 2990         else if (foundStructHeader)
 2991             returnVal = (BraceType)(returnVal | STRUCT_TYPE);
 2992         else if (foundInterfaceHeader)
 2993             returnVal = (BraceType)(returnVal | INTERFACE_TYPE);
 2994     }
 2995     else if (isInEnum)
 2996     {
 2997         returnVal = (BraceType)(ARRAY_TYPE | ENUM_TYPE);
 2998     }
 2999     else
 3000     {
 3001         bool isCommandType = (foundPreCommandHeader
 3002                               || foundPreCommandMacro
 3003                               || (currentHeader != nullptr && isNonParenHeader)
 3004                               || (previousCommandChar == ')')
 3005                               || (previousCommandChar == ':' && !foundQuestionMark)
 3006                               || (previousCommandChar == ';')
 3007                               || ((previousCommandChar == '{' || previousCommandChar == '}')
 3008                                   && isPreviousBraceBlockRelated)
 3009                               || (isInClassInitializer
 3010                                   && ((!isLegalNameChar(previousNonWSChar) && previousNonWSChar != '(')
 3011                                       || foundPreCommandHeader))
 3012                               || foundTrailingReturnType
 3013                               || isInObjCMethodDefinition
 3014                               || isInObjCInterface
 3015                               || isJavaStaticConstructor
 3016                               || isSharpDelegate);
 3017 
 3018         // C# methods containing 'get', 'set', 'add', and 'remove' do NOT end with parens
 3019         if (!isCommandType && isSharpStyle() && isNextWordSharpNonParenHeader(charNum + 1))
 3020         {
 3021             isCommandType = true;
 3022             isSharpAccessor = true;
 3023         }
 3024 
 3025         if (isInExternC)
 3026             returnVal = (isCommandType ? COMMAND_TYPE : EXTERN_TYPE);
 3027         else
 3028             returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
 3029     }
 3030 
 3031     int foundOneLineBlock = isOneLineBlockReached(currentLine, charNum);
 3032 
 3033     if (foundOneLineBlock == 2 && returnVal == COMMAND_TYPE)
 3034         returnVal = ARRAY_TYPE;
 3035 
 3036     if (foundOneLineBlock > 0)
 3037     {
 3038         returnVal = (BraceType) (returnVal | SINGLE_LINE_TYPE);
 3039         if (breakCurrentOneLineBlock)
 3040             returnVal = (BraceType) (returnVal | BREAK_BLOCK_TYPE);
 3041         if (foundOneLineBlock == 3)
 3042             returnVal = (BraceType)(returnVal | EMPTY_BLOCK_TYPE);
 3043     }
 3044 
 3045     if (isBraceType(returnVal, ARRAY_TYPE))
 3046     {
 3047         if (isNonInStatementArrayBrace())
 3048         {
 3049             returnVal = (BraceType)(returnVal | ARRAY_NIS_TYPE);
 3050             isNonInStatementArray = true;
 3051             isImmediatelyPostNonInStmt = false;     // in case of "},{"
 3052             nonInStatementBrace = formattedLine.length() - 1;
 3053         }
 3054         if (isUniformInitializerBrace())
 3055             returnVal = (BraceType)(returnVal | INIT_TYPE);
 3056     }
 3057 
 3058     return returnVal;
 3059 }
 3060 
 3061 bool ASFormatter::isNumericVariable(const string& word) const
 3062 {
 3063     if (word == "bool"
 3064             || word == "int"
 3065             || word == "void"
 3066             || word == "char"
 3067             || word == "long"
 3068             || word == "short"
 3069             || word == "double"
 3070             || word == "float"
 3071             || (word.length() >= 4     // check end of word for _t
 3072                 && word.compare(word.length() - 2, 2, "_t") == 0)
 3073 // removed release 3.1
 3074 //          || word == "Int32"
 3075 //          || word == "UInt32"
 3076 //          || word == "Int64"
 3077 //          || word == "UInt64"
 3078             || word == "BOOL"
 3079             || word == "DWORD"
 3080             || word == "HWND"
 3081             || word == "INT"
 3082             || word == "LPSTR"
 3083             || word == "VOID"
 3084             || word == "LPVOID"
 3085             || word == "wxFontEncoding"
 3086        )
 3087         return true;
 3088     return false;
 3089 }
 3090 
 3091 /**
 3092 * check if a colon is a class initializer separator
 3093 *
 3094 * @return        whether it is a class initializer separator
 3095 */
 3096 bool ASFormatter::isClassInitializer() const
 3097 {
 3098     assert(currentChar == ':');
 3099     assert(previousChar != ':' && peekNextChar() != ':');   // not part of '::'
 3100 
 3101     // this should be similar to ASBeautifier::parseCurrentLine()
 3102     bool foundClassInitializer = false;
 3103 
 3104     if (foundQuestionMark)
 3105     {
 3106         // do nothing special
 3107     }
 3108     else if (parenStack->back() > 0)
 3109     {
 3110         // found a 'for' loop or an objective-C statement
 3111         // so do nothing special
 3112     }
 3113     else if (isInEnum)
 3114     {
 3115         // found an enum with a base-type
 3116     }
 3117     else if (isCStyle()
 3118              && !isInCase
 3119              && (previousCommandChar == ')' || foundPreCommandHeader))
 3120     {
 3121         // found a 'class' c'tor initializer
 3122         foundClassInitializer = true;
 3123     }
 3124     return foundClassInitializer;
 3125 }
 3126 
 3127 /**
 3128  * check if a line is empty
 3129  *
 3130  * @return        whether line is empty
 3131  */
 3132 bool ASFormatter::isEmptyLine(const string& line) const
 3133 {
 3134     return line.find_first_not_of(" \t") == string::npos;
 3135 }
 3136 
 3137 /**
 3138  * Check if the following text is "C" as in extern "C".
 3139  *
 3140  * @return        whether the statement is extern "C"
 3141  */
 3142 bool ASFormatter::isExternC() const
 3143 {
 3144     // charNum should be at 'extern'
 3145     assert(!isWhiteSpace(currentLine[charNum]));
 3146     size_t startQuote = currentLine.find_first_of(" \t\"", charNum);
 3147     if (startQuote == string::npos)
 3148         return false;
 3149     startQuote = currentLine.find_first_not_of(" \t", startQuote);
 3150     if (startQuote == string::npos)
 3151         return false;
 3152     if (currentLine.compare(startQuote, 3, "\"C\"") != 0)
 3153         return false;
 3154     return true;
 3155 }
 3156 
 3157 /**
 3158  * Check if the currently reached '*', '&' or '^' character is
 3159  * a pointer-or-reference symbol, or another operator.
 3160  * A pointer dereference (*) or an "address of" character (&)
 3161  * counts as a pointer or reference because it is not an
 3162  * arithmetic operator.
 3163  *
 3164  * @return        whether current character is a reference-or-pointer
 3165  */
 3166 bool ASFormatter::isPointerOrReference() const
 3167 {
 3168     assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
 3169 
 3170     if (isJavaStyle())
 3171         return false;
 3172 
 3173     if (isCharImmediatelyPostOperator)
 3174         return false;
 3175 
 3176     // get the last legal word (may be a number)
 3177     string lastWord = getPreviousWord(currentLine, charNum);
 3178     if (lastWord.empty())
 3179         lastWord = " ";
 3180 
 3181     // check for preceding or following numeric values
 3182     string nextText = peekNextText(currentLine.substr(charNum + 1));
 3183     if (nextText.length() == 0)
 3184         nextText = " ";
 3185     if (isDigit(lastWord[0])
 3186             || isDigit(nextText[0])
 3187             || nextText[0] == '!'
 3188             || nextText[0] == '~')
 3189         return false;
 3190 
 3191     // check for multiply then a dereference (a * *b)
 3192     char nextChar = peekNextChar();
 3193     if (currentChar == '*'
 3194             && nextChar == '*'
 3195             && !isPointerToPointer(currentLine, charNum))
 3196         return false;
 3197 
 3198     if ((foundCastOperator && nextChar == '>')
 3199             || isPointerOrReferenceVariable(lastWord))
 3200         return true;
 3201 
 3202     if (isInClassInitializer
 3203             && previousNonWSChar != '('
 3204             && previousNonWSChar != '{'
 3205             && previousCommandChar != ','
 3206             && nextChar != ')'
 3207             && nextChar != '}')
 3208         return false;
 3209 
 3210     //check for rvalue reference
 3211     if (currentChar == '&' && nextChar == '&')
 3212     {
 3213         if (lastWord == AS_AUTO)
 3214             return true;
 3215         if (previousNonWSChar == '>')
 3216             return true;
 3217         string followingText;
 3218         if ((int) currentLine.length() > charNum + 2)
 3219             followingText = peekNextText(currentLine.substr(charNum + 2));
 3220         if (followingText.length() > 0 && followingText[0] == ')')
 3221             return true;
 3222         if (currentHeader != nullptr || isInPotentialCalculation)
 3223             return false;
 3224         if (parenStack->back() > 0 && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
 3225             return false;
 3226         return true;
 3227     }
 3228     if (nextChar == '*'
 3229             || previousNonWSChar == '='
 3230             || previousNonWSChar == '('
 3231             || previousNonWSChar == '['
 3232             || isCharImmediatelyPostReturn
 3233             || isInTemplate
 3234             || isCharImmediatelyPostTemplate
 3235             || currentHeader == &AS_CATCH
 3236             || currentHeader == &AS_FOREACH
 3237             || currentHeader == &AS_QFOREACH)
 3238         return true;
 3239 
 3240     if (isBraceType(braceTypeStack->back(), ARRAY_TYPE)
 3241             && isLegalNameChar(lastWord[0])
 3242             && isLegalNameChar(nextChar)
 3243             && previousNonWSChar != ')')
 3244     {
 3245         if (isArrayOperator())
 3246             return false;
 3247     }
 3248 
 3249     // checks on operators in parens
 3250     if (parenStack->back() > 0
 3251             && isLegalNameChar(lastWord[0])
 3252             && isLegalNameChar(nextChar))
 3253     {
 3254         // if followed by an assignment it is a pointer or reference
 3255         // if followed by semicolon it is a pointer or reference in range-based for
 3256         const string* followingOperator = getFollowingOperator();
 3257         if (followingOperator != nullptr
 3258                 && followingOperator != &AS_MULT
 3259                 && followingOperator != &AS_BIT_AND)
 3260         {
 3261             if (followingOperator == &AS_ASSIGN || followingOperator == &AS_COLON)
 3262                 return true;
 3263             return false;
 3264         }
 3265 
 3266         if (isBraceType(braceTypeStack->back(), COMMAND_TYPE)
 3267                 || squareBracketCount > 0)
 3268             return false;
 3269         return true;
 3270     }
 3271 
 3272     // checks on operators in parens with following '('
 3273     if (parenStack->back() > 0
 3274             && nextChar == '('
 3275             && previousNonWSChar != ','
 3276             && previousNonWSChar != '('
 3277             && previousNonWSChar != '!'
 3278             && previousNonWSChar != '&'
 3279             && previousNonWSChar != '*'
 3280             && previousNonWSChar != '|')
 3281         return false;
 3282 
 3283     if (nextChar == '-'
 3284             || nextChar == '+')
 3285     {
 3286         size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1);
 3287         if (nextNum != string::npos)
 3288         {
 3289             if (currentLine.compare(nextNum, 2, "++") != 0
 3290                     && currentLine.compare(nextNum, 2, "--") != 0)
 3291                 return false;
 3292         }
 3293     }
 3294 
 3295     bool isPR = (!isInPotentialCalculation
 3296                  || (!isLegalNameChar(previousNonWSChar)
 3297                      && !(previousNonWSChar == ')' && nextChar == '(')
 3298                      && !(previousNonWSChar == ')' && currentChar == '*' && !isImmediatelyPostCast())
 3299                      && previousNonWSChar != ']')
 3300                  || (!isWhiteSpace(nextChar)
 3301                      && nextChar != '-'
 3302                      && nextChar != '('
 3303                      && nextChar != '['
 3304                      && !isLegalNameChar(nextChar))
 3305                 );
 3306 
 3307     return isPR;
 3308 }
 3309 
 3310 /**
 3311  * Check if the currently reached  '*' or '&' character is
 3312  * a dereferenced pointer or "address of" symbol.
 3313  * NOTE: this MUST be a pointer or reference as determined by
 3314  * the function isPointerOrReference().
 3315  *
 3316  * @return        whether current character is a dereference or address of
 3317  */
 3318 bool ASFormatter::isDereferenceOrAddressOf() const
 3319 {
 3320     assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
 3321 
 3322     if (isCharImmediatelyPostTemplate)
 3323         return false;
 3324 
 3325     if (previousNonWSChar == '='
 3326             || previousNonWSChar == ','
 3327             || previousNonWSChar == '.'
 3328             || previousNonWSChar == '{'
 3329             || previousNonWSChar == '>'
 3330             || previousNonWSChar == '<'
 3331             || previousNonWSChar == '?'
 3332             || isCharImmediatelyPostLineComment
 3333             || isCharImmediatelyPostComment
 3334             || isCharImmediatelyPostReturn)
 3335         return true;
 3336 
 3337     char nextChar = peekNextChar();
 3338     if (currentChar == '*' && nextChar == '*')
 3339     {
 3340         if (previousNonWSChar == '(')
 3341             return true;
 3342         if ((int) currentLine.length() < charNum + 2)
 3343             return true;
 3344         return false;
 3345     }
 3346     if (currentChar == '&' && nextChar == '&')
 3347     {
 3348         if (previousNonWSChar == '(' || isInTemplate)
 3349             return true;
 3350         if ((int) currentLine.length() < charNum + 2)
 3351             return true;
 3352         return false;
 3353     }
 3354 
 3355     // check first char on the line
 3356     if (charNum == (int) currentLine.find_first_not_of(" \t")
 3357             && (isBraceType(braceTypeStack->back(), COMMAND_TYPE)
 3358                 || parenStack->back() != 0))
 3359         return true;
 3360 
 3361     string nextText = peekNextText(currentLine.substr(charNum + 1));
 3362     if (nextText.length() > 0)
 3363     {
 3364         if (nextText[0] == ')' || nextText[0] == '>'
 3365                 || nextText[0] == ',' || nextText[0] == '=')
 3366             return false;
 3367         if (nextText[0] == ';')
 3368             return true;
 3369     }
 3370 
 3371     // check for reference to a pointer *&
 3372     if ((currentChar == '*' && nextChar == '&')
 3373             || (previousNonWSChar == '*' && currentChar == '&'))
 3374         return false;
 3375 
 3376     if (!isBraceType(braceTypeStack->back(), COMMAND_TYPE)
 3377             && parenStack->back() == 0)
 3378         return false;
 3379 
 3380     string lastWord = getPreviousWord(currentLine, charNum);
 3381     if (lastWord == "else" || lastWord == "delete")
 3382         return true;
 3383 
 3384     if (isPointerOrReferenceVariable(lastWord))
 3385         return false;
 3386 
 3387     bool isDA = (!(isLegalNameChar(previousNonWSChar) || previousNonWSChar == '>')
 3388                  || (nextText.length() > 0 && !isLegalNameChar(nextText[0]) && nextText[0] != '/')
 3389                  || (ispunct((unsigned char)previousNonWSChar) && previousNonWSChar != '.')
 3390                  || isCharImmediatelyPostReturn);
 3391 
 3392     return isDA;
 3393 }
 3394 
 3395 /**
 3396  * Check if the currently reached  '*' or '&' character is
 3397  * centered with one space on each side.
 3398  * Only spaces are checked, not tabs.
 3399  * If true then a space will be deleted on the output.
 3400  *
 3401  * @return        whether current character is centered.
 3402  */
 3403 bool ASFormatter::isPointerOrReferenceCentered() const
 3404 {
 3405     assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
 3406 
 3407     int prNum = charNum;
 3408     int lineLength = (int) currentLine.length();
 3409 
 3410     // check for end of line
 3411     if (peekNextChar() == ' ')
 3412         return false;
 3413 
 3414     // check space before
 3415     if (prNum < 1
 3416             || currentLine[prNum - 1] != ' ')
 3417         return false;
 3418 
 3419     // check no space before that
 3420     if (prNum < 2
 3421             || currentLine[prNum - 2] == ' ')
 3422         return false;
 3423 
 3424     // check for ** or &&
 3425     if (prNum + 1 < lineLength
 3426             && (currentLine[prNum + 1] == '*' || currentLine[prNum + 1] == '&'))
 3427         prNum++;
 3428 
 3429     // check space after
 3430     if (prNum + 1 <= lineLength
 3431             && currentLine[prNum + 1] != ' ')
 3432         return false;
 3433 
 3434     // check no space after that
 3435     if (prNum + 2 < lineLength
 3436             && currentLine[prNum + 2] == ' ')
 3437         return false;
 3438 
 3439     return true;
 3440 }
 3441 
 3442 /**
 3443  * Check if a word is a pointer or reference variable type.
 3444  *
 3445  * @return        whether word is a pointer or reference variable.
 3446  */
 3447 bool ASFormatter::isPointerOrReferenceVariable(const string& word) const
 3448 {
 3449     return (word == "char"
 3450             || word == "string"
 3451             || word == "NSString"
 3452             || word == "int"
 3453             || word == "void"
 3454             || (word.length() >= 6     // check end of word for _t
 3455                 && word.compare(word.length() - 2, 2, "_t") == 0)
 3456             || word == "INT"
 3457             || word == "VOID");
 3458 }
 3459 
 3460 /**
 3461  * Check if * * is a pointer to a pointer or a multiply then a dereference.
 3462  *
 3463  * @return        true if a pointer *.
 3464  */
 3465 bool ASFormatter::isPointerToPointer(const string& line, int currPos) const
 3466 {
 3467     assert(line[currPos] == '*' && peekNextChar() == '*');
 3468     if ((int) line.length() > currPos + 1 && line[currPos + 1] == '*')
 3469         return true;
 3470     size_t nextText = line.find_first_not_of(" \t", currPos + 1);
 3471     if (nextText == string::npos || line[nextText] != '*')
 3472         return false;
 3473     size_t nextText2 = line.find_first_not_of(" \t", nextText + 1);
 3474     if (nextText2 == string::npos)
 3475         return false;
 3476     if (line[nextText2] == ')' || line[nextText2] == '*')
 3477         return true;
 3478     return false;
 3479 }
 3480 
 3481 /**
 3482  * check if the currently reached '+' or '-' character is a unary operator
 3483  * this method takes for granted that the current character
 3484  * is a '+' or '-'.
 3485  *
 3486  * @return        whether the current '+' or '-' is a unary operator.
 3487  */
 3488 bool ASFormatter::isUnaryOperator() const
 3489 {
 3490     assert(currentChar == '+' || currentChar == '-');
 3491 
 3492     // does a digit follow a c-style cast
 3493     if (previousCommandChar == ')')
 3494     {
 3495         if (!isdigit(peekNextChar()))
 3496             return false;
 3497         size_t end = currentLine.rfind(')', charNum);
 3498         if (end == string::npos)
 3499             return false;
 3500         size_t lastChar = currentLine.find_last_not_of(" \t", end - 1);
 3501         if (lastChar == string::npos)
 3502             return false;
 3503         if (currentLine[lastChar] == '*')
 3504             end = lastChar;
 3505         string prevWord = getPreviousWord(currentLine, end);
 3506         if (prevWord.empty())
 3507             return false;
 3508         if (!isNumericVariable(prevWord))
 3509             return false;
 3510         return true;
 3511     }
 3512 
 3513     return ((isCharImmediatelyPostReturn || !isLegalNameChar(previousCommandChar))
 3514             && previousCommandChar != '.'
 3515             && previousCommandChar != '\"'
 3516             && previousCommandChar != '\''
 3517             && previousCommandChar != ']');
 3518 }
 3519 
 3520 /**
 3521  * check if the currently reached comment is in a 'switch' statement
 3522  *
 3523  * @return        whether the current '+' or '-' is in an exponent.
 3524  */
 3525 bool ASFormatter::isInSwitchStatement() const
 3526 {
 3527     assert(isInLineComment || isInComment);
 3528     if (!preBraceHeaderStack->empty())
 3529         for (size_t i = 1; i < preBraceHeaderStack->size(); i++)
 3530             if (preBraceHeaderStack->at(i) == &AS_SWITCH)
 3531                 return true;
 3532     return false;
 3533 }
 3534 
 3535 /**
 3536  * check if the currently reached '+' or '-' character is
 3537  * part of an exponent, i.e. 0.2E-5.
 3538  *
 3539  * @return        whether the current '+' or '-' is in an exponent.
 3540  */
 3541 bool ASFormatter::isInExponent() const
 3542 {
 3543     assert(currentChar == '+' || currentChar == '-');
 3544 
 3545     if (charNum >= 2)
 3546     {
 3547         char prevPrevFormattedChar = currentLine[charNum - 2];
 3548         char prevFormattedChar = currentLine[charNum - 1];
 3549         return ((prevFormattedChar == 'e' || prevFormattedChar == 'E')
 3550                 && (prevPrevFormattedChar == '.' || isDigit(prevPrevFormattedChar)));
 3551     }
 3552     return false;
 3553 }
 3554 
 3555 /**
 3556  * check if an array brace should NOT have an in-statement indent
 3557  *
 3558  * @return        the array is non in-statement
 3559  */
 3560 bool ASFormatter::isNonInStatementArrayBrace() const
 3561 {
 3562     bool returnVal = false;
 3563     char nextChar = peekNextChar();
 3564     // if this opening brace begins the line there will be no inStatement indent
 3565     if (currentLineBeginsWithBrace
 3566             && (size_t) charNum == currentLineFirstBraceNum
 3567             && nextChar != '}')
 3568         returnVal = true;
 3569     // if an opening brace ends the line there will be no inStatement indent
 3570     if (isWhiteSpace(nextChar)
 3571             || isBeforeAnyLineEndComment(charNum)
 3572             || nextChar == '{')
 3573         returnVal = true;
 3574 
 3575     // Java "new Type [] {...}" IS an inStatement indent
 3576     if (isJavaStyle() && previousNonWSChar == ']')
 3577         returnVal = false;
 3578 
 3579     return returnVal;
 3580 }
 3581 
 3582 /**
 3583  * check if a one-line block has been reached,
 3584  * i.e. if the currently reached '{' character is closed
 3585  * with a complimentary '}' elsewhere on the current line,
 3586  *.
 3587  * @return     0 = one-line block has not been reached.
 3588  *             1 = one-line block has been reached.
 3589  *             2 = one-line block has been reached and is followed by a comma.
 3590  *             3 = one-line block has been reached and is an empty block.
 3591  */
 3592 int ASFormatter::isOneLineBlockReached(const string& line, int startChar) const
 3593 {
 3594     assert(line[startChar] == '{');
 3595 
 3596     bool isInComment_ = false;
 3597     bool isInQuote_ = false;
 3598     bool hasText = false;
 3599     int braceCount = 0;
 3600     int lineLength = line.length();
 3601     char quoteChar_ = ' ';
 3602     char ch = ' ';
 3603     char prevCh = ' ';
 3604 
 3605     for (int i = startChar; i < lineLength; ++i)
 3606     {
 3607         ch = line[i];
 3608 
 3609         if (isInComment_)
 3610         {
 3611             if (line.compare(i, 2, "*/") == 0)
 3612             {
 3613                 isInComment_ = false;
 3614                 ++i;
 3615             }
 3616             continue;
 3617         }
 3618 
 3619         if (isInQuote_)
 3620         {
 3621             if (ch == '\\')
 3622                 ++i;
 3623             else if (ch == quoteChar_)
 3624                 isInQuote_ = false;
 3625             continue;
 3626         }
 3627 
 3628         if (ch == '"'
 3629                 || (ch == '\'' && !isDigitSeparator(line, i)))
 3630         {
 3631             isInQuote_ = true;
 3632             quoteChar_ = ch;
 3633             continue;
 3634         }
 3635 
 3636         if (line.compare(i, 2, "//") == 0)
 3637             break;
 3638 
 3639         if (line.compare(i, 2, "/*") == 0)
 3640         {
 3641             isInComment_ = true;
 3642             ++i;
 3643             continue;
 3644         }
 3645 
 3646         if (ch == '{')
 3647         {
 3648             ++braceCount;
 3649             continue;
 3650         }
 3651         if (ch == '}')
 3652         {
 3653             --braceCount;
 3654             if (braceCount == 0)
 3655             {
 3656                 // is this an array?
 3657                 if (parenStack->back() == 0 && prevCh != '}')
 3658                 {
 3659                     size_t peekNum = line.find_first_not_of(" \t", i + 1);
 3660                     if (peekNum != string::npos && line[peekNum] == ',')
 3661                         return 2;
 3662                 }
 3663                 if (!hasText)
 3664                     return 3;   // is an empty block
 3665                 return 1;
 3666             }
 3667         }
 3668         if (ch == ';')
 3669             continue;
 3670         if (!isWhiteSpace(ch))
 3671         {
 3672             hasText = true;
 3673             prevCh = ch;
 3674         }
 3675     }
 3676 
 3677     return 0;
 3678 }
 3679 
 3680 /**
 3681  * peek at the next word to determine if it is a C# non-paren header.
 3682  * will look ahead in the input file if necessary.
 3683  *
 3684  * @param  startChar      position on currentLine to start the search
 3685  * @return                true if the next word is get or set.
 3686  */
 3687 bool ASFormatter::isNextWordSharpNonParenHeader(int startChar) const
 3688 {
 3689     // look ahead to find the next non-comment text
 3690     string nextText = peekNextText(currentLine.substr(startChar));
 3691     if (nextText.length() == 0)
 3692         return false;
 3693     if (nextText[0] == '[')
 3694         return true;
 3695     if (!isCharPotentialHeader(nextText, 0))
 3696         return false;
 3697     if (findKeyword(nextText, 0, AS_GET) || findKeyword(nextText, 0, AS_SET)
 3698             || findKeyword(nextText, 0, AS_ADD) || findKeyword(nextText, 0, AS_REMOVE))
 3699         return true;
 3700     return false;
 3701 }
 3702 
 3703 /**
 3704  * peek at the next char to determine if it is an opening brace.
 3705  * will look ahead in the input file if necessary.
 3706  * this determines a java static constructor.
 3707  *
 3708  * @param startChar     position on currentLine to start the search
 3709  * @return              true if the next word is an opening brace.
 3710  */
 3711 bool ASFormatter::isNextCharOpeningBrace(int startChar) const
 3712 {
 3713     bool retVal = false;
 3714     string nextText = peekNextText(currentLine.substr(startChar));
 3715     if (nextText.length() > 0
 3716             && nextText.compare(0, 1, "{") == 0)
 3717         retVal = true;
 3718     return retVal;
 3719 }
 3720 
 3721 /**
 3722 * Check if operator and, pointer, and reference padding is disabled.
 3723 * Disabling is done thru a NOPAD tag in an ending comment.
 3724 *
 3725 * @return              true if the formatting on this line is disabled.
 3726 */
 3727 bool ASFormatter::isOperatorPaddingDisabled() const
 3728 {
 3729     size_t commentStart = currentLine.find("//", charNum);
 3730     if (commentStart == string::npos)
 3731     {
 3732         commentStart = currentLine.find("/*", charNum);
 3733         // comment must end on this line
 3734         if (commentStart != string::npos)
 3735         {
 3736             size_t commentEnd = currentLine.find("*/", commentStart + 2);
 3737             if (commentEnd == string::npos)
 3738                 commentStart = string::npos;
 3739         }
 3740     }
 3741     if (commentStart == string::npos)
 3742         return false;
 3743     size_t noPadStart = currentLine.find("*NOPAD*", commentStart);
 3744     if (noPadStart == string::npos)
 3745         return false;
 3746     return true;
 3747 }
 3748 
 3749 /**
 3750 * Determine if an opening array-type brace should have a leading space pad.
 3751 * This is to identify C++11 uniform initializers.
 3752 */
 3753 bool ASFormatter::isUniformInitializerBrace() const
 3754 {
 3755     if (isCStyle() && !isInEnum && !isImmediatelyPostPreprocessor)
 3756     {
 3757         if (isInClassInitializer
 3758                 || isLegalNameChar(previousNonWSChar)
 3759                 || previousNonWSChar == '(')
 3760             return true;
 3761     }
 3762     return false;
 3763 }
 3764 
 3765 /**
 3766 * Determine if there is a following statement on the current line.
 3767 */
 3768 bool ASFormatter::isMultiStatementLine() const
 3769 {
 3770     assert((isImmediatelyPostHeader || foundClosingHeader));
 3771     bool isInComment_ = false;
 3772     bool isInQuote_ = false;
 3773     int  semiCount_ = 0;
 3774     int  parenCount_ = 0;
 3775     int  braceCount_ = 0;
 3776 
 3777     for (size_t i = 0; i < currentLine.length(); i++)
 3778     {
 3779         if (isInComment_)
 3780         {
 3781             if (currentLine.compare(i, 2, "*/") == 0)
 3782             {
 3783                 isInComment_ = false;
 3784                 continue;
 3785             }
 3786         }
 3787         if (currentLine.compare(i, 2, "/*") == 0)
 3788         {
 3789             isInComment_ = true;
 3790             continue;
 3791         }
 3792         if (currentLine.compare(i, 2, "//") == 0)
 3793             return false;
 3794         if (isInQuote_)
 3795         {
 3796             if (currentLine[i] == '"' || currentLine[i] == '\'')
 3797                 isInQuote_ = false;
 3798             continue;
 3799         }
 3800         if (currentLine[i] == '"' || currentLine[i] == '\'')
 3801         {
 3802             isInQuote_ = true;
 3803             continue;
 3804         }
 3805         if (currentLine[i] == '(')
 3806         {
 3807             ++parenCount_;
 3808             continue;
 3809         }
 3810         if (currentLine[i] == ')')
 3811         {
 3812             --parenCount_;
 3813             continue;
 3814         }
 3815         if (parenCount_ > 0)
 3816             continue;
 3817         if (currentLine[i] == '{')
 3818         {
 3819             ++braceCount_;
 3820         }
 3821         if (currentLine[i] == '}')
 3822         {
 3823             --braceCount_;
 3824         }
 3825         if (braceCount_ > 0)
 3826             continue;
 3827         if (currentLine[i] == ';')
 3828         {
 3829             ++semiCount_;
 3830             if (semiCount_ > 1)
 3831                 return true;
 3832             continue;
 3833         }
 3834     }
 3835     return false;
 3836 }
 3837 
 3838 /**
 3839  * get the next non-whitespace substring on following lines, bypassing all comments.
 3840  *
 3841  * @param   firstLine   the first line to check
 3842  * @return  the next non-whitespace substring.
 3843  */
 3844 string ASFormatter::peekNextText(const string& firstLine,
 3845                                  bool endOnEmptyLine /*false*/,
 3846                                  const shared_ptr<ASPeekStream>& streamArg /*nullptr*/) const
 3847 {
 3848     assert(sourceIterator->getPeekStart() == 0 || streamArg != nullptr);    // Borland may need != 0
 3849     bool isFirstLine = true;
 3850     string nextLine_ = firstLine;
 3851     size_t firstChar = string::npos;
 3852     shared_ptr<ASPeekStream> stream = streamArg;
 3853     if (stream == nullptr)                  // Borland may need == 0
 3854         stream = make_shared<ASPeekStream>(sourceIterator);
 3855 
 3856     // find the first non-blank text, bypassing all comments.
 3857     bool isInComment_ = false;
 3858     while (stream->hasMoreLines() || isFirstLine)
 3859     {
 3860         if (isFirstLine)
 3861             isFirstLine = false;
 3862         else
 3863             nextLine_ = stream->peekNextLine();
 3864 
 3865         firstChar = nextLine_.find_first_not_of(" \t");
 3866         if (firstChar == string::npos)
 3867         {
 3868             if (endOnEmptyLine && !isInComment_)
 3869                 break;
 3870             continue;
 3871         }
 3872 
 3873         if (nextLine_.compare(firstChar, 2, "/*") == 0)
 3874         {
 3875             firstChar += 2;
 3876             isInComment_ = true;
 3877         }
 3878 
 3879         if (isInComment_)
 3880         {
 3881             firstChar = nextLine_.find("*/", firstChar);
 3882             if (firstChar == string::npos)
 3883                 continue;
 3884             firstChar += 2;
 3885             isInComment_ = false;
 3886             firstChar = nextLine_.find_first_not_of(" \t", firstChar);
 3887             if (firstChar == string::npos)
 3888                 continue;
 3889         }
 3890 
 3891         if (nextLine_.compare(firstChar, 2, "//") == 0)
 3892             continue;
 3893 
 3894         // found the next text
 3895         break;
 3896     }
 3897 
 3898     if (firstChar == string::npos)
 3899         nextLine_ = "";
 3900     else
 3901         nextLine_ = nextLine_.substr(firstChar);
 3902     return nextLine_;
 3903 }
 3904 
 3905 /**
 3906  * adjust comment position because of adding or deleting spaces
 3907  * the spaces are added or deleted to formattedLine
 3908  * spacePadNum contains the adjustment
 3909  */
 3910 void ASFormatter::adjustComments()
 3911 {
 3912     assert(spacePadNum != 0);
 3913     assert(isSequenceReached("//") || isSequenceReached("/*"));
 3914 
 3915     // block comment must be closed on this line with nothing after it
 3916     if (isSequenceReached("/*"))
 3917     {
 3918         size_t endNum = currentLine.find("*/", charNum + 2);
 3919         if (endNum == string::npos)
 3920             return;
 3921         // following line comments may be a tag from AStyleWx //[[)>
 3922         size_t nextNum = currentLine.find_first_not_of(" \t", endNum + 2);
 3923         if (nextNum != string::npos
 3924                 && currentLine.compare(nextNum, 2, "//") != 0)
 3925             return;
 3926     }
 3927 
 3928     size_t len = formattedLine.length();
 3929     // don't adjust a tab
 3930     if (formattedLine[len - 1] == '\t')
 3931         return;
 3932     // if spaces were removed, need to add spaces before the comment
 3933     if (spacePadNum < 0)
 3934     {
 3935         int adjust = -spacePadNum;          // make the number positive
 3936         formattedLine.append(adjust, ' ');
 3937     }
 3938     // if spaces were added, need to delete extra spaces before the comment
 3939     // if cannot be done put the comment one space after the last text
 3940     else if (spacePadNum > 0)
 3941     {
 3942         int adjust = spacePadNum;
 3943         size_t lastText = formattedLine.find_last_not_of(' ');
 3944         if (lastText != string::npos
 3945                 && lastText < len - adjust - 1)
 3946             formattedLine.resize(len - adjust);
 3947         else if (len > lastText + 2)
 3948             formattedLine.resize(lastText + 2);
 3949         else if (len < lastText + 2)
 3950             formattedLine.append(len - lastText, ' ');
 3951     }
 3952 }
 3953 
 3954 /**
 3955  * append the current brace inside the end of line comments
 3956  * currentChar contains the brace, it will be appended to formattedLine
 3957  * formattedLineCommentNum is the comment location on formattedLine
 3958  */
 3959 void ASFormatter::appendCharInsideComments()
 3960 {
 3961     if (formattedLineCommentNum == string::npos     // does the comment start on the previous line?
 3962             || formattedLineCommentNum == 0)
 3963     {
 3964         appendCurrentChar();                        // don't attach
 3965         return;
 3966     }
 3967     assert(formattedLine.compare(formattedLineCommentNum, 2, "//") == 0
 3968            || formattedLine.compare(formattedLineCommentNum, 2, "/*") == 0);
 3969 
 3970     // find the previous non space char
 3971     size_t end = formattedLineCommentNum;
 3972     size_t beg = formattedLine.find_last_not_of(" \t", end - 1);
 3973     if (beg == string::npos)
 3974     {
 3975         appendCurrentChar();                // don't attach
 3976         return;
 3977     }
 3978     beg++;
 3979 
 3980     // insert the brace
 3981     if (end - beg < 3)                      // is there room to insert?
 3982         formattedLine.insert(beg, 3 - end + beg, ' ');
 3983     if (formattedLine[beg] == '\t')         // don't pad with a tab
 3984         formattedLine.insert(beg, 1, ' ');
 3985     formattedLine[beg + 1] = currentChar;
 3986     testForTimeToSplitFormattedLine();
 3987 
 3988     if (isBeforeComment())
 3989         breakLine();
 3990     else if (isCharImmediatelyPostLineComment)
 3991         shouldBreakLineAtNextChar = true;
 3992 }
 3993 
 3994 /**
 3995  * add or remove space padding to operators
 3996  * the operators and necessary padding will be appended to formattedLine
 3997  * the calling function should have a continue statement after calling this method
 3998  *
 3999  * @param newOperator     the operator to be padded
 4000  */
 4001 void ASFormatter::padOperators(const string* newOperator)
 4002 {
 4003     assert(shouldPadOperators);
 4004     assert(newOperator != nullptr);
 4005 
 4006     char nextNonWSChar = ASBase::peekNextChar(currentLine, charNum);
 4007     bool shouldPad = (newOperator != &AS_SCOPE_RESOLUTION
 4008                       && newOperator != &AS_PLUS_PLUS
 4009                       && newOperator != &AS_MINUS_MINUS
 4010                       && newOperator != &AS_NOT
 4011                       && newOperator != &AS_BIT_NOT
 4012                       && newOperator != &AS_ARROW
 4013                       && !(newOperator == &AS_COLON && !foundQuestionMark           // objC methods
 4014                            && (isInObjCMethodDefinition || isInObjCInterface
 4015                                || isInObjCSelector || squareBracketCount != 0))
 4016                       && !(newOperator == &AS_MINUS && isInExponent())
 4017                       && !(newOperator == &AS_PLUS && isInExponent())
 4018                       && !((newOperator == &AS_PLUS || newOperator == &AS_MINUS)    // check for unary plus or minus
 4019                            && (previousNonWSChar == '('
 4020                                || previousNonWSChar == '['
 4021                                || previousNonWSChar == '='
 4022                                || previousNonWSChar == ','
 4023                                || previousNonWSChar == ':'
 4024                                || previousNonWSChar == '{'))
 4025 //?                   // commented out in release 2.05.1 - doesn't seem to do anything???
 4026 //x                   && !((newOperator == &AS_MULT || newOperator == &AS_BIT_AND || newOperator == &AS_AND)
 4027 //x                        && isPointerOrReference())
 4028                       && !(newOperator == &AS_MULT
 4029                            && (previousNonWSChar == '.'
 4030                                || previousNonWSChar == '>'))    // check for ->
 4031                       && !(newOperator == &AS_MULT && peekNextChar() == '>')
 4032                       && !((isInTemplate || isImmediatelyPostTemplate)
 4033                            && (newOperator == &AS_LS || newOperator == &AS_GR))
 4034                       && !(newOperator == &AS_GCC_MIN_ASSIGN
 4035                            && ASBase::peekNextChar(currentLine, charNum + 1) == '>')
 4036                       && !(newOperator == &AS_GR && previousNonWSChar == '?')
 4037                       && !(newOperator == &AS_QUESTION          // check for Java wildcard
 4038                            && isJavaStyle()
 4039                            && (previousNonWSChar == '<'
 4040                                || nextNonWSChar == '>'
 4041                                || nextNonWSChar == '.'))
 4042                       && !(newOperator == &AS_QUESTION          // check for C# null conditional operator
 4043                            && isSharpStyle()
 4044                            && (nextNonWSChar == '.'
 4045                                || nextNonWSChar == '['))
 4046                       && !isCharImmediatelyPostOperator
 4047                       && !isInCase
 4048                       && !isInAsm
 4049                       && !isInAsmOneLine
 4050                       && !isInAsmBlock
 4051                      );
 4052 
 4053     // pad before operator
 4054     if (shouldPad
 4055             && !(newOperator == &AS_COLON
 4056                  && (!foundQuestionMark && !isInEnum) && currentHeader != &AS_FOR)
 4057             && !(newOperator == &AS_QUESTION && isSharpStyle() // check for C# nullable type (e.g. int?)
 4058                  && currentLine.find(':', charNum + 1) == string::npos)
 4059        )
 4060         appendSpacePad();
 4061     appendOperator(*newOperator);
 4062     goForward(newOperator->length() - 1);
 4063 
 4064     currentChar = (*newOperator)[newOperator->length() - 1];
 4065     // pad after operator
 4066     // but do not pad after a '-' that is a unary-minus.
 4067     if (shouldPad
 4068             && !isBeforeAnyComment()
 4069             && !(newOperator == &AS_PLUS && isUnaryOperator())
 4070             && !(newOperator == &AS_MINUS && isUnaryOperator())
 4071             && !(currentLine.compare(charNum + 1, 1, AS_SEMICOLON) == 0)
 4072             && !(currentLine.compare(charNum + 1, 2, AS_SCOPE_RESOLUTION) == 0)
 4073             && !(peekNextChar() == ',')
 4074             && !(newOperator == &AS_QUESTION && isSharpStyle() // check for C# nullable type (e.g. int?)
 4075                  && peekNextChar() == '[')
 4076        )
 4077         appendSpaceAfter();
 4078 }
 4079 
 4080 /**
 4081  * format pointer or reference
 4082  * currentChar contains the pointer or reference
 4083  * the symbol and necessary padding will be appended to formattedLine
 4084  * the calling function should have a continue statement after calling this method
 4085  *
 4086  * NOTE: Do NOT use appendCurrentChar() in this method. The line should not be
 4087  *       broken once the calculation starts.
 4088  */
 4089 void ASFormatter::formatPointerOrReference()
 4090 {
 4091     assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
 4092     assert(!isJavaStyle());
 4093 
 4094     int pa = pointerAlignment;
 4095     int ra = referenceAlignment;
 4096     int itemAlignment = (currentChar == '*' || currentChar == '^')
 4097                         ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra);
 4098 
 4099     // check for ** and &&
 4100     int ptrLength = 1;
 4101     char peekedChar = peekNextChar();
 4102     if ((currentChar == '*' && peekedChar == '*')
 4103             || (currentChar == '&' && peekedChar == '&'))
 4104     {
 4105         ptrLength = 2;
 4106         size_t nextChar = currentLine.find_first_not_of(" \t", charNum + 2);
 4107         if (nextChar == string::npos)
 4108             peekedChar = ' ';
 4109         else
 4110             peekedChar = currentLine[nextChar];
 4111     }
 4112     // check for cast
 4113     if (peekedChar == ')' || peekedChar == '>' || peekedChar == ',')
 4114     {
 4115         formatPointerOrReferenceCast();
 4116         return;
 4117     }
 4118 
 4119     // check for a padded space and remove it
 4120     if (charNum > 0
 4121             && !isWhiteSpace(currentLine[charNum - 1])
 4122             && formattedLine.length() > 0
 4123             && isWhiteSpace(formattedLine[formattedLine.length() - 1]))
 4124     {
 4125         formattedLine.erase(formattedLine.length() - 1);
 4126         spacePadNum--;
 4127     }
 4128 
 4129     if (itemAlignment == PTR_ALIGN_TYPE)
 4130     {
 4131         formatPointerOrReferenceToType();
 4132     }
 4133     else if (itemAlignment == PTR_ALIGN_MIDDLE)
 4134     {
 4135         formatPointerOrReferenceToMiddle();
 4136     }
 4137     else if (itemAlignment == PTR_ALIGN_NAME)
 4138     {
 4139         formatPointerOrReferenceToName();
 4140     }
 4141     else    // pointerAlignment == PTR_ALIGN_NONE
 4142     {
 4143         formattedLine.append(currentLine.substr(charNum, ptrLength));
 4144         if (ptrLength > 1)
 4145             goForward(ptrLength - 1);
 4146     }
 4147 }
 4148 
 4149 /**
 4150  * format pointer or reference with align to type
 4151  */
 4152 void ASFormatter::formatPointerOrReferenceToType()
 4153 {
 4154     assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
 4155     assert(!isJavaStyle());
 4156 
 4157     // do this before bumping charNum
 4158     bool isOldPRCentered = isPointerOrReferenceCentered();
 4159     string sequenceToInsert(1, currentChar);
 4160     // get the sequence
 4161     if (currentChar == peekNextChar())
 4162     {
 4163         for (size_t i = charNum + 1; currentLine.length() > i; i++)
 4164         {
 4165             if (currentLine[i] == sequenceToInsert[0])
 4166             {
 4167                 sequenceToInsert.append(1, currentLine[i]);
 4168                 goForward(1);
 4169                 continue;
 4170             }
 4171             break;
 4172         }
 4173     }
 4174     // append the sequence
 4175     string charSave;
 4176     size_t prevCh = formattedLine.find_last_not_of(" \t");
 4177     if (prevCh < formattedLine.length())
 4178     {
 4179         charSave = formattedLine.substr(prevCh + 1);
 4180         formattedLine.resize(prevCh + 1);
 4181     }
 4182     formattedLine.append(sequenceToInsert);
 4183     if (peekNextChar() != ')')
 4184         formattedLine.append(charSave);
 4185     else
 4186         spacePadNum -= charSave.length();
 4187     // if no space after then add one
 4188     if (charNum < (int) currentLine.length() - 1
 4189             && !isWhiteSpace(currentLine[charNum + 1])
 4190             && currentLine[charNum + 1] != ')')
 4191         appendSpacePad();
 4192     // if old pointer or reference is centered, remove a space
 4193     if (isOldPRCentered
 4194             && isWhiteSpace(formattedLine[formattedLine.length() - 1]))
 4195     {
 4196         formattedLine.erase(formattedLine.length() - 1, 1);
 4197         spacePadNum--;
 4198     }
 4199     // update the formattedLine split point
 4200     if (maxCodeLength != string::npos && formattedLine.length() > 0)
 4201     {
 4202         size_t index = formattedLine.length() - 1;
 4203         if (isWhiteSpace(formattedLine[index]))
 4204         {
 4205             updateFormattedLineSplitPointsPointerOrReference(index);
 4206             testForTimeToSplitFormattedLine();
 4207         }
 4208     }
 4209 }
 4210 
 4211 /**
 4212  * format pointer or reference with align in the middle
 4213  */
 4214 void ASFormatter::formatPointerOrReferenceToMiddle()
 4215 {
 4216     assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
 4217     assert(!isJavaStyle());
 4218 
 4219     // compute current whitespace before
 4220     size_t wsBefore = currentLine.find_last_not_of(" \t", charNum - 1);
 4221     if (wsBefore == string::npos)
 4222         wsBefore = 0;
 4223     else
 4224         wsBefore = charNum - wsBefore - 1;
 4225     string sequenceToInsert(1, currentChar);
 4226     if (currentChar == peekNextChar())
 4227     {
 4228         for (size_t i = charNum + 1; currentLine.length() > i; i++)
 4229         {
 4230             if (currentLine[i] == sequenceToInsert[0])
 4231             {
 4232                 sequenceToInsert.append(1, currentLine[i]);
 4233                 goForward(1);
 4234                 continue;
 4235             }
 4236             break;
 4237         }
 4238     }
 4239     // if reference to a pointer check for conflicting alignment
 4240     else if (currentChar == '*' && peekNextChar() == '&'
 4241              && (referenceAlignment == REF_ALIGN_TYPE
 4242                  || referenceAlignment == REF_ALIGN_MIDDLE
 4243                  || referenceAlignment == REF_SAME_AS_PTR))
 4244     {
 4245         sequenceToInsert = "*&";
 4246         goForward(1);
 4247         for (size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace(currentLine[i]); i++)
 4248             goForward(1);
 4249     }
 4250     // if a comment follows don't align, just space pad
 4251     if (isBeforeAnyComment())
 4252     {
 4253         appendSpacePad();
 4254         formattedLine.append(sequenceToInsert);
 4255         appendSpaceAfter();
 4256         return;
 4257     }
 4258     // do this before goForward()
 4259     bool isAfterScopeResolution = previousNonWSChar == ':';
 4260     size_t charNumSave = charNum;
 4261     // if this is the last thing on the line
 4262     if (currentLine.find_first_not_of(" \t", charNum + 1) == string::npos)
 4263     {
 4264         if (wsBefore == 0 && !isAfterScopeResolution)
 4265             formattedLine.append(1, ' ');
 4266         formattedLine.append(sequenceToInsert);
 4267         return;
 4268     }
 4269     // goForward() to convert tabs to spaces, if necessary,
 4270     // and move following characters to preceding characters
 4271     // this may not work every time with tab characters
 4272     for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
 4273     {
 4274         goForward(1);
 4275         if (formattedLine.length() > 0)
 4276             formattedLine.append(1, currentLine[i]);
 4277         else
 4278             spacePadNum--;
 4279     }
 4280     // find space padding after
 4281     size_t wsAfter = currentLine.find_first_not_of(" \t", charNumSave + 1);
 4282     if (wsAfter == string::npos || isBeforeAnyComment())
 4283         wsAfter = 0;
 4284     else
 4285         wsAfter = wsAfter - charNumSave - 1;
 4286     // don't pad before scope resolution operator, but pad after
 4287     if (isAfterScopeResolution)
 4288     {
 4289         size_t lastText = formattedLine.find_last_not_of(" \t");
 4290         formattedLine.insert(lastText + 1, sequenceToInsert);
 4291         appendSpacePad();
 4292     }
 4293     else if (formattedLine.length() > 0)
 4294     {
 4295         // whitespace should be at least 2 chars to center
 4296         if (wsBefore + wsAfter < 2)
 4297         {
 4298             size_t charsToAppend = (2 - (wsBefore + wsAfter));
 4299             formattedLine.append(charsToAppend, ' ');
 4300             spacePadNum += charsToAppend;
 4301             if (wsBefore == 0)
 4302                 wsBefore++;
 4303             if (wsAfter == 0)
 4304                 wsAfter++;
 4305         }
 4306         // insert the pointer or reference char
 4307         size_t padAfter = (wsBefore + wsAfter) / 2;
 4308         size_t index = formattedLine.length() - padAfter;
 4309         if (index < formattedLine.length())
 4310             formattedLine.insert(index, sequenceToInsert);
 4311         else
 4312             formattedLine.append(sequenceToInsert);
 4313     }
 4314     else    // formattedLine.length() == 0
 4315     {
 4316         formattedLine.append(sequenceToInsert);
 4317         if (wsAfter == 0)
 4318             wsAfter++;
 4319         formattedLine.append(wsAfter, ' ');
 4320         spacePadNum += wsAfter;
 4321     }
 4322     // update the formattedLine split point after the pointer
 4323     if (maxCodeLength != string::npos && formattedLine.length() > 0)
 4324     {
 4325         size_t index = formattedLine.find_last_not_of(" \t");
 4326         if (index != string::npos && (index < formattedLine.length() - 1))
 4327         {
 4328             index++;
 4329             updateFormattedLineSplitPointsPointerOrReference(index);
 4330             testForTimeToSplitFormattedLine();
 4331         }
 4332     }
 4333 }
 4334 
 4335 /**
 4336  * format pointer or reference with align to name
 4337  */
 4338 void ASFormatter::formatPointerOrReferenceToName()
 4339 {
 4340     assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
 4341     assert(!isJavaStyle());
 4342 
 4343     // do this before bumping charNum
 4344     bool isOldPRCentered = isPointerOrReferenceCentered();
 4345 
 4346     size_t startNum = formattedLine.find_last_not_of(" \t");
 4347     if (startNum == string::npos)
 4348         startNum = 0;
 4349     string sequenceToInsert(1, currentChar);
 4350     if (currentChar == peekNextChar())
 4351     {
 4352         for (size_t i = charNum + 1; currentLine.length() > i; i++)
 4353         {
 4354             if (currentLine[i] == sequenceToInsert[0])
 4355             {
 4356                 sequenceToInsert.append(1, currentLine[i]);
 4357                 goForward(1);
 4358                 continue;
 4359             }
 4360             break;
 4361         }
 4362     }
 4363     // if reference to a pointer align both to name
 4364     else if (currentChar == '*' && peekNextChar() == '&')
 4365     {
 4366         sequenceToInsert = "*&";
 4367         goForward(1);
 4368         for (size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace(currentLine[i]); i++)
 4369             goForward(1);
 4370     }
 4371     char peekedChar = peekNextChar();
 4372     bool isAfterScopeResolution = previousNonWSChar == ':';     // check for ::
 4373     // if this is not the last thing on the line
 4374     if ((isLegalNameChar(peekedChar) || peekedChar == '(' || peekedChar == '[' || peekedChar == '=')
 4375             && (int) currentLine.find_first_not_of(" \t", charNum + 1) > charNum)
 4376     {
 4377         // goForward() to convert tabs to spaces, if necessary,
 4378         // and move following characters to preceding characters
 4379         // this may not work every time with tab characters
 4380         for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
 4381         {
 4382             // if a padded paren follows don't move
 4383             if (shouldPadParensOutside && peekedChar == '(' && !isOldPRCentered)
 4384             {
 4385                 // empty parens don't count
 4386                 size_t start = currentLine.find_first_not_of("( \t", i);
 4387                 if (start != string::npos && currentLine[start] != ')')
 4388                     break;
 4389             }
 4390             goForward(1);
 4391             if (formattedLine.length() > 0)
 4392                 formattedLine.append(1, currentLine[charNum]);
 4393             else
 4394                 spacePadNum--;
 4395         }
 4396     }
 4397     // don't pad before scope resolution operator
 4398     if (isAfterScopeResolution)
 4399     {
 4400         size_t lastText = formattedLine.find_last_not_of(" \t");
 4401         if (lastText != string::npos && lastText + 1 < formattedLine.length())
 4402             formattedLine.erase(lastText + 1);
 4403     }
 4404     // if no space before * then add one
 4405     else if (formattedLine.length() > 0
 4406              && (formattedLine.length() <= startNum + 1
 4407                  || !isWhiteSpace(formattedLine[startNum + 1])))
 4408     {
 4409         formattedLine.insert(startNum + 1, 1, ' ');
 4410         spacePadNum++;
 4411     }
 4412     appendSequence(sequenceToInsert, false);
 4413     // if old pointer or reference is centered, remove a space
 4414     if (isOldPRCentered
 4415             && formattedLine.length() > startNum + 1
 4416             && isWhiteSpace(formattedLine[startNum + 1])
 4417             && peekedChar != '*'        // check for '* *'
 4418             && !isBeforeAnyComment())
 4419     {
 4420         formattedLine.erase(startNum + 1, 1);
 4421         spacePadNum--;
 4422     }
 4423     // don't convert to *= or &=
 4424     if (peekedChar == '=')
 4425     {
 4426         appendSpaceAfter();
 4427         // if more than one space before, delete one
 4428         if (formattedLine.length() > startNum
 4429                 && isWhiteSpace(formattedLine[startNum + 1])
 4430                 && isWhiteSpace(formattedLine[startNum + 2]))
 4431         {
 4432             formattedLine.erase(startNum + 1, 1);
 4433             spacePadNum--;
 4434         }
 4435     }
 4436     // update the formattedLine split point
 4437     if (maxCodeLength != string::npos)
 4438     {
 4439         size_t index = formattedLine.find_last_of(" \t");
 4440         if (index != string::npos
 4441                 && index < formattedLine.length() - 1
 4442                 && (formattedLine[index + 1] == '*'
 4443                     || formattedLine[index + 1] == '&'
 4444                     || formattedLine[index + 1] == '^'))
 4445         {
 4446             updateFormattedLineSplitPointsPointerOrReference(index);
 4447             testForTimeToSplitFormattedLine();
 4448         }
 4449     }
 4450 }
 4451 
 4452 /**
 4453  * format pointer or reference cast
 4454  * currentChar contains the pointer or reference
 4455  * NOTE: the pointers and references in function definitions
 4456  *       are processed as a cast (e.g. void foo(void*, void*))
 4457  *       is processed here.
 4458  */
 4459 void ASFormatter::formatPointerOrReferenceCast()
 4460 {
 4461     assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
 4462     assert(!isJavaStyle());
 4463 
 4464     int pa = pointerAlignment;
 4465     int ra = referenceAlignment;
 4466     int itemAlignment = (currentChar == '*' || currentChar == '^')
 4467                         ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra);
 4468 
 4469     string sequenceToInsert(1, currentChar);
 4470     if (isSequenceReached("**") || isSequenceReached("&&"))
 4471     {
 4472         goForward(1);
 4473         sequenceToInsert.append(1, currentLine[charNum]);
 4474     }
 4475     if (itemAlignment == PTR_ALIGN_NONE)
 4476     {
 4477         appendSequence(sequenceToInsert, false);
 4478         return;
 4479     }
 4480     // remove preceding whitespace
 4481     char prevCh = ' ';
 4482     size_t prevNum = formattedLine.find_last_not_of(" \t");
 4483     if (prevNum != string::npos)
 4484     {
 4485         prevCh = formattedLine[prevNum];
 4486         if (itemAlignment == PTR_ALIGN_TYPE && currentChar == '*' && prevCh == '*')
 4487         {
 4488             // '* *' may be a multiply followed by a dereference
 4489             if (prevNum + 2 < formattedLine.length()
 4490                     && isWhiteSpace(formattedLine[prevNum + 2]))
 4491             {
 4492                 spacePadNum -= (formattedLine.length() - 2 - prevNum);
 4493                 formattedLine.erase(prevNum + 2);
 4494             }
 4495         }
 4496         else if (prevNum + 1 < formattedLine.length()
 4497                  && isWhiteSpace(formattedLine[prevNum + 1])
 4498                  && prevCh != '(')
 4499         {
 4500             spacePadNum -= (formattedLine.length() - 1 - prevNum);
 4501             formattedLine.erase(prevNum + 1);
 4502         }
 4503     }
 4504     bool isAfterScopeResolution = previousNonWSChar == ':';
 4505     if ((itemAlignment == PTR_ALIGN_MIDDLE || itemAlignment == PTR_ALIGN_NAME)
 4506             && !isAfterScopeResolution && prevCh != '(')
 4507     {
 4508         appendSpacePad();
 4509         // in this case appendSpacePad may or may not update the split point
 4510         if (maxCodeLength != string::npos && formattedLine.length() > 0)
 4511             updateFormattedLineSplitPointsPointerOrReference(formattedLine.length() - 1);
 4512         appendSequence(sequenceToInsert, false);
 4513     }
 4514     else
 4515         appendSequence(sequenceToInsert, false);
 4516 }
 4517 
 4518 /**
 4519  * add or remove space padding to parens
 4520  * currentChar contains the paren
 4521  * the parens and necessary padding will be appended to formattedLine
 4522  * the calling function should have a continue statement after calling this method
 4523  */
 4524 void ASFormatter::padParens()
 4525 {
 4526     assert(currentChar == '(' || currentChar == ')');
 4527     assert(shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen);
 4528 
 4529     int spacesOutsideToDelete = 0;
 4530     int spacesInsideToDelete = 0;
 4531 
 4532     if (currentChar == '(')
 4533     {
 4534         spacesOutsideToDelete = formattedLine.length() - 1;
 4535         spacesInsideToDelete = 0;
 4536 
 4537         // compute spaces outside the opening paren to delete
 4538         if (shouldUnPadParens)
 4539         {
 4540             char lastChar = ' ';
 4541             bool prevIsParenHeader = false;
 4542             size_t i = formattedLine.find_last_not_of(" \t");
 4543             if (i != string::npos)
 4544             {
 4545                 // if last char is a brace the previous whitespace is an indent
 4546                 if (formattedLine[i] == '{')
 4547                     spacesOutsideToDelete = 0;
 4548                 else if (isCharImmediatelyPostPointerOrReference)
 4549                     spacesOutsideToDelete = 0;
 4550                 else
 4551                 {
 4552                     spacesOutsideToDelete -= i;
 4553                     lastChar = formattedLine[i];
 4554                     // if previous word is a header, it will be a paren header
 4555                     string prevWord = getPreviousWord(formattedLine, formattedLine.length());
 4556                     const string* prevWordH = nullptr;
 4557                     if (shouldPadHeader
 4558                             && prevWord.length() > 0
 4559                             && isCharPotentialHeader(prevWord, 0))
 4560                         prevWordH = ASBase::findHeader(prevWord, 0, headers);
 4561                     if (prevWordH != nullptr)
 4562                         prevIsParenHeader = true;    // don't unpad
 4563                     else if (prevWord == AS_RETURN)
 4564                         prevIsParenHeader = true;    // don't unpad
 4565                     else if ((prevWord == AS_NEW || prevWord == AS_DELETE)
 4566                              && shouldPadHeader)
 4567                         prevIsParenHeader = true;    // don't unpad
 4568                     else if (isCStyle() && prevWord == AS_THROW && shouldPadHeader)
 4569                         prevIsParenHeader = true;    // don't unpad
 4570                     else if (prevWord == "and" || prevWord == "or" || prevWord == "in")
 4571                         prevIsParenHeader = true;    // don't unpad
 4572                     // don't unpad variables
 4573                     else if (isNumericVariable(prevWord))
 4574                         prevIsParenHeader = true;    // don't unpad
 4575                 }
 4576             }
 4577             // do not unpad operators, but leave them if already padded
 4578             if (shouldPadParensOutside || prevIsParenHeader)
 4579                 spacesOutsideToDelete--;
 4580             else if (lastChar == '|'          // check for ||
 4581                      || lastChar == '&'       // check for &&
 4582                      || lastChar == ','
 4583                      || (lastChar == '(' && shouldPadParensInside)
 4584                      || (lastChar == '>' && !foundCastOperator)
 4585                      || lastChar == '<'
 4586                      || lastChar == '?'
 4587                      || lastChar == ':'
 4588                      || lastChar == ';'
 4589                      || lastChar == '='
 4590                      || lastChar == '+'
 4591                      || lastChar == '-'
 4592                      || lastChar == '*'
 4593                      || lastChar == '/'
 4594                      || lastChar == '%'
 4595                      || lastChar == '^'
 4596                     )
 4597                 spacesOutsideToDelete--;
 4598 
 4599             if (spacesOutsideToDelete > 0)
 4600             {
 4601                 formattedLine.erase(i + 1, spacesOutsideToDelete);
 4602                 spacePadNum -= spacesOutsideToDelete;
 4603             }
 4604         }
 4605 
 4606         // pad open paren outside
 4607         char peekedCharOutside = peekNextChar();
 4608         if (shouldPadFirstParen && previousChar != '(' && peekedCharOutside != ')')
 4609             appendSpacePad();
 4610         else if (shouldPadParensOutside)
 4611         {
 4612             if (!(currentChar == '(' && peekedCharOutside == ')'))
 4613                 appendSpacePad();
 4614         }
 4615 
 4616         appendCurrentChar();
 4617 
 4618         // unpad open paren inside
 4619         if (shouldUnPadParens)
 4620         {
 4621             size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
 4622             if (j != string::npos)
 4623                 spacesInsideToDelete = j - charNum - 1;
 4624             if (shouldPadParensInside)
 4625                 spacesInsideToDelete--;
 4626             if (spacesInsideToDelete > 0)
 4627             {
 4628                 currentLine.erase(charNum + 1, spacesInsideToDelete);
 4629                 spacePadNum -= spacesInsideToDelete;
 4630             }
 4631             // convert tab to space if requested
 4632             if (shouldConvertTabs
 4633                     && (int) currentLine.length() > charNum + 1
 4634                     && currentLine[charNum + 1] == '\t')
 4635                 currentLine[charNum + 1] = ' ';
 4636         }
 4637 
 4638         // pad open paren inside
 4639         char peekedCharInside = peekNextChar();
 4640         if (shouldPadParensInside)
 4641             if (!(currentChar == '(' && peekedCharInside == ')'))
 4642                 appendSpaceAfter();
 4643     }
 4644     else if (currentChar == ')')
 4645     {
 4646         // unpad close paren inside
 4647         if (shouldUnPadParens)
 4648         {
 4649             spacesInsideToDelete = formattedLine.length();
 4650             size_t i = formattedLine.find_last_not_of(" \t");
 4651             if (i != string::npos)
 4652                 spacesInsideToDelete = formattedLine.length() - 1 - i;
 4653             if (shouldPadParensInside)
 4654                 spacesInsideToDelete--;
 4655             if (spacesInsideToDelete > 0)
 4656             {
 4657                 formattedLine.erase(i + 1, spacesInsideToDelete);
 4658                 spacePadNum -= spacesInsideToDelete;
 4659             }
 4660         }
 4661 
 4662         // pad close paren inside
 4663         if (shouldPadParensInside)
 4664             if (!(previousChar == '(' && currentChar == ')'))
 4665                 appendSpacePad();
 4666 
 4667         appendCurrentChar();
 4668 
 4669         // unpad close paren outside
 4670         // close parens outside are left unchanged
 4671         if (shouldUnPadParens)
 4672         {
 4673             //spacesOutsideToDelete = 0;
 4674             //size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
 4675             //if (j != string::npos)
 4676             //  spacesOutsideToDelete = j - charNum - 1;
 4677             //if (shouldPadParensOutside)
 4678             //  spacesOutsideToDelete--;
 4679 
 4680             //if (spacesOutsideToDelete > 0)
 4681             //{
 4682             //  currentLine.erase(charNum + 1, spacesOutsideToDelete);
 4683             //  spacePadNum -= spacesOutsideToDelete;
 4684             //}
 4685         }
 4686 
 4687         // pad close paren outside
 4688         char peekedCharOutside = peekNextChar();
 4689         if (shouldPadParensOutside)
 4690             if (peekedCharOutside != ';'
 4691                     && peekedCharOutside != ','
 4692                     && peekedCharOutside != '.'
 4693                     && peekedCharOutside != '+'    // check for ++
 4694                     && peekedCharOutside != '-'    // check for --
 4695                     && peekedCharOutside != ']')
 4696                 appendSpaceAfter();
 4697     }
 4698 }
 4699 
 4700 /**
 4701 * add or remove space padding to objective-c method prefix (- or +)
 4702 * if this is a '(' it begins a return type
 4703 * these options have precedence over the padParens methods
 4704 * the padParens method has already been called, this method adjusts
 4705 */
 4706 void ASFormatter::padObjCMethodPrefix()
 4707 {
 4708     assert(isInObjCMethodDefinition && isImmediatelyPostObjCMethodPrefix);
 4709     assert(shouldPadMethodPrefix || shouldUnPadMethodPrefix);
 4710 
 4711     size_t prefix = formattedLine.find_first_of("+-");
 4712     if (prefix == string::npos)
 4713         return;
 4714     size_t firstChar = formattedLine.find_first_not_of(" \t", prefix + 1);
 4715     if (firstChar == string::npos)
 4716         firstChar = formattedLine.length();
 4717     int spaces = firstChar - prefix - 1;
 4718 
 4719     if (shouldPadMethodPrefix)
 4720     {
 4721         if (spaces == 0)
 4722         {
 4723             formattedLine.insert(prefix + 1, 1, ' ');
 4724             spacePadNum += 1;
 4725         }
 4726         else if (spaces > 1)
 4727         {
 4728             formattedLine.erase(prefix + 1, spaces - 1);
 4729             formattedLine[prefix + 1] = ' ';  // convert any tab to space
 4730             spacePadNum -= spaces - 1;
 4731         }
 4732     }
 4733     // this option will be ignored if used with pad-method-prefix
 4734     else if (shouldUnPadMethodPrefix)
 4735     {
 4736         if (spaces > 0)
 4737         {
 4738             formattedLine.erase(prefix + 1, spaces);
 4739             spacePadNum -= spaces;
 4740         }
 4741     }
 4742 }
 4743 
 4744 /**
 4745 * add or remove space padding to objective-c parens
 4746 * these options have precedence over the padParens methods
 4747 * the padParens method has already been called, this method adjusts
 4748 */
 4749 void ASFormatter::padObjCReturnType()
 4750 {
 4751     assert(currentChar == ')' && isInObjCReturnType);
 4752     assert(shouldPadReturnType || shouldUnPadReturnType);
 4753 
 4754     size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
 4755     if (nextText == string::npos)
 4756         return;
 4757     int spaces = nextText - charNum - 1;
 4758 
 4759     if (shouldPadReturnType)
 4760     {
 4761         if (spaces == 0)
 4762         {
 4763             // this will already be padded if pad-paren is used
 4764             if (formattedLine[formattedLine.length() - 1] != ' ')
 4765             {
 4766                 formattedLine.append(" ");
 4767                 spacePadNum += 1;
 4768             }
 4769         }
 4770         else if (spaces > 1)
 4771         {
 4772             // do not use goForward here
 4773             currentLine.erase(charNum + 1, spaces - 1);
 4774             currentLine[charNum + 1] = ' ';  // convert any tab to space
 4775             spacePadNum -= spaces - 1;
 4776         }
 4777     }
 4778     // this option will be ignored if used with pad-return-type
 4779     else if (shouldUnPadReturnType)
 4780     {
 4781         // this will already be padded if pad-paren is used
 4782         if (formattedLine[formattedLine.length() - 1] == ' ')
 4783         {
 4784             int lastText = formattedLine.find_last_not_of(" \t");
 4785             spacePadNum -= formattedLine.length() - lastText - 1;
 4786             formattedLine.resize(lastText + 1);
 4787         }
 4788         // do not use goForward here
 4789         currentLine.erase(charNum + 1, spaces);
 4790         spacePadNum -= spaces;
 4791     }
 4792 }
 4793 
 4794 /**
 4795 * add or remove space padding to objective-c parens
 4796 * these options have precedence over the padParens methods
 4797 * the padParens method has already been called, this method adjusts
 4798 */
 4799 void ASFormatter::padObjCParamType()
 4800 {
 4801     assert((currentChar == '(' || currentChar == ')') && isInObjCMethodDefinition);
 4802     assert(!isImmediatelyPostObjCMethodPrefix && !isInObjCReturnType);
 4803     assert(shouldPadParamType || shouldUnPadParamType);
 4804 
 4805     if (currentChar == '(')
 4806     {
 4807         // open paren has already been attached to formattedLine by padParen
 4808         size_t paramOpen = formattedLine.rfind('(');
 4809         assert(paramOpen != string::npos);
 4810         size_t prevText = formattedLine.find_last_not_of(" \t", paramOpen - 1);
 4811         if (prevText == string::npos)
 4812             return;
 4813         int spaces = paramOpen - prevText - 1;
 4814 
 4815         if (shouldPadParamType
 4816                 || objCColonPadMode == COLON_PAD_ALL
 4817                 || objCColonPadMode == COLON_PAD_AFTER)
 4818         {
 4819             if (spaces == 0)
 4820             {
 4821                 formattedLine.insert(paramOpen, 1, ' ');
 4822                 spacePadNum += 1;
 4823             }
 4824             if (spaces > 1)
 4825             {
 4826                 formattedLine.erase(prevText + 1, spaces - 1);
 4827                 formattedLine[prevText + 1] = ' ';  // convert any tab to space
 4828                 spacePadNum -= spaces - 1;
 4829             }
 4830         }
 4831         // this option will be ignored if used with pad-param-type
 4832         else if (shouldUnPadParamType
 4833                  || objCColonPadMode == COLON_PAD_NONE
 4834                  || objCColonPadMode == COLON_PAD_BEFORE)
 4835         {
 4836             if (spaces > 0)
 4837             {
 4838                 formattedLine.erase(prevText + 1, spaces);
 4839                 spacePadNum -= spaces;
 4840             }
 4841         }
 4842     }
 4843     else if (currentChar == ')')
 4844     {
 4845         size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
 4846         if (nextText == string::npos)
 4847             return;
 4848         int spaces = nextText - charNum - 1;
 4849 
 4850         if (shouldPadParamType)
 4851         {
 4852             if (spaces == 0)
 4853             {
 4854                 // this will already be padded if pad-paren is used
 4855                 if (formattedLine[formattedLine.length() - 1] != ' ')
 4856                 {
 4857                     formattedLine.append(" ");
 4858                     spacePadNum += 1;
 4859                 }
 4860             }
 4861             else if (spaces > 1)
 4862             {
 4863                 // do not use goForward here
 4864                 currentLine.erase(charNum + 1, spaces - 1);
 4865                 currentLine[charNum + 1] = ' ';  // convert any tab to space
 4866                 spacePadNum -= spaces - 1;
 4867             }
 4868         }
 4869         // this option will be ignored if used with pad-param-type
 4870         else if (shouldUnPadParamType)
 4871         {
 4872             // this will already be padded if pad-paren is used
 4873             if (formattedLine[formattedLine.length() - 1] == ' ')
 4874             {
 4875                 spacePadNum -= 1;
 4876                 int lastText = formattedLine.find_last_not_of(" \t");
 4877                 formattedLine.resize(lastText + 1);
 4878             }
 4879             if (spaces > 0)
 4880             {
 4881                 // do not use goForward here
 4882                 currentLine.erase(charNum + 1, spaces);
 4883                 spacePadNum -= spaces;
 4884             }
 4885         }
 4886     }
 4887 }
 4888 
 4889 /**
 4890  * format opening brace as attached or broken
 4891  * currentChar contains the brace
 4892  * the braces will be appended to the current formattedLine or a new formattedLine as necessary
 4893  * the calling function should have a continue statement after calling this method
 4894  *
 4895  * @param braceType    the type of brace to be formatted.
 4896  */
 4897 void ASFormatter::formatOpeningBrace(BraceType braceType)
 4898 {
 4899     assert(!isBraceType(braceType, ARRAY_TYPE));
 4900     assert(currentChar == '{');
 4901 
 4902     parenStack->emplace_back(0);
 4903 
 4904     bool breakBrace = isCurrentBraceBroken();
 4905 
 4906     if (breakBrace)
 4907     {
 4908         if (isBeforeAnyComment() && isOkToBreakBlock(braceType) && sourceIterator->hasMoreLines())
 4909         {
 4910             // if comment is at line end leave the comment on this line
 4911             if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
 4912             {
 4913                 currentChar = ' ';              // remove brace from current line
 4914                 if (parenStack->size() > 1)
 4915                     parenStack->pop_back();
 4916                 currentLine[charNum] = currentChar;
 4917                 appendOpeningBrace = true;      // append brace to following line
 4918             }
 4919             // else put comment after the brace
 4920             else if (!isBeforeMultipleLineEndComments(charNum))
 4921                 breakLine();
 4922         }
 4923         else if (!isBraceType(braceType, SINGLE_LINE_TYPE))
 4924         {
 4925             formattedLine = rtrim(formattedLine);
 4926             breakLine();
 4927         }
 4928         else if ((shouldBreakOneLineBlocks || isBraceType(braceType, BREAK_BLOCK_TYPE))
 4929                  && !isBraceType(braceType, EMPTY_BLOCK_TYPE))
 4930             breakLine();
 4931         else if (!isInLineBreak)
 4932             appendSpacePad();
 4933 
 4934         appendCurrentChar();
 4935 
 4936         // should a following comment break from the brace?
 4937         // must break the line AFTER the brace
 4938         if (isBeforeComment()
 4939                 && formattedLine.length() > 0
 4940                 && formattedLine[0] == '{'
 4941                 && isOkToBreakBlock(braceType)
 4942                 && (braceFormatMode == BREAK_MODE
 4943                     || braceFormatMode == LINUX_MODE))
 4944         {
 4945             shouldBreakLineAtNextChar = true;
 4946         }
 4947     }
 4948     else    // attach brace
 4949     {
 4950         // are there comments before the brace?
 4951         if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
 4952         {
 4953             if (isOkToBreakBlock(braceType)
 4954                     && !(isCharImmediatelyPostComment && isCharImmediatelyPostLineComment)  // don't attach if two comments on the line
 4955                     && !isImmediatelyPostPreprocessor
 4956 //                  && peekNextChar() != '}'        // don't attach { }     // removed release 2.03
 4957                     && previousCommandChar != '{'   // don't attach { {
 4958                     && previousCommandChar != '}'   // don't attach } {
 4959                     && previousCommandChar != ';')  // don't attach ; {
 4960             {
 4961                 appendCharInsideComments();
 4962             }
 4963             else
 4964             {
 4965                 appendCurrentChar();                // don't attach
 4966             }
 4967         }
 4968         else if (previousCommandChar == '{'
 4969                  || (previousCommandChar == '}' && !isInClassInitializer)
 4970                  || previousCommandChar == ';')     // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
 4971         {
 4972             appendCurrentChar();                    // don't attach
 4973         }
 4974         else
 4975         {
 4976             // if a blank line precedes this don't attach
 4977             if (isEmptyLine(formattedLine))
 4978                 appendCurrentChar();                // don't attach
 4979             else if (isOkToBreakBlock(braceType)
 4980                      && !(isImmediatelyPostPreprocessor
 4981                           && currentLineBeginsWithBrace))
 4982             {
 4983                 if (!isBraceType(braceType, EMPTY_BLOCK_TYPE))
 4984                 {
 4985                     appendSpacePad();
 4986                     appendCurrentChar(false);               // OK to attach
 4987                     testForTimeToSplitFormattedLine();      // line length will have changed
 4988                     // should a following comment attach with the brace?
 4989                     // insert spaces to reposition the comment
 4990                     if (isBeforeComment()
 4991                             && !isBeforeMultipleLineEndComments(charNum)
 4992                             && (!isBeforeAnyLineEndComment(charNum) || currentLineBeginsWithBrace))
 4993                     {
 4994                         shouldBreakLineAtNextChar = true;
 4995                         currentLine.insert(charNum + 1, charNum + 1, ' ');
 4996                     }
 4997                     else if (!isBeforeAnyComment())     // added in release 2.03
 4998                     {
 4999                         shouldBreakLineAtNextChar = true;
 5000                     }
 5001                 }
 5002                 else
 5003                 {
 5004                     if (currentLineBeginsWithBrace && (size_t) charNum == currentLineFirstBraceNum)
 5005                     {
 5006                         appendSpacePad();
 5007                         appendCurrentChar(false);       // attach
 5008                         shouldBreakLineAtNextChar = true;
 5009                     }
 5010                     else
 5011                     {
 5012                         appendSpacePad();
 5013                         appendCurrentChar();        // don't attach
 5014                     }
 5015                 }
 5016             }
 5017             else
 5018             {
 5019                 if (!isInLineBreak)
 5020                     appendSpacePad();
 5021                 appendCurrentChar();                // don't attach
 5022             }
 5023         }
 5024     }
 5025 }
 5026 
 5027 /**
 5028  * format closing brace
 5029  * currentChar contains the brace
 5030  * the calling function should have a continue statement after calling this method
 5031  *
 5032  * @param braceType    the type of the opening brace for this closing brace.
 5033  */
 5034 void ASFormatter::formatClosingBrace(BraceType braceType)
 5035 {
 5036     assert(!isBraceType(braceType, ARRAY_TYPE));
 5037     assert(currentChar == '}');
 5038 
 5039     // parenStack must contain one entry
 5040     if (parenStack->size() > 1)
 5041         parenStack->pop_back();
 5042 
 5043     // mark state of immediately after empty block
 5044     // this state will be used for locating braces that appear immediately AFTER an empty block (e.g. '{} \n}').
 5045     if (previousCommandChar == '{')
 5046         isImmediatelyPostEmptyBlock = true;
 5047 
 5048     if (attachClosingBraceMode)
 5049     {
 5050         // for now, namespaces and classes will be attached. Uncomment the lines below to break.
 5051         if ((isEmptyLine(formattedLine)         // if a blank line precedes this
 5052                 || isCharImmediatelyPostLineComment
 5053                 || isCharImmediatelyPostComment
 5054                 || (isImmediatelyPostPreprocessor && (int) currentLine.find_first_not_of(" \t") == charNum)
 5055 //              || (isBraceType(braceType, CLASS_TYPE) && isOkToBreakBlock(braceType) && previousNonWSChar != '{')
 5056 //              || (isBraceType(braceType, NAMESPACE_TYPE) && isOkToBreakBlock(braceType) && previousNonWSChar != '{')
 5057             )
 5058                 && (!isBraceType(braceType, SINGLE_LINE_TYPE) || isOkToBreakBlock(braceType)))
 5059         {
 5060             breakLine();
 5061             appendCurrentChar();                // don't attach
 5062         }
 5063         else
 5064         {
 5065             if (previousNonWSChar != '{'
 5066                     && (!isBraceType(braceType, SINGLE_LINE_TYPE)
 5067                         || isOkToBreakBlock(braceType)))
 5068                 appendSpacePad();
 5069             appendCurrentChar(false);           // attach
 5070         }
 5071     }
 5072     else if (!isBraceType(braceType, EMPTY_BLOCK_TYPE)
 5073              && (isBraceType(braceType, BREAK_BLOCK_TYPE)
 5074                  || isOkToBreakBlock(braceType)))
 5075     {
 5076         breakLine();
 5077         appendCurrentChar();
 5078     }
 5079     else
 5080     {
 5081         appendCurrentChar();
 5082     }
 5083 
 5084     // if a declaration follows a definition, space pad
 5085     if (isLegalNameChar(peekNextChar()))
 5086         appendSpaceAfter();
 5087 
 5088     if (shouldBreakBlocks
 5089             && currentHeader != nullptr
 5090             && !isHeaderInMultiStatementLine
 5091             && parenStack->back() == 0)
 5092     {
 5093         if (currentHeader == &AS_CASE || currentHeader == &AS_DEFAULT)
 5094         {
 5095             // do not yet insert a line if "break" statement is outside the braces
 5096             string nextText = peekNextText(currentLine.substr(charNum + 1));
 5097             if (nextText.length() > 0
 5098                     && nextText.substr(0, 5) != "break")
 5099                 isAppendPostBlockEmptyLineRequested = true;
 5100         }
 5101         else
 5102             isAppendPostBlockEmptyLineRequested = true;
 5103     }
 5104 }
 5105 
 5106 /**
 5107  * format array braces as attached or broken
 5108  * determine if the braces can have an inStatement indent
 5109  * currentChar contains the brace
 5110  * the braces will be appended to the current formattedLine or a new formattedLine as necessary
 5111  * the calling function should have a continue statement after calling this method
 5112  *
 5113  * @param braceType            the type of brace to be formatted, must be an ARRAY_TYPE.
 5114  * @param isOpeningArrayBrace  indicates if this is the opening brace for the array block.
 5115  */
 5116 void ASFormatter::formatArrayBraces(BraceType braceType, bool isOpeningArrayBrace)
 5117 {
 5118     assert(isBraceType(braceType, ARRAY_TYPE));
 5119     assert(currentChar == '{' || currentChar == '}');
 5120 
 5121     if (currentChar == '{')
 5122     {
 5123         // is this the first opening brace in the array?
 5124         if (isOpeningArrayBrace)
 5125         {
 5126             if (braceFormatMode == ATTACH_MODE
 5127                     || braceFormatMode == LINUX_MODE)
 5128             {
 5129                 // break an enum if mozilla
 5130                 if (isBraceType(braceType, ENUM_TYPE)
 5131                         && formattingStyle == STYLE_MOZILLA)
 5132                 {
 5133                     isInLineBreak = true;
 5134                     appendCurrentChar();                // don't attach
 5135                 }
 5136                 // don't attach to a preprocessor directive or '\' line
 5137                 else if ((isImmediatelyPostPreprocessor
 5138                           || (formattedLine.length() > 0
 5139                               && formattedLine[formattedLine.length() - 1] == '\\'))
 5140                          && currentLineBeginsWithBrace)
 5141                 {
 5142                     isInLineBreak = true;
 5143                     appendCurrentChar();                // don't attach
 5144                 }
 5145                 else if (isCharImmediatelyPostComment)
 5146                 {
 5147                     // TODO: attach brace to line-end comment
 5148                     appendCurrentChar();                // don't attach
 5149                 }
 5150                 else if (isCharImmediatelyPostLineComment && !isBraceType(braceType, SINGLE_LINE_TYPE))
 5151                 {
 5152                     appendCharInsideComments();
 5153                 }
 5154                 else
 5155                 {
 5156                     // if a blank line precedes this don't attach
 5157                     if (isEmptyLine(formattedLine))
 5158                         appendCurrentChar();            // don't attach
 5159                     else
 5160                     {
 5161                         // if brace is broken or not an assignment
 5162                         if (currentLineBeginsWithBrace
 5163                                 && !isBraceType(braceType, SINGLE_LINE_TYPE))
 5164                         {
 5165                             appendSpacePad();
 5166                             appendCurrentChar(false);               // OK to attach
 5167                             // TODO: debug the following line
 5168                             testForTimeToSplitFormattedLine();      // line length will have changed
 5169 
 5170                             if (currentLineBeginsWithBrace
 5171                                     && currentLineFirstBraceNum == (size_t) charNum)
 5172                                 shouldBreakLineAtNextChar = true;
 5173                         }
 5174                         else
 5175                         {
 5176                             if (previousNonWSChar != '(')
 5177                             {
 5178                                 // don't space pad C++11 uniform initialization
 5179                                 if (!isBraceType(braceType, INIT_TYPE))
 5180                                     appendSpacePad();
 5181                             }
 5182                             appendCurrentChar();
 5183                         }
 5184                     }
 5185                 }
 5186             }
 5187             else if (braceFormatMode == BREAK_MODE)
 5188             {
 5189                 if (isWhiteSpace(peekNextChar()) && !isInVirginLine)
 5190                     breakLine();
 5191                 else if (isBeforeAnyComment() && sourceIterator->hasMoreLines())
 5192                 {
 5193                     // do not break unless comment is at line end
 5194                     if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
 5195                     {
 5196                         currentChar = ' ';            // remove brace from current line
 5197                         appendOpeningBrace = true;    // append brace to following line
 5198                     }
 5199                 }
 5200                 if (!isInLineBreak && previousNonWSChar != '(')
 5201                 {
 5202                     // don't space pad C++11 uniform initialization
 5203                     if (!isBraceType(braceType, INIT_TYPE))
 5204                         appendSpacePad();
 5205                 }
 5206                 appendCurrentChar();
 5207 
 5208                 if (currentLineBeginsWithBrace
 5209                         && currentLineFirstBraceNum == (size_t) charNum
 5210                         && !isBraceType(braceType, SINGLE_LINE_TYPE))
 5211                     shouldBreakLineAtNextChar = true;
 5212             }
 5213             else if (braceFormatMode == RUN_IN_MODE)
 5214             {
 5215                 if (isWhiteSpace(peekNextChar()) && !isInVirginLine)
 5216                     breakLine();
 5217                 else if (isBeforeAnyComment() && sourceIterator->hasMoreLines())
 5218                 {
 5219                     // do not break unless comment is at line end
 5220                     if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
 5221                     {
 5222                         currentChar = ' ';            // remove brace from current line
 5223                         appendOpeningBrace = true;    // append brace to following line
 5224                     }
 5225                 }
 5226                 if (!isInLineBreak && previousNonWSChar != '(')
 5227                 {
 5228                     // don't space pad C++11 uniform initialization
 5229                     if (!isBraceType(braceType, INIT_TYPE))
 5230                         appendSpacePad();
 5231                 }
 5232                 appendCurrentChar();
 5233             }
 5234             else if (braceFormatMode == NONE_MODE)
 5235             {
 5236                 if (currentLineBeginsWithBrace
 5237                         && (size_t) charNum == currentLineFirstBraceNum)
 5238                 {
 5239                     appendCurrentChar();                // don't attach
 5240                 }
 5241                 else
 5242                 {
 5243                     if (previousNonWSChar != '(')
 5244                     {
 5245                         // don't space pad C++11 uniform initialization
 5246                         if (!isBraceType(braceType, INIT_TYPE))
 5247                             appendSpacePad();
 5248                     }
 5249                     appendCurrentChar(false);           // OK to attach
 5250                 }
 5251             }
 5252         }
 5253         else         // not the first opening brace
 5254         {
 5255             if (braceFormatMode == RUN_IN_MODE)
 5256             {
 5257                 if (previousNonWSChar == '{'
 5258                         && braceTypeStack->size() > 2
 5259                         && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2],
 5260                                         SINGLE_LINE_TYPE))
 5261                     formatArrayRunIn();
 5262             }
 5263             else if (!isInLineBreak
 5264                      && !isWhiteSpace(peekNextChar())
 5265                      && previousNonWSChar == '{'
 5266                      && braceTypeStack->size() > 2
 5267                      && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2],
 5268                                      SINGLE_LINE_TYPE))
 5269                 formatArrayRunIn();
 5270 
 5271             appendCurrentChar();
 5272         }
 5273     }
 5274     else if (currentChar == '}')
 5275     {
 5276         if (attachClosingBraceMode)
 5277         {
 5278             if (isEmptyLine(formattedLine)          // if a blank line precedes this
 5279                     || isImmediatelyPostPreprocessor
 5280                     || isCharImmediatelyPostLineComment
 5281                     || isCharImmediatelyPostComment)
 5282                 appendCurrentChar();                // don't attach
 5283             else
 5284             {
 5285                 appendSpacePad();
 5286                 appendCurrentChar(false);           // attach
 5287             }
 5288         }
 5289         else
 5290         {
 5291             // does this close the first opening brace in the array?
 5292             // must check if the block is still a single line because of anonymous statements
 5293             if (!isBraceType(braceType, INIT_TYPE)
 5294                     && (!isBraceType(braceType, SINGLE_LINE_TYPE)
 5295                         || formattedLine.find('{') == string::npos))
 5296                 breakLine();
 5297             appendCurrentChar();
 5298         }
 5299 
 5300         // if a declaration follows an enum definition, space pad
 5301         char peekedChar = peekNextChar();
 5302         if ((isLegalNameChar(peekedC