/*************************************************************************** ansigenerator.cpp - description ------------------- begin : Jul 5 2004 copyright : (C) 2004 by André Simon email : andre.simon1@gmx.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "ansigenerator.h" using namespace std; namespace highlight { string AnsiGenerator::getOpenTag(const string&font, const string&fgCol, const string&bgCol) { ostringstream s; s << "\033["< #include #include #include #include "codegenerator.h" #include "charcodes.h" #include "version.h" namespace highlight { /** \brief This class generates ANSI escape sequences. It contains information about the resulting document structure (document header and footer), the colour system, white space handling and text formatting attributes. * @author Andre Simon */ class AnsiGenerator : public highlight::CodeGenerator { public: /** Constructor \param colourTheme Name of Colour theme to use */ AnsiGenerator( const string &colourTheme); AnsiGenerator(); ~AnsiGenerator(); /** prints document header \param title Title of the document */ string getHeader(const string & title); /** Prints document footer*/ string getFooter(); /** Prints document body*/ void printBody(); private: /** \return escaped character*/ virtual string maskCharacter(unsigned char ); /** gibt ANSI-"Tags" zurueck (Farbindex+bold+kursiv)*/ string getOpenTag(const string&font, const string&fgCol, const string&bgCol=""); string getMatchingOpenTag(unsigned int styleID); string getMatchingCloseTag(unsigned int styleID); }; } #endif /* * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved. * * ASBeautifier.cpp * by Tal Davidson (davidsont@bigfoot.com) * This file is a part of "Artistic Style" - an indentater and reformatter * of C, C, C# and Java source files. * * The "Artistic Style" project, including all files needed to compile it, * is free software; you can redistribute it and/or use it and/or modify it * under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU General Public * License along with this program. * * Patches: * 18 March 1999 - Brian Rampel - * Fixed inverse insertion of spaces vs. tabs when in -t mode. * 08 may 2004 * applied ASBeautifier.cpp.BITFIELD.patch.bz2 */ #include "compiler_defines.h" #include "ASBeautifier.h" #include #include #include #include #include #define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); } #define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container) ; } #ifdef USES_NAMESPACE using namespace std; #endif #ifdef USES_NAMESPACE namespace astyle { #endif bool ASBeautifier::calledInitStatic = false; vector ASBeautifier::headers; vector ASBeautifier::nonParenHeaders; vector ASBeautifier::preBlockStatements; vector ASBeautifier::assignmentOperators; vector ASBeautifier::nonAssignmentOperators; /* * initialize the static vars */ void ASBeautifier::initStatic() { if (calledInitStatic) return; calledInitStatic = true; headers.push_back(&AS_IF); headers.push_back(&AS_ELSE); headers.push_back(&AS_FOR); headers.push_back(&AS_WHILE); headers.push_back(&AS_DO); headers.push_back(&AS_TRY); headers.push_back(&AS_CATCH); headers.push_back(&AS_FINALLY); headers.push_back(&AS_SYNCHRONIZED); headers.push_back(&AS_SWITCH); headers.push_back(&AS_CASE); headers.push_back(&AS_DEFAULT); headers.push_back(&AS_FOREACH); headers.push_back(&AS_LOCK); headers.push_back(&AS_UNSAFE); headers.push_back(&AS_FIXED); headers.push_back(&AS_GET); headers.push_back(&AS_SET); headers.push_back(&AS_ADD); headers.push_back(&AS_REMOVE); //headers.push_back(&AS_PUBLIC); //headers.push_back(&AS_PRIVATE); //headers.push_back(&AS_PROTECTED); //headers.push_back(&AS_OPERATOR); headers.push_back(&AS_TEMPLATE); headers.push_back(&AS_CONST); /**/ headers.push_back(&AS_STATIC); headers.push_back(&AS_EXTERN); nonParenHeaders.push_back(&AS_ELSE); nonParenHeaders.push_back(&AS_DO); nonParenHeaders.push_back(&AS_TRY); nonParenHeaders.push_back(&AS_FINALLY); nonParenHeaders.push_back(&AS_STATIC); nonParenHeaders.push_back(&AS_CONST); nonParenHeaders.push_back(&AS_EXTERN); nonParenHeaders.push_back(&AS_CASE); nonParenHeaders.push_back(&AS_DEFAULT); nonParenHeaders.push_back(&AS_UNSAFE); nonParenHeaders.push_back(&AS_GET); nonParenHeaders.push_back(&AS_SET); nonParenHeaders.push_back(&AS_ADD); nonParenHeaders.push_back(&AS_REMOVE); nonParenHeaders.push_back(&AS_PUBLIC); nonParenHeaders.push_back(&AS_PRIVATE); nonParenHeaders.push_back(&AS_PROTECTED); nonParenHeaders.push_back(&AS_TEMPLATE); nonParenHeaders.push_back(&AS_CONST); /// nonParenHeaders.push_back(&AS_ASM); preBlockStatements.push_back(&AS_CLASS); preBlockStatements.push_back(&AS_STRUCT); preBlockStatements.push_back(&AS_UNION); preBlockStatements.push_back(&AS_INTERFACE); preBlockStatements.push_back(&AS_NAMESPACE); preBlockStatements.push_back(&AS_THROWS); preBlockStatements.push_back(&AS_EXTERN); assignmentOperators.push_back(&AS_ASSIGN); assignmentOperators.push_back(&AS_PLUS_ASSIGN); assignmentOperators.push_back(&AS_MINUS_ASSIGN); assignmentOperators.push_back(&AS_MULT_ASSIGN); assignmentOperators.push_back(&AS_DIV_ASSIGN); assignmentOperators.push_back(&AS_MOD_ASSIGN); assignmentOperators.push_back(&AS_OR_ASSIGN); assignmentOperators.push_back(&AS_AND_ASSIGN); assignmentOperators.push_back(&AS_XOR_ASSIGN); assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN); assignmentOperators.push_back(&AS_GR_GR_ASSIGN); assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN); assignmentOperators.push_back(&AS_LS_LS_ASSIGN); assignmentOperators.push_back(&AS_RETURN); nonAssignmentOperators.push_back(&AS_EQUAL); nonAssignmentOperators.push_back(&AS_PLUS_PLUS); nonAssignmentOperators.push_back(&AS_MINUS_MINUS); nonAssignmentOperators.push_back(&AS_NOT_EQUAL); nonAssignmentOperators.push_back(&AS_GR_EQUAL); nonAssignmentOperators.push_back(&AS_GR_GR_GR); nonAssignmentOperators.push_back(&AS_GR_GR); nonAssignmentOperators.push_back(&AS_LS_EQUAL); nonAssignmentOperators.push_back(&AS_LS_LS_LS); nonAssignmentOperators.push_back(&AS_LS_LS); nonAssignmentOperators.push_back(&AS_ARROW); nonAssignmentOperators.push_back(&AS_AND); nonAssignmentOperators.push_back(&AS_OR); } /** * ASBeautifier's constructor */ ASBeautifier::ASBeautifier() { initStatic(); waitingBeautifierStack = NULL; activeBeautifierStack = NULL; waitingBeautifierStackLengthStack = NULL; activeBeautifierStackLengthStack = NULL; headerStack = NULL; tempStacks = NULL; blockParenDepthStack = NULL; blockStatementStack = NULL; parenStatementStack = NULL; bracketBlockStateStack = NULL; inStatementIndentStack = NULL; inStatementIndentStackSizeStack = NULL; parenIndentStack = NULL; sourceIterator = NULL; isMinimalConditinalIndentSet = false; shouldForceTabIndentation = false; setSpaceIndentation(4); setMaxInStatementIndentLength(40); setClassIndent(false); setSwitchIndent(false); setCaseIndent(false); setBlockIndent(false); setBracketIndent(false); setNamespaceIndent(false); setLabelIndent(false); setEmptyLineFill(false); setCStyle(); setPreprocessorIndent(false); } ASBeautifier::ASBeautifier(const ASBeautifier &other) { waitingBeautifierStack = NULL; activeBeautifierStack = NULL; waitingBeautifierStackLengthStack = NULL; activeBeautifierStackLengthStack = NULL; headerStack = new vector; *headerStack = *other.headerStack; tempStacks = new vector< vector* >; vector< vector* >::iterator iter; for (iter = other.tempStacks->begin(); iter != other.tempStacks->end(); ++iter) { vector *newVec = new vector; *newVec = **iter; tempStacks->push_back(newVec); } blockParenDepthStack = new vector; *blockParenDepthStack = *other.blockParenDepthStack; blockStatementStack = new vector; *blockStatementStack = *other.blockStatementStack; parenStatementStack = new vector; *parenStatementStack = *other.parenStatementStack; bracketBlockStateStack = new vector; *bracketBlockStateStack = *other.bracketBlockStateStack; inStatementIndentStack = new vector; *inStatementIndentStack = *other.inStatementIndentStack; inStatementIndentStackSizeStack = new vector; *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack; parenIndentStack = new vector; *parenIndentStack = *other.parenIndentStack; sourceIterator = other.sourceIterator; indentString = other.indentString; currentHeader = other.currentHeader; previousLastLineHeader = other.previousLastLineHeader; immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp; isInQuote = other.isInQuote; isInComment = other.isInComment; isInCase = other.isInCase; isInQuestion = other.isInQuestion; isInStatement =other. isInStatement; isInHeader = other.isInHeader; isCStyle = other.isCStyle; isInOperator = other.isInOperator; isInTemplate = other.isInTemplate; isInConst = other.isInConst; classIndent = other.classIndent; isInClassHeader = other.isInClassHeader; isInClassHeaderTab = other.isInClassHeaderTab; switchIndent = other.switchIndent; caseIndent = other.caseIndent; namespaceIndent = other.namespaceIndent; bracketIndent = other.bracketIndent; blockIndent = other.blockIndent; labelIndent = other.labelIndent; preprocessorIndent = other.preprocessorIndent; parenDepth = other.parenDepth; indentLength = other.indentLength; blockTabCount = other.blockTabCount; leadingWhiteSpaces = other.leadingWhiteSpaces; maxInStatementIndent = other.maxInStatementIndent; templateDepth = other.templateDepth; quoteChar = other.quoteChar; prevNonSpaceCh = other.prevNonSpaceCh; currentNonSpaceCh = other.currentNonSpaceCh; currentNonLegalCh = other.currentNonLegalCh; prevNonLegalCh = other.prevNonLegalCh; isInConditional = other.isInConditional; minConditionalIndent = other.minConditionalIndent; prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount; prevFinalLineTabCount = other.prevFinalLineTabCount; emptyLineFill = other.emptyLineFill; probationHeader = other.probationHeader; isInDefine = other.isInDefine; isInDefineDefinition = other.isInDefineDefinition; backslashEndsPrevLine = other.backslashEndsPrevLine; defineTabCount = other.defineTabCount; } /** * ASBeautifier's destructor */ ASBeautifier::~ASBeautifier() { DELETE_CONTAINER( headerStack ); DELETE_CONTAINER( tempStacks ); DELETE_CONTAINER( blockParenDepthStack ); DELETE_CONTAINER( blockStatementStack ); DELETE_CONTAINER( parenStatementStack ); DELETE_CONTAINER( bracketBlockStateStack ); DELETE_CONTAINER( inStatementIndentStack ); DELETE_CONTAINER( inStatementIndentStackSizeStack ); DELETE_CONTAINER( parenIndentStack ); // DELETE_CONTAINER( sourceIterator ); } /** * initialize the ASBeautifier. * * init() should be called every time a ABeautifier object is to start * beautifying a NEW source file. * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object * that will be used to iterate through the source code. This object will be * deleted during the ASBeautifier's destruction, and thus should not be * deleted elsewhere. * * @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object. */ void ASBeautifier::init(ASSourceIterator *iter) { sourceIterator = iter; init(); } /** * initialize the ASBeautifier. */ void ASBeautifier::init() { INIT_CONTAINER( waitingBeautifierStack, new vector ); INIT_CONTAINER( activeBeautifierStack, new vector ); INIT_CONTAINER( waitingBeautifierStackLengthStack, new vector ); INIT_CONTAINER( activeBeautifierStackLengthStack, new vector ); INIT_CONTAINER( headerStack, new vector ); INIT_CONTAINER( tempStacks, new vector< vector* > ); tempStacks->push_back(new vector); INIT_CONTAINER( blockParenDepthStack, new vector ); INIT_CONTAINER( blockStatementStack, new vector ); INIT_CONTAINER( parenStatementStack, new vector ); INIT_CONTAINER( bracketBlockStateStack, new vector ); bracketBlockStateStack->push_back(true); INIT_CONTAINER( inStatementIndentStack, new vector ); INIT_CONTAINER( inStatementIndentStackSizeStack, new vector ); inStatementIndentStackSizeStack->push_back(0); INIT_CONTAINER( parenIndentStack, new vector ); immediatelyPreviousAssignmentOp = NULL; previousLastLineHeader = NULL; isInQuote = false; isInComment = false; isInStatement = false; isInCase = false; isInQuestion = false; isInClassHeader = false; isInClassHeaderTab = false; isInHeader = false; isInOperator = false; isInTemplate = false; isInConst = false; isInConditional = false; templateDepth = 0; parenDepth=0; blockTabCount = 0; leadingWhiteSpaces = 0; prevNonSpaceCh = '{'; currentNonSpaceCh = '{'; prevNonLegalCh = '{'; currentNonLegalCh = '{'; prevFinalLineSpaceTabCount = 0; prevFinalLineTabCount = 0; probationHeader = NULL; backslashEndsPrevLine = false; isInDefine = false; isInDefineDefinition = false; defineTabCount = 0; } /** * set indentation style to ANSI C/C++. */ void ASBeautifier::setCStyle() { isCStyle = true; } /** * set indentation style to Java / K&R. */ void ASBeautifier::setJavaStyle() { isCStyle = false; } /** * indent using one tab per indentation */ void ASBeautifier::setTabIndentation(int length, bool forceTabs) { indentString = "\t"; indentLength = length; shouldForceTabIndentation = forceTabs; if (!isMinimalConditinalIndentSet) minConditionalIndent = indentLength * 2; } /** * indent using a number of spaces per indentation. * * @param length number of spaces per indent. */ void ASBeautifier::setSpaceIndentation(int length) { indentString=string(length, ' '); indentLength = length; if (!isMinimalConditinalIndentSet) minConditionalIndent = indentLength * 2; } /** * set the maximum indentation between two lines in a multi-line statement. * * @param max maximum indentation length. */ void ASBeautifier::setMaxInStatementIndentLength(int max) { maxInStatementIndent = max; } /** * set the minimum indentation between two lines in a multi-line condition. * * @param min minimal indentation length. */ void ASBeautifier::setMinConditionalIndentLength(int min) { minConditionalIndent = min; isMinimalConditinalIndentSet = true; } /** * set the state of the bracket indentation option. If true, brackets will * be indented one additional indent. * * @param state state of option. */ void ASBeautifier::setBracketIndent(bool state) { bracketIndent = state; } /** * set the state of the block indentation option. If true, entire blocks * will be indented one additional indent, similar to the GNU indent style. * * @param state state of option. */ void ASBeautifier::setBlockIndent(bool state) { if (state) setBracketIndent(false); // so that we don't have both bracket and block indent blockIndent = state; } /** * set the state of the class indentation option. If true, C++ class * definitions will be indented one additional indent. * * @param state state of option. */ void ASBeautifier::setClassIndent(bool state) { classIndent = state; } /** * set the state of the switch indentation option. If true, blocks of 'switch' * statements will be indented one additional indent. * * @param state state of option. */ void ASBeautifier::setSwitchIndent(bool state) { switchIndent = state; } /** * set the state of the case indentation option. If true, lines of 'case' * statements will be indented one additional indent. * * @param state state of option. */ void ASBeautifier::setCaseIndent(bool state) { caseIndent = state; } /** * set the state of the namespace indentation option. * If true, blocks of 'namespace' statements will be indented one * additional indent. Otherwise, NO indentation will be added. * * @param state state of option. */ void ASBeautifier::setNamespaceIndent(bool state) { namespaceIndent = state; } /** * set the state of the label indentation option. * If true, labels will be indented one indent LESS than the * current indentation level. * If false, labels will be flushed to the left with NO * indent at all. * * @param state state of option. */ void ASBeautifier::setLabelIndent(bool state) { labelIndent = state; } /** * set the state of the preprocessor indentation option. * If true, multiline #define statements will be indented. * * @param state state of option. */ void ASBeautifier::setPreprocessorIndent(bool state) { preprocessorIndent = state; } /** * set the state of the empty line fill option. * If true, empty lines will be filled with the whitespace. * of their previous lines. * If false, these lines will remain empty. * * @param state state of option. */ void ASBeautifier::setEmptyLineFill(bool state) { emptyLineFill = state; } /** * check if there are any indented lines ready to be read by nextLine() * * @return are there any indented lines ready? */ bool ASBeautifier::hasMoreLines() const { return sourceIterator->hasMoreLines(); } /** * get the next indented line. * * @return indented line. */ string ASBeautifier::nextLine() { return beautify(sourceIterator->nextLine()); } /** * beautify a line of source code. * every line of source code in a source code file should be sent * one after the other to the beautify method. * * @return the indented line. * @param originalLine the original unindented line. */ string ASBeautifier::beautify(const string &originalLine) { string line; bool isInLineComment = false; bool lineStartsInComment = false; bool isInClass = false; bool isInSwitch = false; bool isImmediatelyAfterConst = false; bool isSpecialChar = false; char ch = ' '; char prevCh; string outBuffer; // the newly idented line is bufferd here int tabCount = 0; const string *lastLineHeader = NULL; bool closingBracketReached = false; int spaceTabCount = 0; char tempCh; unsigned int headerStackSize = headerStack->size(); //bool isLineInStatement = isInStatement; bool shouldIndentBrackettedLine = true; int lineOpeningBlocksNum = 0; int lineClosingBlocksNum = 0; bool previousLineProbation = (probationHeader != NULL); unsigned int i; currentHeader = NULL; lineStartsInComment = isInComment; // handle and remove white spaces around the line: // If not in comment, first find out size of white space before line, // so that possible comments starting in the line continue in // relation to the preliminary white-space. if (!isInComment) { leadingWhiteSpaces = 0; while (leadingWhiteSpacesinit(); //defineBeautifier->isInDefineDefinition = true; //defineBeautifier->beautify(""); activeBeautifierStack->push_back(defineBeautifier); } else { // the is the cloned beautifier that is in charge of indenting the #define. isInDefine = true; } } else if (preproc.COMPARE(0, 2, string("if")) == 0) { // push a new beautifier into the stack waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size()); activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size()); waitingBeautifierStack->push_back(new ASBeautifier(*this)); } else if (preproc.COMPARE(0, 4/*2*/, string("else")) == 0) { if (!waitingBeautifierStack->empty()) { // MOVE current waiting beautifier to active stack. activeBeautifierStack->push_back(waitingBeautifierStack->back()); waitingBeautifierStack->pop_back(); } } else if (preproc.COMPARE(0, 4, string("elif")) == 0) { if (!waitingBeautifierStack->empty()) { // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original. activeBeautifierStack->push_back( new ASBeautifier( *(waitingBeautifierStack->back()) ) ); } } else if (preproc.COMPARE(0, 5, string("endif")) == 0) { unsigned int stackLength; ASBeautifier *beautifier; if (!waitingBeautifierStackLengthStack->empty()) { stackLength = waitingBeautifierStackLengthStack->back(); waitingBeautifierStackLengthStack->pop_back(); while (waitingBeautifierStack->size() > stackLength) { beautifier = waitingBeautifierStack->back(); waitingBeautifierStack->pop_back(); delete beautifier; } } if (!activeBeautifierStackLengthStack->empty()) { stackLength = activeBeautifierStackLengthStack->back(); activeBeautifierStackLengthStack->pop_back(); while (activeBeautifierStack->size() > stackLength) { beautifier = activeBeautifierStack->back(); activeBeautifierStack->pop_back(); delete beautifier; } } } } // check if the last char is a backslash if(line.length() > 0) backslashEndsPrevLine = (line[line.length() - 1] == '\\'); else backslashEndsPrevLine = false; // check if this line ends a multi-line #define // if so, use the #define's cloned beautifier for the line's indentation // and then remove it from the active beautifier stack and delete it. if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine) { string beautifiedLine; ASBeautifier *defineBeautifier; isInDefineDefinition = false; defineBeautifier = activeBeautifierStack->back(); activeBeautifierStack->pop_back(); beautifiedLine = defineBeautifier->beautify(line); delete defineBeautifier; return beautifiedLine; } // unless this is a multi-line #define, return this precompiler line as is. if (!isInDefine && !isInDefineDefinition) return originalLine; } // if there exists any worker beautifier in the activeBeautifierStack, // then use it instead of me to indent the current line. if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty()) { return activeBeautifierStack->back()->beautify(line); } // calculate preliminary indentation based on data from past lines if (!inStatementIndentStack->empty()) spaceTabCount = inStatementIndentStack->back(); for (i=0; i0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET && (*headerStack)[i] == &AS_OPEN_BRACKET))) ++tabCount; if (isCStyle && !namespaceIndent && i >= 1 && (*headerStack)[i-1] == &AS_NAMESPACE && (*headerStack)[i] == &AS_OPEN_BRACKET) --tabCount; if (isCStyle && i >= 1 && (*headerStack)[i-1] == &AS_CLASS && (*headerStack)[i] == &AS_OPEN_BRACKET ) { if (classIndent) ++tabCount; isInClass = true; } // is the switchIndent option is on, indent switch statements an additional indent. else if (switchIndent && i > 1 && (*headerStack)[i-1] == &AS_SWITCH && (*headerStack)[i] == &AS_OPEN_BRACKET ) { ++tabCount; isInSwitch = true; } } if (!lineStartsInComment && isCStyle && isInClass && classIndent && headerStackSize >= 2 &&(*headerStack)[headerStackSize-2] == &AS_CLASS && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET && line[0] == '}') --tabCount; else if (!lineStartsInComment && isInSwitch && switchIndent && headerStackSize >= 2 && (*headerStack)[headerStackSize-2] == &AS_SWITCH && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET && line[0] == '}') --tabCount; if (isInClassHeader) { isInClassHeaderTab = true; tabCount += 2; } if (isInConditional) { --tabCount; } // parse characters in the current line. for (i=0; ipush_back(probationHeader); // handle the specific probation header isInConditional = (probationHeader == &AS_SYNCHRONIZED); if (probationHeader == &AS_CONST) isImmediatelyAfterConst = true; // isInConst = true; /* TODO: * There is actually no more need for the global isInConst variable. * The only reason for checking const is to see if there is a const * immediately before an open-bracket. * Since CONST is now put into probation and is checked during itspost-char, * isImmediatelyAfterConst can be set by its own... */ isInStatement = false; // if the probation comes from the previous line, then indent by 1 tab count. if (previousLineProbation && ch == '{') tabCount++; previousLineProbation = false; } // dismiss the probation header probationHeader = NULL; } prevNonSpaceCh = currentNonSpaceCh; currentNonSpaceCh = ch; if (!isLegalNameChar(ch) && ch != ',' && ch != ';' ) { prevNonLegalCh = currentNonLegalCh; currentNonLegalCh = ch; } //if (isInConst) //{ // isInConst = false; // isImmediatelyAfterConst = true; //} if (isInHeader) { isInHeader = false; currentHeader = headerStack->back(); } else currentHeader = NULL; if (isCStyle && isInTemplate && (ch == '<' || ch == '>') && findHeader(line, i, nonAssignmentOperators) == NULL) //; { if (ch == '<') { ++templateDepth; } else if (ch == '>') { if (--templateDepth <= 0) { if (isInTemplate) ch = ';'; else ch = 't'; isInTemplate = false; templateDepth = 0; } } } // handle parenthesies if (ch == '(' || ch == '[' || ch == ')' || ch == ']') { if (ch == '(' || ch == '[') { if (parenDepth == 0) { parenStatementStack->push_back(isInStatement); isInStatement = true; } parenDepth++; inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); if (currentHeader != NULL) registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true); else registerInStatementIndent(line, i, spaceTabCount, 0, true); } else if (ch == ')' || ch == ']') { parenDepth--; if (parenDepth == 0) { isInStatement = parenStatementStack->back(); parenStatementStack->pop_back(); ch = ' '; isInConditional = false; } if (!inStatementIndentStackSizeStack->empty()) { unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back(); inStatementIndentStackSizeStack->pop_back(); while (previousIndentStackSize < inStatementIndentStack->size()) inStatementIndentStack->pop_back(); if (!parenIndentStack->empty()) { int poppedIndent = parenIndentStack->back(); parenIndentStack->pop_back(); if (i == 0) spaceTabCount = poppedIndent; } } } continue; } if (ch == '{') { bool isBlockOpener = false; // first, check if '{' is a block-opener or an static-array opener isBlockOpener = ( (prevNonSpaceCh == '{' && bracketBlockStateStack->back()) || prevNonSpaceCh == '}' || prevNonSpaceCh == ')' || prevNonSpaceCh == ';' || isInClassHeader || isBlockOpener || isImmediatelyAfterConst || (isInDefine && (prevNonSpaceCh == '(' || prevNonSpaceCh == '_' || isalnum(prevNonSpaceCh))) ); isInClassHeader = false; if (!isBlockOpener && currentHeader != NULL) { for (unsigned int n=0; n < nonParenHeaders.size(); n++) if (currentHeader == nonParenHeaders[n]) { isBlockOpener = true; break; } } bracketBlockStateStack->push_back(isBlockOpener); if (!isBlockOpener) { inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); registerInStatementIndent(line, i, spaceTabCount, 0, true); parenDepth++; if (i == 0) shouldIndentBrackettedLine = false; continue; } // this bracket is a block opener... ++lineOpeningBlocksNum; if (isInClassHeader) isInClassHeader = false; if (isInClassHeaderTab) { isInClassHeaderTab = false; tabCount -= 2; } blockParenDepthStack->push_back(parenDepth); blockStatementStack->push_back(isInStatement); inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); blockTabCount += isInStatement? 1 : 0; parenDepth = 0; isInStatement = false; tempStacks->push_back(new vector); headerStack->push_back(&AS_OPEN_BRACKET); lastLineHeader = &AS_OPEN_BRACKET; // <------ continue; } //check if a header has been reached if (prevCh == ' ') { bool isIndentableHeader = true; const string *newHeader = findHeader(line, i, headers); if (newHeader != NULL) { // if we reached here, then this is a header... isInHeader = true; vector *lastTempStack; if (tempStacks->empty()) lastTempStack = NULL; else lastTempStack = tempStacks->back(); // if a new block is opened, push a new stack into tempStacks to hold the // future list of headers in the new block. // take care of the special case: 'else if (...)' if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE) { //spaceTabCount += indentLength; // to counter the opposite addition that occurs when the 'if' is registered below... headerStack->pop_back(); } // take care of 'else' else if (newHeader == &AS_ELSE) { if (lastTempStack != NULL) { int indexOfIf = indexOf(*lastTempStack, &AS_IF); // <--- if (indexOfIf != -1) { // recreate the header list in headerStack up to the previous 'if' // from the temporary snapshot stored in lastTempStack. int restackSize = lastTempStack->size() - indexOfIf - 1; for (int r=0; rpush_back(lastTempStack->back()); lastTempStack->pop_back(); } if (!closingBracketReached) tabCount += restackSize; } /* * If the above if is not true, i.e. no 'if' before the 'else', * then nothing beautiful will come out of this... * I should think about inserting an Exception here to notify the caller of this... */ } } // check if 'while' closes a previous 'do' else if (newHeader == &AS_WHILE) { if (lastTempStack != NULL) { int indexOfDo = indexOf(*lastTempStack, &AS_DO); // <--- if (indexOfDo != -1) { // recreate the header list in headerStack up to the previous 'do' // from the temporary snapshot stored in lastTempStack. int restackSize = lastTempStack->size() - indexOfDo - 1; for (int r=0; rpush_back(lastTempStack->back()); lastTempStack->pop_back(); } if (!closingBracketReached) tabCount += restackSize; } } } // check if 'catch' closes a previous 'try' or 'catch' else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY) { if (lastTempStack != NULL) { int indexOfTry = indexOf(*lastTempStack, &AS_TRY); if (indexOfTry == -1) indexOfTry = indexOf(*lastTempStack, &AS_CATCH); if (indexOfTry != -1) { // recreate the header list in headerStack up to the previous 'try' // from the temporary snapshot stored in lastTempStack. int restackSize = lastTempStack->size() - indexOfTry - 1; for (int r=0; rpush_back(lastTempStack->back()); lastTempStack->pop_back(); } if (!closingBracketReached) tabCount += restackSize; } } } else if (newHeader == &AS_CASE) { isInCase = true; if (!caseIndent) --tabCount; } else if(newHeader == &AS_DEFAULT) { isInCase = true; if (!caseIndent) --tabCount; } else if (newHeader == &AS_PUBLIC || newHeader == &AS_PROTECTED || newHeader == &AS_PRIVATE) { if (isCStyle && !isInClassHeader) --tabCount; isIndentableHeader = false; } //else if ((newHeader == &STATIC || newHeader == &SYNCHRONIZED) && // !headerStack->empty() && // (headerStack->back() == &STATIC || headerStack->back() == &SYNCHRONIZED)) //{ // isIndentableHeader = false; //} else if (newHeader == &AS_STATIC || newHeader == &AS_SYNCHRONIZED || (newHeader == &AS_CONST && isCStyle)) { if (!headerStack->empty() && (headerStack->back() == &AS_STATIC || headerStack->back() == &AS_SYNCHRONIZED || headerStack->back() == &AS_CONST)) { isIndentableHeader = false; } else { isIndentableHeader = false; probationHeader = newHeader; } } else if (newHeader == &AS_CONST) { // this will be entered only if NOT in C style // since otherwise the CONST would be found to be a probstion header... //if (isCStyle) // isInConst = true; isIndentableHeader = false; } /* else if (newHeader == &OPERATOR) { if (isCStyle) isInOperator = true; isIndentableHeader = false; } */ else if (newHeader == &AS_TEMPLATE) { if (isCStyle) isInTemplate = true; isIndentableHeader = false; } if (isIndentableHeader) { // 3.2.99 //spaceTabCount-=indentLength; headerStack->push_back(newHeader); isInStatement = false; if (indexOf(nonParenHeaders, newHeader) == -1) { isInConditional = true; } lastLineHeader = newHeader; } else isInHeader = false; //lastLineHeader = newHeader; outBuffer.append(newHeader->substr(1)); i += newHeader->length() - 1; continue; } } if (isCStyle && !isalpha(prevCh) && line.COMPARE(i, 8, AS_OPERATOR) == 0 && !isalnum(line[i+8])) { isInOperator = true; outBuffer.append(AS_OPERATOR.substr(1)); i += 7; continue; } if (ch == '?') isInQuestion = true; // special handling of 'case' statements if (ch == ':') { if (line.length() > i+1 && line[i+1] == ':') // look for :: { ++i; outBuffer.append(1, ':'); ch = ' '; continue; } else if (isCStyle && isInClass && prevNonSpaceCh != ')') { // BEGIN Content of ASBeautifier.cpp.BITFIELD.patch: unsigned int chIndex; char nextCh = 0; for (chIndex = i+1; chIndex < line.length(); chIndex++) if (!isWhiteSpace(line[chIndex])) break; if (chIndex< line.length()) nextCh = line[chIndex]; int nWord =0; for (chIndex = 0; chIndex < i; chIndex++) { if (!isWhiteSpace(line[chIndex])) { nWord ++; while (!isWhiteSpace(line[++chIndex])); } } if ((nextCh >= '0' && nextCh <= '9') || (nWord >1)) continue; // END Content of ASBeautifier.cpp.BITFIELD.patch: --tabCount; // found a 'private:' or 'public:' inside a class definition // so do nothing special } else if (isCStyle && isInClassHeader) { // found a 'class A : public B' definition // so do nothing special } else if (isInQuestion) { isInQuestion = false; } else if (isCStyle && prevNonSpaceCh == ')') { isInClassHeader = true; if (i==0) tabCount += 2; } else { currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers if (isInCase) { isInCase = false; ch = ';'; // from here on, treat char as ';' } // BEGIN content of ASBeautifier.cpp.BITFIELD.patch.bz2 else // bitfield or labels { unsigned int chIndex; char nextCh = 0; for (chIndex = i+1; (isCStyle && chIndex < line.length()); chIndex++) if (!isWhiteSpace(line[chIndex])) break; if (chIndex< line.length()) nextCh = line[chIndex]; int nWord =0; for (chIndex = 0; chIndex < i; chIndex++) { if (!isWhiteSpace(line[chIndex])) { nWord ++; while (!isWhiteSpace(line[++chIndex])); } } if (isCStyle && (nextCh >= '0' && nextCh <= '9') || (nWord >1)) { continue; } // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2 else // is in a label (e.g. 'label1:') { if (labelIndent) --tabCount; // unindent label by one indent else tabCount = 0; // completely flush indent to left } // BEGIN content of ASASBeautifier.cpp.BITFIELD.patch.bz2 } // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2 } } if ((ch == ';' || (parenDepth>0 && ch == ',')) && !inStatementIndentStackSizeStack->empty()) while ((unsigned int)inStatementIndentStackSizeStack->back() + (parenDepth>0 ? 1 : 0) < inStatementIndentStack->size()) inStatementIndentStack->pop_back(); // handle ends of statements if ( (ch == ';' && parenDepth == 0) || ch == '}'/* || (ch == ',' && parenDepth == 0)*/) { if (ch == '}') { // first check if this '}' closes a previous block, or a static array... if (!bracketBlockStateStack->empty()) { bool bracketBlockState = bracketBlockStateStack->back(); bracketBlockStateStack->pop_back(); if (!bracketBlockState) { if (!inStatementIndentStackSizeStack->empty()) { // this bracket is a static array unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back(); inStatementIndentStackSizeStack->pop_back(); while (previousIndentStackSize < inStatementIndentStack->size()) inStatementIndentStack->pop_back(); parenDepth--; if (i == 0) shouldIndentBrackettedLine = false; if (!parenIndentStack->empty()) { int poppedIndent = parenIndentStack->back(); parenIndentStack->pop_back(); if (i == 0) spaceTabCount = poppedIndent; } } continue; } } // this bracket is block closer... ++lineClosingBlocksNum; if(!inStatementIndentStackSizeStack->empty()) inStatementIndentStackSizeStack->pop_back(); if (!blockParenDepthStack->empty()) { parenDepth = blockParenDepthStack->back(); blockParenDepthStack->pop_back(); isInStatement = blockStatementStack->back(); blockStatementStack->pop_back(); if (isInStatement) blockTabCount--; } closingBracketReached = true; int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET); // <--- if (headerPlace != -1) { const string *popped = headerStack->back(); while (popped != &AS_OPEN_BRACKET) { headerStack->pop_back(); popped = headerStack->back(); } headerStack->pop_back(); if (!tempStacks->empty()) { vector *temp = tempStacks->back(); tempStacks->pop_back(); delete temp; } } ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified... } /* * Create a temporary snapshot of the current block's header-list in the * uppermost inner stack in tempStacks, and clear the headerStack up to * the begining of the block. * Thus, the next future statement will think it comes one indent past * the block's '{' unless it specifically checks for a companion-header * (such as a previous 'if' for an 'else' header) within the tempStacks, * and recreates the temporary snapshot by manipulating the tempStacks. */ if (!tempStacks->back()->empty()) while (!tempStacks->back()->empty()) tempStacks->back()->pop_back(); while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET) { tempStacks->back()->push_back(headerStack->back()); headerStack->pop_back(); } if (parenDepth == 0 && ch == ';') isInStatement=false; isInClassHeader = false; continue; } // check for preBlockStatements ONLY if not within parenthesies // (otherwise 'struct XXX' statements would be wrongly interpreted...) if (prevCh == ' ' && !isInTemplate && parenDepth == 0) { const string *newHeader = findHeader(line, i, preBlockStatements); if (newHeader != NULL) { isInClassHeader = true; outBuffer.append(newHeader->substr(1)); i += newHeader->length() - 1; //if (isCStyle) headerStack->push_back(newHeader); } } // Handle operators // //// // PRECHECK if a '==' or '--' or '++' operator was reached. //// // If not, then register an indent IF an assignment operator was reached. //// // The precheck is important, so that statements such as 'i--==2' are not recognized //// // to have assignment operators (here, '-=') in them . . . const string *foundAssignmentOp = NULL; const string *foundNonAssignmentOp = NULL; immediatelyPreviousAssignmentOp = NULL; // Check if an operator has been reached. foundAssignmentOp = findHeader(line, i, assignmentOperators, false); foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false); // Since findHeader's boundry checking was not used above, it is possible // that both an assignment op and a non-assignment op where found, // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the // found operator. if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL) if (foundAssignmentOp->length() < foundNonAssignmentOp->length()) foundAssignmentOp = NULL; else foundNonAssignmentOp = NULL; if (foundNonAssignmentOp != NULL) { if (foundNonAssignmentOp->length() > 1) { outBuffer.append(foundNonAssignmentOp->substr(1)); i += foundNonAssignmentOp->length() - 1; } } else if (foundAssignmentOp != NULL) { if (foundAssignmentOp->length() > 1) { outBuffer.append(foundAssignmentOp->substr(1)); i += foundAssignmentOp->length() - 1; } if (!isInOperator && !isInTemplate) { registerInStatementIndent(line, i, spaceTabCount, 0, false); immediatelyPreviousAssignmentOp = foundAssignmentOp; isInStatement = true; } } /* immediatelyPreviousAssignmentOp = NULL; bool isNonAssingmentOperator = false; for (int n = 0; n < nonAssignmentOperators.size(); n++) if (line.COMPARE(i, nonAssignmentOperators[n]->length(), *(nonAssignmentOperators[n])) == 0) { if (nonAssignmentOperators[n]->length() > 1) { outBuffer.append(nonAssignmentOperators[n]->substr(1)); i += nonAssignmentOperators[n]->length() - 1; } isNonAssingmentOperator = true; break; } if (!isNonAssingmentOperator) { for (int a = 0; a < assignmentOperators.size(); a++) if (line.COMPARE(i, assignmentOperators[a]->length(), *(assignmentOperators[a])) == 0) { if (assignmentOperators[a]->length() > 1) { outBuffer.append(assignmentOperators[a]->substr(1)); i += assignmentOperators[a]->length() - 1; } if (!isInOperator && !isInTemplate) { registerInStatementIndent(line, i, spaceTabCount, 0, false); immediatelyPreviousAssignmentOp = assignmentOperators[a]; isInStatement = true; } break; } } */ if (isInOperator) isInOperator = false; } // handle special cases of unindentation: /* * if '{' doesn't follow an immediately previous '{' in the headerStack * (but rather another header such as "for" or "if", then unindent it * by one indentation relative to its block. */ // cerr << endl << lineOpeningBlocksNum << " " << lineClosingBlocksNum << " " << previousLastLineHeader << endl; // indent #define lines with one less tab //if (isInDefine) // tabCount -= defineTabCount-1; if (!lineStartsInComment && !blockIndent && outBuffer.length()>0 && outBuffer[0]=='{' && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum) && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET) && shouldIndentBrackettedLine) --tabCount; else if (!lineStartsInComment && outBuffer.length()>0 && outBuffer[0]=='}' && shouldIndentBrackettedLine ) --tabCount; // correctly indent one-line-blocks... else if (!lineStartsInComment && outBuffer.length()>0 && lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum && previousLastLineHeader != NULL && previousLastLineHeader != &AS_OPEN_BRACKET) tabCount -= 1; //lineOpeningBlocksNum - (blockIndent ? 1 : 0); if (tabCount < 0) tabCount = 0; // take care of extra bracket indentatation option... if (bracketIndent && outBuffer.length()>0 && shouldIndentBrackettedLine) if (outBuffer[0]=='{' || outBuffer[0]=='}') tabCount++; if (isInDefine) { if (outBuffer[0] == '#') { string preproc = trim(string(outBuffer.c_str() + 1)); if (preproc.COMPARE(0, 6, string("define")) == 0) { if (!inStatementIndentStack->empty() && inStatementIndentStack->back() > 0) { defineTabCount = tabCount; } else { defineTabCount = tabCount - 1; tabCount--; } } } tabCount -= defineTabCount; } if (tabCount < 0) tabCount = 0; // finally, insert indentations into begining of line prevFinalLineSpaceTabCount = spaceTabCount; prevFinalLineTabCount = tabCount; if (shouldForceTabIndentation) { tabCount += spaceTabCount / indentLength; spaceTabCount = spaceTabCount % indentLength; } outBuffer = preLineWS(spaceTabCount,tabCount) + outBuffer; if (lastLineHeader != NULL) previousLastLineHeader = lastLineHeader; return outBuffer; } string ASBeautifier::preLineWS(int spaceTabCount, int tabCount) { string ws; for (int i=0; i 0) ws += string(" "); return ws; } /** * register an in-statement indent. */ void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount, int minIndent, bool updateParenStack) { int inStatementIndent; int remainingCharNum = line.length() - i; int nextNonWSChar = 1; nextNonWSChar = getNextProgramCharDistance(line, i); // if indent is around the last char in the line, indent instead 2 spaces from the previous indent if (nextNonWSChar == remainingCharNum) { int previousIndent = spaceTabCount; if (!inStatementIndentStack->empty()) previousIndent = inStatementIndentStack->back(); inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent ); if (updateParenStack) parenIndentStack->push_back( previousIndent ); return; } if (updateParenStack) parenIndentStack->push_back(i+spaceTabCount); inStatementIndent = i + nextNonWSChar + spaceTabCount; if (i + nextNonWSChar < minIndent) inStatementIndent = minIndent + spaceTabCount; if (i + nextNonWSChar > maxInStatementIndent) inStatementIndent = indentLength*2 + spaceTabCount; if (!inStatementIndentStack->empty() && inStatementIndent < inStatementIndentStack->back()) inStatementIndent = inStatementIndentStack->back(); inStatementIndentStack->push_back(inStatementIndent); } /** * get distance to the next non-white sspace, non-comment character in the line. * if no such character exists, return the length remaining to the end of the line. */ int ASBeautifier::getNextProgramCharDistance(const string &line, int i) { bool inComment = false; int remainingCharNum = line.length() - i; int charDistance = 1; int ch; for (charDistance = 1; charDistance < remainingCharNum; charDistance++) { ch = line[i + charDistance]; if (inComment) { if (line.COMPARE(i + charDistance, 2, AS_CLOSE_COMMENT) == 0) { charDistance++; inComment = false; } continue; } else if (isWhiteSpace(ch)) continue; else if (ch == '/') { if (line.COMPARE(i + charDistance, 2, AS_OPEN_LINE_COMMENT) == 0) return remainingCharNum; else if (line.COMPARE(i + charDistance, 2, AS_OPEN_COMMENT) == 0) { charDistance++; inComment = true; } } else return charDistance; } return charDistance; } /** * check if a specific character can be used in a legal variable/method/class name * * @return legality of the char. * @param ch the character to be checked. */ bool ASBeautifier::isLegalNameChar(char ch) const { return (isalnum(ch) //(ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9') || || ch=='.' || ch=='_' || (!isCStyle && ch=='$') || (isCStyle && ch=='~')); } /** * check if a specific line position contains a header, out of several possible headers. * * @return a pointer to the found header. if no header was found then return NULL. */ const string *ASBeautifier::findHeader(const string &line, int i, const vector &possibleHeaders, bool checkBoundry) { int maxHeaders = possibleHeaders.size(); const string *header = NULL; int p; for (p=0; p < maxHeaders; p++) { header = possibleHeaders[p]; if (line.COMPARE(i, header->length(), *header) == 0) { // check that this is a header and not a part of a longer word // (e.g. not at its begining, not at its middle...) int lineLength = line.length(); int headerEnd = i + header->length(); char startCh = (*header)[0]; // first char of header char endCh = 0; // char just after header char prevCh = 0; // char just before header if (headerEnd < lineLength) { endCh = line[headerEnd]; } if (i > 0) { prevCh = line[i-1]; } if (!checkBoundry) { return header; } else if (prevCh != 0 && isLegalNameChar(startCh) && isLegalNameChar(prevCh)) { return NULL; } else if (headerEnd >= lineLength || !isLegalNameChar(startCh) || !isLegalNameChar(endCh)) { return header; } else { return NULL; } } } return NULL; } /** * check if a specific character can be used in a legal variable/method/class name * * @return legality of the char. * @param ch the character to be checked. */ bool ASBeautifier::isWhiteSpace(char ch) const { return (ch == ' ' || ch == '\t'); } /** * find the index number of a string element in a container of strings * * @return the index number of element in the ocntainer. -1 if element not found. * @param container a vector of strings. * @param element the element to find . */ int ASBeautifier::indexOf(vector &container, const string *element) { vector::const_iterator where; where= find(container.begin(), container.end(), element); if (where == container.end()) return -1; else return where - container.begin(); } /** * trim removes the white space surrounding a line. * * @return the trimmed line. * @param str the line to trim. */ string ASBeautifier::trim(const string &str) { int start = 0; int end = str.length() - 1; while (start < end && isWhiteSpace(str[start])) start++; while (start <= end && isWhiteSpace(str[end])) end--; string returnStr(str, start, end+1-start); return returnStr; } #ifdef USES_NAMESPACE } #endif /* * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved. * * compiler_defines.h (1 January 1999) * by Tal Davidson (davidsont@bigfoot.com) * This file is a part of "Artistic Style" - an indentater and reformatter * of C, C++, C# and Java source files. * * The "Artistic Style" project, including all files needed to compile it, * is free software; you can redistribute it and/or use it and/or modify it * under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU General Public * License along with this program. */ #ifndef ASBEAUTIFIER_H #define ASBEAUTIFIER_H #include "ASResource.h" #include "compiler_defines.h" #include "ASSourceIterator.h" #include #include using namespace std; namespace astyle { enum BracketMode { NONE_MODE, ATTACH_MODE, BREAK_MODE, BDAC_MODE }; enum BracketType { NULL_TYPE = 0, DEFINITION_TYPE = 1, COMMAND_TYPE = 2, ARRAY_TYPE = 4, SINGLE_LINE_TYPE = 8}; class ASBeautifier : protected ASResource { public: ASBeautifier(); virtual ~ASBeautifier(); virtual void init(ASSourceIterator* iter); // pointer to dynamically created iterator. virtual void init(); virtual bool hasMoreLines() const; virtual string nextLine(); virtual string beautify(const string &line); void setTabIndentation(int length = 4, bool forceTabs = false); void setSpaceIndentation(int length = 4); void setMaxInStatementIndentLength(int max); void setMinConditionalIndentLength(int min); void setClassIndent(bool state); void setSwitchIndent(bool state); void setCaseIndent(bool state); void setBracketIndent(bool state); void setBlockIndent(bool state); void setNamespaceIndent(bool state); void setLabelIndent(bool state); void setCStyle(); void setJavaStyle(); void setEmptyLineFill(bool state); void setPreprocessorIndent(bool state); protected: int getNextProgramCharDistance(const string &line, int i); bool isLegalNameChar(char ch) const; bool isWhiteSpace(char ch) const; const string *findHeader(const string &line, int i, const vector &possibleHeaders, bool checkBoundry = true); string trim(const string &str); int indexOf(vector &container, const string *element); private: ASBeautifier(const ASBeautifier ©); void operator=(ASBeautifier&); // not to be implemented void initStatic(); void registerInStatementIndent(const string &line, int i, int spaceTabCount, int minIndent, bool updateParenStack); string preLineWS(int spaceTabCount, int tabCount); static vector headers; static vector nonParenHeaders; static vector preprocessorHeaders; static vector preBlockStatements; static vector assignmentOperators; static vector nonAssignmentOperators; static bool calledInitStatic; ASSourceIterator *sourceIterator; vector *waitingBeautifierStack; vector *activeBeautifierStack; vector *waitingBeautifierStackLengthStack; vector *activeBeautifierStackLengthStack; vector *headerStack; vector< vector* > *tempStacks; vector *blockParenDepthStack; vector *blockStatementStack; vector *parenStatementStack; vector *inStatementIndentStack; vector *inStatementIndentStackSizeStack; vector *parenIndentStack; vector *bracketBlockStateStack; string indentString; const string *currentHeader; const string *previousLastLineHeader; const string *immediatelyPreviousAssignmentOp; const string *probationHeader; bool isInQuote; bool isInComment; bool isInCase; bool isInQuestion; bool isInStatement; bool isInHeader; bool isCStyle; bool isInOperator; bool isInTemplate; bool isInConst; bool isInDefine; bool isInDefineDefinition; bool classIndent; bool isInClassHeader; bool isInClassHeaderTab; bool switchIndent; bool caseIndent; bool namespaceIndent; bool bracketIndent; bool blockIndent; bool labelIndent; bool preprocessorIndent; bool isInConditional; bool isMinimalConditinalIndentSet; bool shouldForceTabIndentation; int minConditionalIndent; int parenDepth; int indentLength; int blockTabCount; unsigned int leadingWhiteSpaces; int maxInStatementIndent; int templateDepth; char quoteChar; char prevNonSpaceCh; char currentNonSpaceCh; char currentNonLegalCh; char prevNonLegalCh; int prevFinalLineSpaceTabCount; int prevFinalLineTabCount; bool emptyLineFill; bool backslashEndsPrevLine; int defineTabCount; }; } #endif /* * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved. * * ASFormatter.cpp * by Tal Davidson (davidsont@bigfoot.com) * This file is a part of "Artistic Style" - an indentater and reformatter * of C, C++, C# and Java source files. * * The "Artistic Style" project, including all files needed to compile it, * is free software; you can redistribute it and/or use it and/or modify it * under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU General Public * License along with this program. * * * Patches: * 26 November 1998 - Richard Bullington - * A correction of line-breaking in headers following '}', * was created using a variation of a patch by Richard Bullington. * 08 May 2004 * applied ASFormatter450670.patch.bz2, ASFormatter.cpp.patch.bz2, * patch1_ssvb_patch.tar.gz */ #include "compiler_defines.h" #include "ASFormatter.h" #include #include #include #include #include #define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); } #define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container) ; } #define IS_A(a,b) ( ((a) & (b)) == (b)) #ifdef USES_NAMESPACE using namespace std;