home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / asty1153.zip / ASFormatter.cpp < prev    next >
C/C++ Source or Header  |  2002-03-07  |  51KB  |  1,601 lines

  1. /*
  2.  * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
  3.  *
  4.  * ASFormatter.cpp
  5.  * by Tal Davidson (davidsont@bigfoot.com)
  6.  * This file is a part of "Artistic Style" - an indentater and reformatter
  7.  * of C, C++, C# and Java source files.
  8.  *
  9.  * The "Artistic Style" project, including all files needed to compile it,
  10.  * is free software; you can redistribute it and/or use it and/or modify it
  11.  * under the terms of the GNU General Public License as published 
  12.  * by the Free Software Foundation; either version 2 of the License, 
  13.  * or (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18.  *
  19.  * You should have received a copy of the GNU General Public
  20.  * License along with this program.
  21.  *
  22.  *
  23.  * Patches:
  24.  * 26 November 1998 - Richard Bullington -
  25.  *        A correction of line-breaking in headers following '}',
  26.  *        was created using a variation of a  patch by Richard Bullington.
  27.  */
  28.  
  29. #include "compiler_defines.h"
  30. #include "astyle.h"
  31.  
  32. #include <string>
  33. #include <cctype>
  34. #include <vector>
  35. #include <algorithm>
  36. #include <iostream>
  37.  
  38.  
  39. #define INIT_CONTAINER(container, value)     {if ( (container) != NULL ) delete (container); (container) = (value); }
  40. #define DELETE_CONTAINER(container)          {if ( (container) != NULL ) delete (container) ; }
  41. #define IS_A(a,b)                            ( ((a) & (b)) == (b))
  42. #ifdef USES_NAMESPACE
  43. using namespace std;
  44.  
  45. namespace astyle
  46. {
  47. #endif
  48.  
  49.  
  50. bool ASFormatter::calledInitStatic = false;
  51. vector<const string*> ASFormatter::headers;
  52. vector<const string*> ASFormatter::nonParenHeaders;
  53. vector<const string*> ASFormatter::preprocessorHeaders;
  54. vector<const string*> ASFormatter::preDefinitionHeaders;
  55. vector<const string*> ASFormatter::preCommandHeaders;
  56. vector<const string*> ASFormatter::operators;
  57. vector<const string*> ASFormatter::assignmentOperators;
  58.  
  59. /**
  60.  * Constructor of ASFormatter
  61.  */
  62. ASFormatter::ASFormatter()
  63. {
  64.     staticInit();
  65.  
  66.     preBracketHeaderStack = NULL;
  67.     bracketTypeStack = NULL;
  68.     parenStack = NULL;
  69.  
  70.     sourceIterator = NULL;
  71.     bracketFormatMode = NONE_MODE;
  72.     shouldPadOperators = false;
  73.     shouldPadParenthesies = false;
  74.     shouldBreakOneLineBlocks = true;
  75.     shouldBreakOneLineStatements = true;
  76.     shouldConvertTabs = false;
  77.     shouldBreakBlocks = false;
  78.     shouldBreakClosingHeaderBlocks = false;
  79.     shouldBreakClosingHeaderBrackets = false;
  80.     shouldBreakElseIfs = false;
  81. }
  82.  
  83. /**
  84.  * Destructor of ASFormatter
  85.  */
  86. ASFormatter::~ASFormatter()
  87. {
  88.     DELETE_CONTAINER( preBracketHeaderStack );
  89. }
  90.  
  91. /**
  92.  * initialization of static data of ASFormatter.
  93.  */
  94. void ASFormatter::staticInit()
  95. {
  96.     if (calledInitStatic)
  97.         return;
  98.  
  99.     calledInitStatic = true;
  100.  
  101.     headers.push_back(&AS_IF);
  102.     headers.push_back(&AS_ELSE);
  103.     headers.push_back(&AS_DO);
  104.     headers.push_back(&AS_WHILE);
  105.     headers.push_back(&AS_FOR);
  106.     headers.push_back(&AS_SYNCHRONIZED);
  107.     headers.push_back(&AS_TRY);
  108.     headers.push_back(&AS_CATCH);
  109.     headers.push_back(&AS_FINALLY);
  110.     headers.push_back(&AS_SWITCH);
  111.     headers.push_back(&AS_TEMPLATE);
  112.     headers.push_back(&AS_FOREACH);
  113.     headers.push_back(&AS_LOCK);
  114.     headers.push_back(&AS_UNSAFE);
  115.     headers.push_back(&AS_FIXED);
  116.     headers.push_back(&AS_GET);
  117.     headers.push_back(&AS_SET);
  118.     headers.push_back(&AS_ADD);
  119.     headers.push_back(&AS_REMOVE);
  120.  
  121.     nonParenHeaders.push_back(&AS_ELSE);
  122.     nonParenHeaders.push_back(&AS_DO);
  123.     nonParenHeaders.push_back(&AS_TRY);
  124.     nonParenHeaders.push_back(&AS_FINALLY);
  125.     nonParenHeaders.push_back(&AS_UNSAFE);
  126.     nonParenHeaders.push_back(&AS_GET);
  127.     nonParenHeaders.push_back(&AS_SET);
  128.     nonParenHeaders.push_back(&AS_ADD);
  129.     nonParenHeaders.push_back(&AS_REMOVE);
  130.  
  131. //    nonParenHeaders.push_back(&AS_TEMPLATE);
  132.  
  133.     preDefinitionHeaders.push_back(&AS_CLASS);
  134.     preDefinitionHeaders.push_back(&AS_INTERFACE);
  135.     preDefinitionHeaders.push_back(&AS_NAMESPACE);
  136.     preDefinitionHeaders.push_back(&AS_STRUCT);
  137.  
  138.     preCommandHeaders.push_back(&AS_EXTERN);
  139.     preCommandHeaders.push_back(&AS_THROWS);
  140.     preCommandHeaders.push_back(&AS_CONST);
  141.  
  142.     preprocessorHeaders.push_back(&AS_BAR_DEFINE);
  143.             //// DEVEL: removed the folowing lines
  144.             ////preprocessorHeaders.push_back(&AS_BAR_INCLUDE);
  145.             ////preprocessorHeaders.push_back(&AS_BAR_IF); // #if or #ifdef
  146.             ////preprocessorHeaders.push_back(&AS_BAR_EL); // #else or #elif
  147.             ////preprocessorHeaders.push_back(&AS_BAR_ENDIF);
  148.  
  149.     operators.push_back(&AS_PLUS_ASSIGN);
  150.     operators.push_back(&AS_MINUS_ASSIGN);
  151.     operators.push_back(&AS_MULT_ASSIGN);
  152.     operators.push_back(&AS_DIV_ASSIGN);
  153.     operators.push_back(&AS_MOD_ASSIGN);
  154.     operators.push_back(&AS_OR_ASSIGN);
  155.     operators.push_back(&AS_AND_ASSIGN);
  156.     operators.push_back(&AS_XOR_ASSIGN);
  157.     operators.push_back(&AS_EQUAL);
  158.     operators.push_back(&AS_PLUS_PLUS);
  159.     operators.push_back(&AS_MINUS_MINUS);
  160.     operators.push_back(&AS_NOT_EQUAL);
  161.     operators.push_back(&AS_GR_EQUAL);
  162.     operators.push_back(&AS_GR_GR_GR_ASSIGN);
  163.     operators.push_back(&AS_GR_GR_ASSIGN);
  164.     operators.push_back(&AS_GR_GR_GR);
  165.     operators.push_back(&AS_GR_GR);
  166.     operators.push_back(&AS_LS_EQUAL);
  167.     operators.push_back(&AS_LS_LS_LS_ASSIGN);
  168.     operators.push_back(&AS_LS_LS_ASSIGN);
  169.     operators.push_back(&AS_LS_LS_LS);
  170.     operators.push_back(&AS_LS_LS);
  171.     operators.push_back(&AS_ARROW);
  172.     operators.push_back(&AS_AND);
  173.     operators.push_back(&AS_OR);
  174.     operators.push_back(&AS_COLON_COLON);
  175.  
  176.             //// BUGFIX: removed the folowing lines
  177.             ////    operators.push_back(&AS_PAREN_PAREN);
  178.             ////    operators.push_back(&AS_BLPAREN_BLPAREN);
  179.  
  180.     operators.push_back(&AS_PLUS);
  181.     operators.push_back(&AS_MINUS);
  182.     operators.push_back(&AS_MULT);
  183.     operators.push_back(&AS_DIV);
  184.     operators.push_back(&AS_MOD);
  185.     operators.push_back(&AS_QUESTION);
  186.     operators.push_back(&AS_COLON);
  187.     operators.push_back(&AS_ASSIGN);
  188.     operators.push_back(&AS_LS);
  189.     operators.push_back(&AS_GR);
  190.     operators.push_back(&AS_NOT);
  191.     operators.push_back(&AS_BIT_OR);
  192.     operators.push_back(&AS_BIT_AND);
  193.     operators.push_back(&AS_BIT_NOT);
  194.     operators.push_back(&AS_BIT_XOR);
  195.     operators.push_back(&AS_OPERATOR);
  196.     operators.push_back(&AS_COMMA);
  197.     //    operators.push_back(&AS_SEMICOLON);
  198.     operators.push_back(&AS_RETURN);
  199.  
  200.     assignmentOperators.push_back(&AS_PLUS_ASSIGN);
  201.     assignmentOperators.push_back(&AS_MINUS_ASSIGN);
  202.     assignmentOperators.push_back(&AS_MULT_ASSIGN);
  203.     assignmentOperators.push_back(&AS_DIV_ASSIGN);
  204.     assignmentOperators.push_back(&AS_MOD_ASSIGN);
  205.     assignmentOperators.push_back(&AS_XOR_ASSIGN);
  206.     assignmentOperators.push_back(&AS_OR_ASSIGN);
  207.     assignmentOperators.push_back(&AS_AND_ASSIGN);
  208.     assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
  209.     assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
  210.     assignmentOperators.push_back(&AS_ASSIGN);
  211. }
  212.  
  213. /**
  214.  * initialize the ASFormatter.
  215.  *
  216.  * init() should be called every time a ASFormatter object is to start
  217.  * formatting a NEW source file.
  218.  * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
  219.  * that will be used to iterate through the source code. This object will be
  220.  * deleted during the ASFormatter's destruction, and thus should not be
  221.  * deleted elsewhere.
  222.  *
  223.  * @param iter     a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
  224.  */
  225. void ASFormatter::init(ASSourceIterator *si)
  226. {
  227.     ASBeautifier::init(si);
  228.     sourceIterator = si;
  229.  
  230.     INIT_CONTAINER( preBracketHeaderStack, new vector<const string*> );
  231.     INIT_CONTAINER( bracketTypeStack, new vector<BracketType> );
  232.     bracketTypeStack->push_back(DEFINITION_TYPE);
  233.     INIT_CONTAINER( parenStack, new vector<int> );
  234.     parenStack->push_back(0);
  235.  
  236.     currentHeader = NULL;
  237.     currentLine = string("");
  238.     formattedLine = "";
  239.     currentChar = ' ';
  240.     previousCommandChar = ' ';
  241.     previousNonWSChar = ' ';
  242.     quoteChar = '"';
  243.     charNum = 0;
  244.     previousOperator = NULL;
  245.  
  246.     isVirgin = true;
  247.     isInLineComment = false;
  248.     isInComment = false;
  249.     isInPreprocessor = false;
  250.     doesLineStartComment = false;
  251.     isInQuote = false;
  252.     isSpecialChar = false;
  253.     isNonParenHeader = true;
  254.     foundPreDefinitionHeader = false;
  255.     foundPreCommandHeader = false;
  256.     foundQuestionMark = false;
  257.     isInLineBreak = false;
  258.     endOfCodeReached = false;
  259.     isLineReady = false;
  260.     isPreviousBracketBlockRelated = true;
  261.     isInPotentialCalculation = false;
  262.     //foundOneLineBlock = false;
  263.     shouldReparseCurrentChar = false;
  264.     passedSemicolon = false;
  265.     passedColon = false;
  266.     isInTemplate = false;
  267.     shouldBreakLineAfterComments = false;
  268.     isImmediatelyPostComment = false;
  269.     isImmediatelyPostLineComment = false;
  270.     isImmediatelyPostEmptyBlock = false;
  271.  
  272.     isPrependPostBlockEmptyLineRequested = false;
  273.     isAppendPostBlockEmptyLineRequested = false;
  274.     prependEmptyLine = false;
  275.  
  276.     foundClosingHeader = false;
  277.     previousReadyFormattedLineLength = 0;
  278.  
  279.     isImmediatelyPostHeader = false;
  280.     isInHeader = false;
  281. }
  282.  
  283. /**
  284.  * get the next formatted line.
  285.  *
  286.  * @return    formatted line.
  287.  */
  288.  
  289. string ASFormatter::nextLine()
  290. {
  291.     const string *newHeader;
  292.     bool isCharImmediatelyPostComment = false;
  293.     bool isPreviousCharPostComment = false;
  294.     bool isCharImmediatelyPostLineComment = false;
  295.     bool isInVirginLine = isVirgin;
  296.     bool isCharImmediatelyPostOpenBlock = false;
  297.     bool isCharImmediatelyPostCloseBlock = false;
  298.     bool isCharImmediatelyPostTemplate = false;
  299.     bool isCharImmediatelyPostHeader = false;
  300.  
  301.     if (!isFormattingEnabled())
  302.         return ASBeautifier::nextLine();
  303.  
  304.     while (!isLineReady)
  305.     {
  306.         if (shouldReparseCurrentChar)
  307.             shouldReparseCurrentChar = false;
  308.         else if (!getNextChar())
  309.         {
  310.             breakLine();
  311.             return beautify(readyFormattedLine);
  312.         }
  313.         else // stuff to do when reading a new character...
  314.         {
  315.             // make sure that a virgin '{' at the begining ofthe file will be treated as a block...
  316.             if (isInVirginLine && currentChar == '{')
  317.                 previousCommandChar = '{';
  318.             isPreviousCharPostComment = isCharImmediatelyPostComment;
  319.             isCharImmediatelyPostComment = false;
  320.             isCharImmediatelyPostTemplate = false;
  321.             isCharImmediatelyPostHeader = false;
  322.         }
  323.  
  324.         if (isInLineComment)
  325.         {
  326.             appendCurrentChar();
  327.  
  328.             // explicitely break a line when a line comment's end is found.
  329.             if (/*bracketFormatMode == ATTACH_MODE &&*/ charNum+1 == currentLine.length())
  330.             {
  331.                 isInLineBreak = true;
  332.                 isInLineComment = false;
  333.                 isImmediatelyPostLineComment = true;
  334.                 currentChar = 0;  //make sure it is a neutral char.
  335.             }
  336.             continue;
  337.         }
  338.         else if (isInComment)
  339.         {
  340.             if (isSequenceReached(AS_CLOSE_COMMENT))
  341.             {
  342.                 isInComment = false;
  343.                 isImmediatelyPostComment = true;
  344.                 appendSequence(AS_CLOSE_COMMENT);
  345.                 goForward(1);
  346.             }
  347.             else
  348.                 appendCurrentChar();
  349.  
  350.             continue;
  351.         }
  352.  
  353.         // not in line comment or comment
  354.  
  355.         else if (isInQuote)
  356.         {
  357.             if (isSpecialChar)
  358.             {
  359.                 isSpecialChar = false;
  360.                 appendCurrentChar();
  361.             }
  362.             else if (currentChar == '\\')
  363.             {
  364.                 isSpecialChar = true;
  365.                 appendCurrentChar();
  366.             }
  367.             else if (quoteChar == currentChar)
  368.             {
  369.                 isInQuote = false;
  370.                 appendCurrentChar();
  371.             }
  372.             else
  373.             {
  374.                 appendCurrentChar();
  375.             }
  376.  
  377.             continue;
  378.         }
  379.  
  380.  
  381.  
  382.         // handle white space - needed to simplify the rest.
  383.         if (isWhiteSpace(currentChar) || isInPreprocessor)
  384.         {
  385.             ////// DEVEL: if (isLegalNameChar(previousChar) && isLegalNameChar(peekNextChar()))
  386.             appendCurrentChar();
  387.             continue;
  388.         }
  389.  
  390.         /* not in MIDDLE of quote or comment or white-space of any type ... */
  391.  
  392.         if (isSequenceReached(AS_OPEN_LINE_COMMENT))
  393.         {
  394.             isInLineComment = true;
  395.             if (shouldPadOperators)
  396.                 appendSpacePad();
  397.             appendSequence(AS_OPEN_LINE_COMMENT);
  398.             goForward(1);
  399.             continue;
  400.         }
  401.         else if (isSequenceReached(AS_OPEN_COMMENT))
  402.         {
  403.             isInComment = true;
  404.             if (shouldPadOperators)
  405.                 appendSpacePad();
  406.             appendSequence(AS_OPEN_COMMENT);
  407.             goForward(1);
  408.             continue;
  409.         }
  410.         else if (currentChar == '"' || currentChar == '\'')
  411.         {
  412.             isInQuote = true;
  413.             quoteChar = currentChar;
  414.                 ////            if (shouldPadOperators)  // BUGFIX: these two lines removed. seem to be unneeded, and interfere with L"
  415.                 ////                appendSpacePad();    // BUFFIX:    TODO make sure the removal of these lines doesn't reopen old bugs...
  416.             appendCurrentChar();
  417.             continue;
  418.         }
  419.  
  420.         /* not in quote or comment or white-space of any type ... */
  421.  
  422.         // check if in preprocessor
  423.         // ** isInPreprocessor will be automatically reset at the begining
  424.         //    of a new line in getnextChar()
  425.         if (currentChar == '#')
  426.             isInPreprocessor = true;
  427.  
  428.         if (isInPreprocessor)
  429.         {
  430.             appendCurrentChar();
  431.             continue;
  432.         }
  433.  
  434.         /* not in preprocessor ... */
  435.  
  436.         if (isImmediatelyPostComment)
  437.         {
  438.             isImmediatelyPostComment = false;
  439.             isCharImmediatelyPostComment = true;
  440.         }
  441.  
  442.         if (isImmediatelyPostLineComment)
  443.         {
  444.             isImmediatelyPostLineComment = false;
  445.             isCharImmediatelyPostLineComment = true;
  446.         }
  447.  
  448.         if (shouldBreakLineAfterComments)
  449.         {
  450.             shouldBreakLineAfterComments = false;
  451.             shouldReparseCurrentChar = true;
  452.             breakLine();
  453.             continue;
  454.         }
  455.  
  456.         // reset isImmediatelyPostHeader information
  457.         if (isImmediatelyPostHeader)
  458.         {
  459.             isImmediatelyPostHeader = false;
  460.             isCharImmediatelyPostHeader = true;
  461.             
  462.             // Make sure headers are broken from their succeeding blocks
  463.             // (e.g.    
  464.             //     if (isFoo) DoBar();
  465.             //  should become
  466.             //     if (isFoo)
  467.             //         DoBar;
  468.             // )
  469.             // But treat else if() as a special case which should not be broken!
  470.             if (shouldBreakOneLineStatements)
  471.             {
  472.                 // if may break 'else if()'s, ythen simply break the line
  473.  
  474.                 if (shouldBreakElseIfs)
  475.                     isInLineBreak = true;
  476.  
  477.                 else
  478.                 {
  479.                     // make sure 'else if()'s are not broken.
  480.  
  481.                     bool isInElseIf = false;
  482.                     const string *upcomingHeader;
  483.                 
  484.                     upcomingHeader = findHeader(headers);
  485.                     if (currentHeader == &AS_ELSE && upcomingHeader == &AS_IF)
  486.                         isInElseIf = true;        
  487.  
  488.                     if (!isInElseIf)
  489.                         isInLineBreak = true;  ////BUGFIX: SHOULD NOT BE breakLine() !!!
  490.                 }
  491.             }
  492.         }
  493.  
  494.         if (passedSemicolon)
  495.         {
  496.             passedSemicolon = false;
  497.             if (parenStack->back() == 0)
  498.             {
  499.                 shouldReparseCurrentChar = true;
  500.                 isInLineBreak = true;
  501.                 continue;
  502.             }
  503.         }
  504.  
  505.         if (passedColon)
  506.         {
  507.             passedColon = false;
  508.             if (parenStack->back() == 0)
  509.             {
  510.                 shouldReparseCurrentChar = true;
  511.                 isInLineBreak = true;
  512.                 continue;
  513.             }
  514.         }
  515.  
  516.         // Check if in template declaration, e.g. foo<bar> or foo<bar,fig>
  517.         // If so, set isInTemplate to true
  518.         //
  519.         if (!isInTemplate && currentChar == '<')
  520.         {
  521.             int templateDepth = 0;
  522.             const string *oper;
  523.             for ( int i=charNum; 
  524.                   i< currentLine.length(); 
  525.                   i += (oper ? oper->length() : 1) )
  526.             {
  527.                 oper = ASBeautifier::findHeader(currentLine, i, operators);
  528.  
  529.                 if (oper == &AS_LS)
  530.                 {
  531.                     templateDepth++;
  532.                 }
  533.                 else if (oper == &AS_GR)
  534.                 {
  535.                     templateDepth--;
  536.                     if (templateDepth == 0)
  537.                     {
  538.                         // this is a template!
  539.                         //
  540.                         isInTemplate = true;
  541.                         break;
  542.                     }
  543.                 }
  544.                 else if (oper == &AS_COMMA               // comma,     e.g. A<int, char>
  545.                             || oper == &AS_BIT_AND       // reference, e.g. A<int&>
  546.                             || oper == &AS_MULT          // pointer,   e.g. A<int*>
  547.                             || oper == &AS_COLON_COLON)  // ::,        e.g. std::string
  548.                 {
  549.                     continue;
  550.                 }
  551.                 else if (!isLegalNameChar(currentLine[i]) && !isWhiteSpace(currentLine[i]))
  552.                 {
  553.                     // this is not a template -> leave...
  554.                     //
  555.                     isInTemplate = false;
  556.                     break;
  557.                 }
  558.             }
  559.         }
  560.  
  561.         // handle parenthesies
  562.         //
  563.         if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
  564.         {
  565.             parenStack->back()++;
  566.         }
  567.         else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
  568.         {
  569.             parenStack->back()--;
  570.             if (isInTemplate && parenStack->back() == 0)
  571.             {
  572.                 isInTemplate = false;
  573.                 isCharImmediatelyPostTemplate = true;
  574.             }
  575.  
  576.             // check if this parenthesis closes a header, e.g. if (...), while (...)
  577.             //
  578.             if (isInHeader && parenStack->back() == 0)
  579.             {
  580.                 isInHeader = false;
  581.                 isImmediatelyPostHeader = true;
  582.             }
  583.  
  584.         }
  585.  
  586.         // handle brackets
  587.         //
  588.         BracketType bracketType = NULL_TYPE;
  589.  
  590.         if (currentChar == '{')
  591.         {
  592.             bracketType = getBracketType();
  593.             foundPreDefinitionHeader = false;
  594.             foundPreCommandHeader = false;
  595.  
  596.             bracketTypeStack->push_back(bracketType);
  597.             preBracketHeaderStack->push_back(currentHeader);
  598.             currentHeader = NULL;
  599.  
  600.             isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
  601.         }
  602.         else if (currentChar == '}')
  603.         {
  604.             // if a request has been made to append a post block empty line,
  605.             // but the block exists immediately before a closing bracket,
  606.             // then there is not need for the post block empty line.
  607.             //
  608.             isAppendPostBlockEmptyLineRequested = false;
  609.  
  610.             if (!bracketTypeStack->empty())
  611.             {
  612.                 bracketType = bracketTypeStack->back();
  613.                 bracketTypeStack->pop_back();
  614.  
  615.                 isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
  616.             }
  617.  
  618.             if (!preBracketHeaderStack->empty())
  619.             {
  620.                 currentHeader = preBracketHeaderStack->back();
  621.                 preBracketHeaderStack->pop_back();
  622.             }
  623.             else
  624.                 currentHeader = NULL;
  625.         }
  626.  
  627.         if (!IS_A(bracketType, ARRAY_TYPE))
  628.         {
  629.  
  630.             if (currentChar == '{')
  631.             {
  632.                 parenStack->push_back(0);
  633.             }
  634.             else if (currentChar == '}')
  635.             {
  636.                 if (!parenStack->empty())
  637.                 {
  638.                     parenStack->pop_back();
  639.                 }
  640.             }
  641.  
  642.             if (bracketFormatMode != NONE_MODE)
  643.             {
  644.                 if (currentChar == '{')
  645.                 {
  646.                     if ( ( bracketFormatMode == ATTACH_MODE
  647.                            || bracketFormatMode == BDAC_MODE && bracketTypeStack->size()>=2
  648.                            && IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], COMMAND_TYPE) /*&& isInLineBreak*/)
  649.                          && !isCharImmediatelyPostLineComment )
  650.                     {
  651.                         appendSpacePad();
  652.                         if (!isCharImmediatelyPostComment // do not attach '{' to lines that end with /**/ comments.
  653.                                 && previousCommandChar != '{' 
  654.                                 && previousCommandChar != '}' 
  655.                                 && previousCommandChar != ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
  656.                             appendCurrentChar(false);
  657.                         else
  658.                             appendCurrentChar(true);
  659.                         continue;
  660.                     }
  661.                     else if (bracketFormatMode == BREAK_MODE
  662.                              || bracketFormatMode == BDAC_MODE && bracketTypeStack->size()>=2
  663.                              && IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], DEFINITION_TYPE))
  664.                     {
  665.                         if ( shouldBreakOneLineBlocks || !IS_A(bracketType,  SINGLE_LINE_TYPE) )
  666.                             breakLine();
  667.                         appendCurrentChar();
  668.                         continue;
  669.                     }
  670.                 }
  671.                 else if (currentChar == '}')
  672.                 {
  673.                     // bool origLineBreak = isInLineBreak;
  674.  
  675.                     // mark state of immediately after empty block
  676.                     // this state will be used for locating brackets that appear immedately AFTER an empty block (e.g. '{} \n}').
  677.                     if (previousCommandChar == '{')
  678.                         isImmediatelyPostEmptyBlock = true;
  679.  
  680.                     if ( (!(previousCommandChar == '{' && isPreviousBracketBlockRelated) )          // this '{' does not close an empty block
  681.                             && (shouldBreakOneLineBlocks || !IS_A(bracketType,  SINGLE_LINE_TYPE))  // astyle is allowed to break on line blocks 
  682.                             && !isImmediatelyPostEmptyBlock)                                        // this '}' does not immediately follow an empty block 
  683.                     {
  684.                         breakLine();
  685.                         appendCurrentChar();
  686.                     }
  687.                     else
  688.                     {
  689.                         if (!isCharImmediatelyPostComment)
  690.                             isInLineBreak = false;
  691.                         appendCurrentChar();
  692.                         if (shouldBreakOneLineBlocks || !IS_A(bracketType,  SINGLE_LINE_TYPE))
  693.                             shouldBreakLineAfterComments = true;
  694.                     }
  695.  
  696.                     if (shouldBreakBlocks)
  697.                     {
  698.                         isAppendPostBlockEmptyLineRequested =true;
  699.                     }
  700.  
  701.                     continue;
  702.                 }
  703.             }
  704.         }
  705.  
  706.         if ( ( (previousCommandChar == '{'
  707.                 && isPreviousBracketBlockRelated)
  708.  
  709.                || (previousCommandChar == '}'
  710.                    && !isImmediatelyPostEmptyBlock   // <--
  711.                    && isPreviousBracketBlockRelated
  712.                    && !isPreviousCharPostComment    // <-- Fixes wrongly appended newlines after '}' immediately after comments... 10/9/1999
  713.                    && peekNextChar() != ' '))
  714.  
  715.                &&  (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(),  SINGLE_LINE_TYPE)) )
  716.         {
  717.             isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
  718.             isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
  719.          
  720.             previousCommandChar = ' ';   
  721.             isInLineBreak = true;  //<----
  722.         }
  723.  
  724.         // reset block handling flags
  725.         isImmediatelyPostEmptyBlock = false;
  726.  
  727.         // look for headers
  728.         if (!isInTemplate)
  729.         {
  730.             if ( (newHeader = findHeader(headers)) != NULL)
  731.             {
  732.                 foundClosingHeader = false;
  733.                 const string *previousHeader;
  734.  
  735.                 // recognize closing headers of do..while, if..else, try..catch..finally
  736.                 if ( (newHeader == &AS_ELSE && currentHeader == &AS_IF)
  737.                         || (newHeader == &AS_WHILE && currentHeader == &AS_DO)
  738.                         || (newHeader == &AS_CATCH && currentHeader == &AS_TRY)
  739.                         || (newHeader == &AS_CATCH && currentHeader == &AS_CATCH)
  740.                         || (newHeader == &AS_FINALLY && currentHeader == &AS_TRY)
  741.                         || (newHeader == &AS_FINALLY && currentHeader == &AS_CATCH) )
  742.                     foundClosingHeader = true;
  743.  
  744.                 previousHeader = currentHeader;
  745.                 currentHeader = newHeader;
  746.  
  747.                 // If in ATTACH or LINUX bracket modes, attach closing headers (e.g. 'else', 'catch')
  748.                 // to their preceding bracket,
  749.                 // But do not perform the attachment if the shouldBreakClosingHeaderBrackets is set!
  750.                 if (!shouldBreakClosingHeaderBrackets && foundClosingHeader && (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE) && previousNonWSChar == '}')
  751.                 {
  752.                     isInLineBreak = false;
  753.                     appendSpacePad();
  754.  
  755.                     if (shouldBreakBlocks)
  756.                         isAppendPostBlockEmptyLineRequested = false;
  757.                 }
  758.  
  759.                 //Check if a template definition as been reached, e.g. template<class A>
  760.                 if (newHeader == &AS_TEMPLATE)
  761.                 {
  762.                     isInTemplate = true;
  763.                 }
  764.  
  765.                 // check if the found header is non-paren header
  766.                 isNonParenHeader = ( find(nonParenHeaders.begin(), nonParenHeaders.end(),
  767.                                           newHeader) != nonParenHeaders.end() );
  768.                 appendSequence(*currentHeader);
  769.                 goForward(currentHeader->length() - 1);
  770.                 // if padding is on, and a paren-header is found
  771.                 // then add a space pad after it.
  772.                 if (shouldPadOperators && !isNonParenHeader)
  773.                     appendSpacePad();
  774.  
  775.  
  776.                 // Signal that a header has been reached
  777.                 // *** But treat a closing while() (as in do...while)
  778.                 //     as if it where NOT a header since a closing while()
  779.                 //     should never have a block after it!
  780.                 if (!(foundClosingHeader && currentHeader == &AS_WHILE))
  781.                 {
  782.                     isInHeader = true;
  783.                     if (isNonParenHeader)
  784.                     {
  785.                         isImmediatelyPostHeader = true;
  786.                         isInHeader = false;
  787.                     }
  788.                 }
  789.  
  790.                 if (currentHeader == &AS_IF && previousHeader == &AS_ELSE)
  791.                     isInLineBreak = false;
  792.  
  793.                 if (shouldBreakBlocks)
  794.                 {
  795.                     if (previousHeader == NULL
  796.                             && !foundClosingHeader
  797.                             && !isCharImmediatelyPostOpenBlock)
  798.                     {
  799.                         isPrependPostBlockEmptyLineRequested = true;
  800.                     }
  801.  
  802.                     if (currentHeader == &AS_ELSE
  803.                             || currentHeader == &AS_CATCH
  804.                             || currentHeader == &AS_FINALLY
  805.                             || foundClosingHeader)
  806.                     {
  807.                         isPrependPostBlockEmptyLineRequested = false;
  808.                     }
  809.  
  810.                     if (shouldBreakClosingHeaderBlocks
  811.                             &&  isCharImmediatelyPostCloseBlock)
  812.                     {
  813.                         isPrependPostBlockEmptyLineRequested = true;
  814.                     }
  815.  
  816.                 }
  817.  
  818.                 continue;
  819.             }
  820.             else if ( (newHeader = findHeader(preDefinitionHeaders)) != NULL)
  821.             {
  822.                 foundPreDefinitionHeader = true;
  823.                 appendSequence(*newHeader);
  824.                 goForward(newHeader->length() - 1);
  825.  
  826.                 if (shouldBreakBlocks)
  827.                     isPrependPostBlockEmptyLineRequested = true;
  828.  
  829.                 continue;
  830.             }
  831.             else if ( (newHeader = findHeader(preCommandHeaders)) != NULL)
  832.             {
  833.                 foundPreCommandHeader = true;
  834.                 appendSequence(*newHeader);
  835.                 goForward(newHeader->length() - 1);
  836.  
  837.                 continue;
  838.             }
  839.         }
  840.  
  841.         if (previousNonWSChar == '}' || currentChar == ';')
  842.         {
  843.             if (shouldBreakOneLineStatements && currentChar == ';'
  844.                     && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(),  SINGLE_LINE_TYPE)))
  845.             {
  846.                 passedSemicolon = true;
  847.             }
  848.  
  849.             if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0)
  850.             {
  851.                 isAppendPostBlockEmptyLineRequested = true;
  852.             }
  853.  
  854.             if (currentChar != ';')
  855.                 currentHeader = NULL; //DEVEL: is this ok?
  856.  
  857.             foundQuestionMark = false;
  858.             foundPreDefinitionHeader = false;
  859.             foundPreCommandHeader = false;
  860.             isInPotentialCalculation = false;
  861.  
  862.         }
  863.  
  864.         if (currentChar == ':'
  865.                 && shouldBreakOneLineStatements
  866.                 && !foundQuestionMark // not in a ... ? ... : ... sequence
  867.                 && !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar
  868.                 && previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...)
  869.                 && previousChar != ':' // not part of '::'
  870.                 && peekNextChar() != ':') // not part of '::'
  871.         {
  872.             passedColon = true;
  873.             if (shouldBreakBlocks)
  874.                 isPrependPostBlockEmptyLineRequested = true;
  875.         }
  876.  
  877.         if (currentChar == '?')
  878.             foundQuestionMark = true;
  879.  
  880.         if (shouldPadOperators)
  881.         {
  882.             if ((newHeader = findHeader(operators)) != NULL)
  883.             {
  884.                 bool shouldPad = (newHeader != &AS_COLON_COLON
  885.                                   && newHeader != &AS_PAREN_PAREN
  886.                                   && newHeader != &AS_BLPAREN_BLPAREN
  887.                                   && newHeader != &AS_PLUS_PLUS
  888.                                   && newHeader != &AS_MINUS_MINUS
  889.                                   && newHeader != &AS_NOT
  890.                                   && newHeader != &AS_BIT_NOT
  891.                                   && newHeader != &AS_ARROW
  892.                                   && newHeader != &AS_OPERATOR
  893.                                   && !(newHeader == &AS_MINUS && isInExponent())
  894.                                   && !(newHeader == &AS_PLUS && isInExponent())
  895.                                   && previousOperator != &AS_OPERATOR
  896.                                   && !((newHeader == &AS_MULT || newHeader == &AS_BIT_AND)
  897.                                        && isPointerOrReference())
  898.                                   && !( (isInTemplate || isCharImmediatelyPostTemplate) 
  899.                                         && (newHeader == &AS_LS || newHeader == &AS_GR))
  900.                                  );
  901.  
  902.                 if (!isInPotentialCalculation)
  903.                     if (find(assignmentOperators.begin(), assignmentOperators.end(), newHeader)
  904.                             != assignmentOperators.end())
  905.                         isInPotentialCalculation = true;
  906.  
  907.                 // pad before operator
  908.                 if (shouldPad
  909.                         && !(newHeader == &AS_COLON && !foundQuestionMark)
  910.                         && newHeader != &AS_SEMICOLON
  911.                         && newHeader != &AS_COMMA)
  912.                     appendSpacePad();
  913.                 appendSequence(*newHeader);
  914.                 goForward(newHeader->length() - 1);
  915.                 
  916.                 // since this block handles '()' and '[]',
  917.                 // the parenStack must be updated here accordingly!
  918.                 if (newHeader == &AS_PAREN_PAREN 
  919.                         || newHeader == &AS_BLPAREN_BLPAREN)
  920.                     parenStack->back()--;
  921.  
  922.                 currentChar = (*newHeader)[newHeader->length() - 1];
  923.                 // pad after operator
  924.                 // but do not pad after a '-' that is a urinary-minus.
  925.                 if ( shouldPad && !(newHeader == &AS_MINUS && isUrinaryMinus()) )
  926.                     appendSpacePad();
  927.  
  928.                 previousOperator = newHeader;
  929.                 continue;
  930.             }
  931.         }
  932.         if (shouldPadParenthesies)
  933.         {
  934.             if (currentChar == '(' || currentChar == '[' )
  935.             {
  936.                 char peekedChar = peekNextChar();
  937.  
  938.                 isInPotentialCalculation = true;
  939.                 appendCurrentChar();
  940.                 if (!(currentChar == '(' && peekedChar == ')')
  941.                         && !(currentChar == '[' && peekedChar == ']'))
  942.                     appendSpacePad();
  943.                 continue;
  944.             }
  945.             else if (currentChar == ')' || currentChar == ']')
  946.             {
  947.                 char peekedChar = peekNextChar();
  948.                 
  949.                 if (!(previousChar == '(' && currentChar == ')')
  950.                         && !(previousChar == '[' && currentChar == ']'))
  951.                     appendSpacePad();
  952.  
  953.                 appendCurrentChar();
  954.  
  955.                 if (peekedChar != ';' && peekedChar != ',' && peekedChar != '.'
  956.                         && !(currentChar == ']' && peekedChar == '['))
  957.                     appendSpacePad();
  958.                 continue;
  959.             }
  960.         }
  961.  
  962.         appendCurrentChar();
  963.     }
  964.  
  965.     // return a beautified (i.e. correctly indented) line.
  966.  
  967.     string beautifiedLine;
  968.     int readyFormattedLineLength = trim(readyFormattedLine).length();
  969.  
  970.     if (prependEmptyLine
  971.             && readyFormattedLineLength > 0
  972.             && previousReadyFormattedLineLength > 0)
  973.     {
  974.         isLineReady = true; // signal that a readyFormattedLine is still waiting
  975.         beautifiedLine = beautify("");
  976.     }
  977.     else
  978.     {
  979.         isLineReady = false;
  980.         beautifiedLine = beautify(readyFormattedLine);
  981.     }
  982.  
  983.     prependEmptyLine = false;
  984.     previousReadyFormattedLineLength = readyFormattedLineLength;
  985.  
  986.     return beautifiedLine;
  987.  
  988. }
  989.  
  990.  
  991. /**
  992. * check if there are any indented lines ready to be read by nextLine()
  993. *
  994. * @return    are there any indented lines ready?
  995. */
  996. bool ASFormatter::hasMoreLines() const
  997. {
  998.     if (!isFormattingEnabled())
  999.         return ASBeautifier::hasMoreLines();
  1000.     else
  1001.         return !endOfCodeReached;
  1002. }
  1003.  
  1004. /**
  1005.  * check if formatting options are enabled, in addition to indentation.
  1006.  *
  1007.  * @return     are formatting options enabled?
  1008.  */
  1009. bool ASFormatter::isFormattingEnabled() const
  1010. {
  1011.     return (bracketFormatMode != NONE_MODE
  1012.             || shouldPadOperators
  1013.             || shouldConvertTabs);
  1014. }
  1015.  
  1016. /**
  1017.  * set the bracket formatting mode.
  1018.  * options:
  1019.  *    astyle::NONE_MODE     no formatting of brackets.
  1020.  *    astyle::ATTACH_MODE   Java, K&R style bracket placement.
  1021.  *    astyle::BREAK_MODE    ANSI C/C++ style bracket placement.
  1022.  *
  1023.  * @param mode         the bracket formatting mode.
  1024.  */
  1025. void ASFormatter::setBracketFormatMode(BracketMode mode)
  1026. {
  1027.     bracketFormatMode = mode;
  1028. }
  1029.  
  1030. /**
  1031.  * set closing header bracket breaking mode
  1032.  * options:
  1033.  *    true     brackets just before closing headers (e.g. 'else', 'catch')
  1034.  *             will be broken, even if standard brackets are attached.
  1035.  *    false    closing header brackets will be treated as standard brackets.
  1036.  *
  1037.  * @param mode         the closing header bracket breaking mode.
  1038.  */
  1039. void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
  1040. {
  1041.     shouldBreakClosingHeaderBrackets = state;
  1042. }
  1043.  
  1044. /**
  1045.  * set 'else if()' breaking mode
  1046.  * options:
  1047.  *    true     'else' headers will be broken from their succeeding 'if' headers.
  1048.  *    false    'else' headers will be attached to their succeeding 'if' headers.
  1049.  *
  1050.  * @param mode         the 'else if()' breaking mode.
  1051.  */
  1052. void ASFormatter::setBreakElseIfsMode(bool state)
  1053. {
  1054.     shouldBreakElseIfs = state;
  1055. }
  1056.  
  1057. /**
  1058.  * set operator padding mode.
  1059.  * options:
  1060.  *    true     statement operators will be padded with spaces around them.
  1061.  *    false    statement operators will not be padded.
  1062.  *
  1063.  * @param mode         the padding mode.
  1064.  */
  1065. void ASFormatter::setOperatorPaddingMode(bool state)
  1066. {
  1067.     shouldPadOperators = state;
  1068. }
  1069.  
  1070. /**
  1071. * set parentheies padding mode.
  1072. * options:
  1073. *    true     statement parenthesies will be padded with spaces around them.
  1074. *    false    statement parenthesies will not be padded.
  1075. *
  1076. * @param mode         the padding mode.
  1077. */
  1078. void ASFormatter::setParenthesisPaddingMode(bool state)
  1079. {
  1080.     shouldPadParenthesies = state;
  1081. }
  1082.  
  1083. /**
  1084.  * set option to break/not break one-line blocks
  1085.  *
  1086.  * @param state        true = break, false = don't break.
  1087.  */
  1088. void ASFormatter::setBreakOneLineBlocksMode(bool state)
  1089. {
  1090.     shouldBreakOneLineBlocks = state;
  1091. }
  1092.  
  1093. /**
  1094.  * set option to break/not break lines consisting of multiple statements.
  1095.  *
  1096.  * @param state        true = break, false = don't break.
  1097.  */
  1098. void ASFormatter::setSingleStatementsMode(bool state)
  1099. {
  1100.     shouldBreakOneLineStatements = state;
  1101. }
  1102.  
  1103. /**
  1104.  * set option to convert tabs to spaces.
  1105.  *
  1106.  * @param state        true = convert, false = don't convert.
  1107.  */
  1108. void ASFormatter::setTabSpaceConversionMode(bool state)
  1109. {
  1110.     shouldConvertTabs = state;
  1111. }
  1112.  
  1113.  
  1114. /**
  1115.  * set option to break unrelated blocks of code with empty lines.
  1116.  *
  1117.  * @param state        true = convert, false = don't convert.
  1118.  */
  1119. void ASFormatter::setBreakBlocksMode(bool state)
  1120. {
  1121.     shouldBreakBlocks = state;
  1122. }
  1123.  
  1124. /**
  1125.  * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
  1126.  *
  1127.  * @param state        true = convert, false = don't convert.
  1128.  */
  1129. void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
  1130. {
  1131.     shouldBreakClosingHeaderBlocks = state;
  1132. }
  1133.  
  1134. /**
  1135.  * check if a specific sequence exists in the current placement of the current line
  1136.  *
  1137.  * @return             whether sequence has been reached.
  1138.  * @param sequence     the sequence to be checked
  1139.  */
  1140. bool ASFormatter::isSequenceReached(const string &sequence) const
  1141. {
  1142.     return currentLine.COMPARE(charNum, sequence.length(), sequence) == 0;
  1143.  
  1144. }
  1145.  
  1146. /**
  1147.  * jump over several characters.
  1148.  *
  1149.  * @param i       the number of characters to jump over.
  1150.  */
  1151. void ASFormatter::goForward(int i)
  1152. {
  1153.     while (--i >= 0)
  1154.         getNextChar();
  1155. }
  1156.  
  1157. /**
  1158. * peek at the next unread character.
  1159. *
  1160. * @return     the next unread character.
  1161. */
  1162. char ASFormatter::peekNextChar() const
  1163. {
  1164.     int peekNum = charNum + 1;
  1165.     int len = currentLine.length();
  1166.     char ch = ' ';
  1167.  
  1168.     while (peekNum < len)
  1169.     {
  1170.         ch = currentLine[peekNum++];
  1171.         if (!isWhiteSpace(ch))
  1172.             return ch;
  1173.     }
  1174.  
  1175.     if (shouldConvertTabs && ch == '\t')
  1176.         ch = ' ';
  1177.  
  1178.     return ch;
  1179. }
  1180.  
  1181. /**
  1182. * check if current placement is before a comment or line-comment
  1183. *
  1184. * @return     is before a comment or line-comment.
  1185. */
  1186. bool ASFormatter::isBeforeComment() const
  1187. {
  1188.     int peekNum = charNum + 1;
  1189.     int len = currentLine.length();
  1190.     // char ch = ' ';
  1191.     bool foundComment = false;
  1192.  
  1193.     for (peekNum = charNum + 1;
  1194.             peekNum < len && isWhiteSpace(currentLine[peekNum]);
  1195.             ++peekNum)
  1196.         ;
  1197.  
  1198.     if (peekNum < len)
  1199.         foundComment = ( currentLine.COMPARE(peekNum, 2, AS_OPEN_COMMENT) == 0
  1200.                          || currentLine.COMPARE(peekNum, 2, AS_OPEN_LINE_COMMENT) == 0 );
  1201.  
  1202.     return foundComment;
  1203. }
  1204.  
  1205. /**
  1206. * get the next character, increasing the current placement in the process.
  1207. * the new character is inserted into the variable currentChar.
  1208. *
  1209. * @return   whether succeded to recieve the new character.
  1210. */
  1211. bool ASFormatter::getNextChar()
  1212. {
  1213.     isInLineBreak = false;
  1214.     bool isAfterFormattedWhiteSpace = false;
  1215.  
  1216.     if (shouldPadOperators && !isInComment && !isInLineComment
  1217.             && !isInQuote && !doesLineStartComment && !isInPreprocessor
  1218.             && !isBeforeComment())
  1219.     {
  1220.         int len = formattedLine.length();
  1221.         if (len > 0 && isWhiteSpace(formattedLine[len-1]))
  1222.             isAfterFormattedWhiteSpace = true;
  1223.     }
  1224.  
  1225.     previousChar = currentChar;
  1226.     if (!isWhiteSpace(currentChar))
  1227.     {
  1228.         previousNonWSChar = currentChar;
  1229.         if (!isInComment && !isInLineComment && !isInQuote
  1230.                 && !isSequenceReached(AS_OPEN_COMMENT)
  1231.                 && !isSequenceReached(AS_OPEN_LINE_COMMENT) )
  1232.             previousCommandChar = previousNonWSChar;
  1233.     }
  1234.  
  1235.     int currentLineLength = currentLine.length();
  1236.  
  1237.     if (charNum+1 < currentLineLength
  1238.             && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
  1239.     {
  1240.         currentChar = currentLine[++charNum];
  1241.         if (isAfterFormattedWhiteSpace)
  1242.             while (isWhiteSpace(currentChar) && charNum+1 < currentLineLength)
  1243.                 currentChar = currentLine[++charNum];
  1244.  
  1245.         if (shouldConvertTabs && currentChar == '\t')
  1246.             currentChar = ' ';
  1247.  
  1248.         return true;
  1249.     }
  1250.     else
  1251.     {
  1252.         if (sourceIterator->hasMoreLines())
  1253.         {
  1254.             currentLine = sourceIterator->nextLine();
  1255.             if (currentLine.length() == 0)
  1256.             {
  1257.                 /*think*/ currentLine = string(" ");
  1258.             }
  1259.  
  1260.             // unless reading in the first line of the file,
  1261.             // break a new line.
  1262.             if (!isVirgin)
  1263.                 isInLineBreak = true;
  1264.             else
  1265.                 isVirgin = false;
  1266.  
  1267.             if (isInLineComment)
  1268.                 isImmediatelyPostLineComment = true;
  1269.             isInLineComment = false;
  1270.  
  1271.             trimNewLine();
  1272.             currentChar = currentLine[charNum];
  1273.  
  1274.             // check if is in preprocessor right after the line break and line trimming
  1275.             if (previousNonWSChar != '\\')
  1276.                 isInPreprocessor = false;
  1277.  
  1278.             if (shouldConvertTabs && currentChar == '\t')
  1279.                 currentChar = ' ';
  1280.  
  1281.             return true;
  1282.         }
  1283.         else
  1284.         {
  1285.             endOfCodeReached = true;
  1286.             return false;
  1287.         }
  1288.     }
  1289. }
  1290.  
  1291. /**
  1292. * jump over the leading white space in the current line,
  1293. * IF the line does not begin a comment or is in a preprocessor definition.
  1294. */
  1295. void ASFormatter::trimNewLine()
  1296. {
  1297.     int len = currentLine.length();
  1298.     charNum = 0;
  1299.  
  1300.     if (isInComment || isInPreprocessor)
  1301.         return;
  1302.  
  1303.     while (isWhiteSpace(currentLine[charNum]) && charNum+1 < len)
  1304.         ++charNum;
  1305.  
  1306.     doesLineStartComment = false;
  1307.     if (isSequenceReached(string("/*")))
  1308.     {
  1309.         charNum = 0;
  1310.         doesLineStartComment = true;
  1311.     }
  1312. }
  1313.  
  1314. /**
  1315.  * append a character to the current formatted line.
  1316.  * Unless disabled (via canBreakLine == false), first check if a 
  1317.  * line-break has been registered, and if so break the 
  1318.  * formatted line, and only then append the character into
  1319.  * the next formatted line.
  1320.  *
  1321.  * @param ch               the character to append.
  1322.  * @param canBreakLine     if true, a registered line-break
  1323.  */
  1324. void ASFormatter::appendChar(char ch, bool canBreakLine)
  1325. {
  1326.     if (canBreakLine && isInLineBreak)
  1327.         breakLine();
  1328.     formattedLine.append(1, ch);
  1329. }
  1330.  
  1331. /**
  1332.  * append the CURRENT character (curentChar)to the current
  1333.  * formatted line. Unless disabled (via canBreakLine == false),
  1334.  * first check if a line-break has been registered, and if so
  1335.  * break the formatted line, and only then append the character
  1336.  * into the next formatted line.
  1337.  *
  1338.  * @param canBreakLine     if true, a registered line-break
  1339.  */
  1340. void ASFormatter::appendCurrentChar(bool canBreakLine)
  1341. {
  1342.     appendChar(currentChar, canBreakLine);
  1343. }
  1344.  
  1345. /**
  1346.  * append a string sequence to the current formatted line.
  1347.  * Unless disabled (via canBreakLine == false), first check if a 
  1348.  * line-break has been registered, and if so break the 
  1349.  * formatted line, and only then append the sequence into
  1350.  * the next formatted line.
  1351.  *
  1352.  * @param sequence         the sequence to append.
  1353.  * @param canBreakLine     if true, a registered line-break
  1354.  */
  1355. void ASFormatter::appendSequence(const string &sequence, bool canBreakLine)
  1356. {
  1357.     if (canBreakLine && isInLineBreak)
  1358.         breakLine();
  1359.     formattedLine.append(sequence);
  1360. }
  1361.  
  1362. /**
  1363.  * append a space to the current formattedline, UNLESS the 
  1364.  * last character is already a white-space character.
  1365.  */
  1366. void ASFormatter::appendSpacePad()
  1367. {
  1368.     int len = formattedLine.length();
  1369.     if (len == 0 || !isWhiteSpace(formattedLine[len-1]))
  1370.         formattedLine.append(1, ' ');
  1371. }
  1372.  
  1373. /**
  1374.  * register a line break for the formatted line.
  1375.  */
  1376. void ASFormatter::breakLine()
  1377. {
  1378.     isLineReady = true;
  1379.     isInLineBreak = false;
  1380.  
  1381.     // queue an empty line prepend request if one exists
  1382.     prependEmptyLine = isPrependPostBlockEmptyLineRequested;
  1383.  
  1384.     readyFormattedLine =  formattedLine;
  1385.     if (isAppendPostBlockEmptyLineRequested)
  1386.     {
  1387.         isAppendPostBlockEmptyLineRequested = false;
  1388.         isPrependPostBlockEmptyLineRequested = true;
  1389.     }
  1390.     else
  1391.     {
  1392.         isPrependPostBlockEmptyLineRequested = false;
  1393.     }
  1394.  
  1395.     formattedLine = "";
  1396. }
  1397.  
  1398. /**
  1399.  * check if the currently reached open-bracket (i.e. '{')
  1400.  * opens a:
  1401.  * - a definition type block (such as a class or namespace),
  1402.  * - a command block (such as a method block)
  1403.  * - a static array
  1404.  * this method takes for granted that the current character
  1405.  * is an opening bracket.
  1406.  *
  1407.  * @return    the type of the opened block.
  1408.  */
  1409. BracketType ASFormatter::getBracketType() const
  1410. {
  1411.     BracketType returnVal;
  1412.  
  1413.     if (foundPreDefinitionHeader)
  1414.         returnVal = DEFINITION_TYPE;
  1415.     else
  1416.     {
  1417.         bool isCommandType;
  1418.         isCommandType = ( foundPreCommandHeader
  1419.                           || ( currentHeader != NULL && isNonParenHeader )
  1420.                           || ( previousCommandChar == ')' )
  1421.                           || ( previousCommandChar == ':' && !foundQuestionMark )
  1422.                           || ( previousCommandChar == ';' )
  1423.                           || ( ( previousCommandChar == '{' ||  previousCommandChar == '}')
  1424.                                && isPreviousBracketBlockRelated ) );
  1425.  
  1426.         returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
  1427.     }
  1428.  
  1429.     if (isOneLineBlockReached())
  1430.         returnVal = (BracketType) (returnVal | SINGLE_LINE_TYPE);
  1431.  
  1432.     return returnVal;
  1433. }
  1434.  
  1435. /**
  1436.  * check if the currently reached  '*' or '&' character is
  1437.  * a pointer-or-reference symbol, or another operator.
  1438.  * this method takes for granted that the current character
  1439.  * is either a '*' or '&'.
  1440.  *
  1441.  * @return        whether current character is a reference-or-pointer 
  1442.  */
  1443. bool ASFormatter::isPointerOrReference() const
  1444. {
  1445.     bool isPR;
  1446.     isPR = ( !isInPotentialCalculation
  1447.              || IS_A(bracketTypeStack->back(), DEFINITION_TYPE)
  1448.              || (!isLegalNameChar(previousNonWSChar)
  1449.                  && previousNonWSChar != ')'
  1450.                  && previousNonWSChar != ']')
  1451.            );
  1452.  
  1453.     if (!isPR)
  1454.     {
  1455.         char nextChar = peekNextChar();
  1456.         isPR |= (!isWhiteSpace(nextChar)
  1457.                  && nextChar != '-'
  1458.                  && nextChar != '('
  1459.                  && nextChar != '['
  1460.                  && !isLegalNameChar(nextChar));
  1461.     }
  1462.  
  1463.     return isPR;
  1464. }
  1465.  
  1466.  
  1467. /**
  1468.  * check if the currently reached '-' character is
  1469.  * a urinary minus
  1470.  * this method takes for granted that the current character
  1471.  * is a '-'.
  1472.  *
  1473.  * @return        whether the current '-' is a urinary minus.
  1474.  */
  1475. bool ASFormatter::isUrinaryMinus() const
  1476. {
  1477.     return ( (previousOperator == &AS_RETURN || !isalnum(previousCommandChar))
  1478.              && previousCommandChar != '.'
  1479.              && previousCommandChar != ')'
  1480.              && previousCommandChar != ']' );
  1481. }
  1482.  
  1483.  
  1484. /**
  1485.  * check if the currently reached '-' or '+' character is
  1486.  * part of an exponent, i.e. 0.2E-5.
  1487.  * this method takes for granted that the current character
  1488.  * is a '-' or '+'.
  1489.  *
  1490.  * @return        whether the current '-' is in an exponent.
  1491.  */
  1492. bool ASFormatter::isInExponent() const
  1493. {
  1494.     int formattedLineLength = formattedLine.length();
  1495.     if (formattedLineLength >= 2)
  1496.     {
  1497.         char prevPrevFormattedChar = formattedLine[formattedLineLength - 2];
  1498.         char prevFormattedChar = formattedLine[formattedLineLength - 1];
  1499.  
  1500.         return ( (prevFormattedChar == 'e' || prevFormattedChar == 'E')
  1501.                  && (prevPrevFormattedChar == '.' || isdigit(prevPrevFormattedChar)) );
  1502.     }
  1503.     else
  1504.         return false;
  1505. }
  1506.  
  1507. /**
  1508.  * check if a one-line bracket has been reached,
  1509.  * i.e. if the currently reached '{' character is closed
  1510.  * with a complimentry '}' elsewhere on the current line,
  1511.  *.
  1512.  * @return        has a one-line bracket been reached?
  1513.  */
  1514. bool ASFormatter::isOneLineBlockReached() const
  1515. {
  1516.     bool isInComment = false;
  1517.     bool isInQuote = false;
  1518.     int bracketCount = 1;
  1519.     int currentLineLength = currentLine.length();
  1520.     int i = 0;
  1521.     char ch = ' ';
  1522.     char quoteChar = ' ';
  1523.  
  1524.     for (i = charNum + 1; i < currentLineLength; ++i)
  1525.     {
  1526.         ch = currentLine[i];
  1527.  
  1528.         if (isInComment)
  1529.         {
  1530.             if (currentLine.COMPARE(i, 2, "*/") == 0)
  1531.             {
  1532.                 isInComment = false;
  1533.                 ++i;
  1534.             }
  1535.             continue;
  1536.         }
  1537.  
  1538.         if (ch == '\\')
  1539.         {
  1540.             ++i;
  1541.             continue;
  1542.         }
  1543.  
  1544.         if (isInQuote)
  1545.         {
  1546.             if (ch == quoteChar)
  1547.                 isInQuote = false;
  1548.             continue;
  1549.         }
  1550.  
  1551.         if (ch == '"' || ch == '\'')
  1552.         {
  1553.             isInQuote = true;
  1554.             quoteChar = ch;
  1555.             continue;
  1556.         }
  1557.  
  1558.         if (currentLine.COMPARE(i, 2, "//") == 0)
  1559.             break;
  1560.  
  1561.         if (currentLine.COMPARE(i, 2, "/*") == 0)
  1562.         {
  1563.             isInComment = true;
  1564.             ++i;
  1565.             continue;
  1566.         }
  1567.  
  1568.         if (ch == '{')
  1569.             ++bracketCount;
  1570.         else if (ch == '}')
  1571.             --bracketCount;
  1572.  
  1573.         if(bracketCount == 0)
  1574.             return true;
  1575.     }
  1576.  
  1577.     return false;
  1578. }
  1579.  
  1580.  
  1581. /**
  1582.  * check if one of a set of headers has been reached in the
  1583.  * current position of the current line.
  1584.  *
  1585.  * @return             a pointer to the found header. Or a NULL if no header has been reached.
  1586.  * @param headers      a vector of headers
  1587.  * @param checkBoundry 
  1588.  */
  1589. const string *ASFormatter::findHeader(const vector<const string*> &headers, bool checkBoundry)
  1590. {
  1591.     return ASBeautifier::findHeader(currentLine, charNum, headers, checkBoundry);
  1592. }
  1593.  
  1594.  
  1595.  
  1596. #ifdef USES_NAMESPACE
  1597. }
  1598. #endif
  1599.  
  1600.  
  1601.