summaryrefslogtreecommitdiffstats
path: root/lib/astyle
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit114a878c64ce6f8223cfd22d76a20eb16d177e5e (patch)
treeacaf47eb0fa12142d3896416a69e74cbf5a72242 /lib/astyle
downloadtdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.tar.gz
tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdevelop@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/astyle')
-rw-r--r--lib/astyle/ASBeautifier.cpp1933
-rw-r--r--lib/astyle/ASEnhancer.cpp483
-rw-r--r--lib/astyle/ASFormatter.cpp2197
-rw-r--r--lib/astyle/ASResource.cpp389
-rw-r--r--lib/astyle/Makefile.am4
-rw-r--r--lib/astyle/astyle.h497
-rw-r--r--lib/astyle/compiler_defines.h49
7 files changed, 5552 insertions, 0 deletions
diff --git a/lib/astyle/ASBeautifier.cpp b/lib/astyle/ASBeautifier.cpp
new file mode 100644
index 00000000..432d58a9
--- /dev/null
+++ b/lib/astyle/ASBeautifier.cpp
@@ -0,0 +1,1933 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * ASBeautifier.cpp
+ *
+ * This file is a part of "Artistic Style" - an indentation and
+ * reformatting tool for C, C++, C# and Java source files.
+ * http://astyle.sourceforge.net
+ *
+ * The "Artistic Style" project, including all files needed to
+ * compile it, is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this project; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ */
+
+#include "astyle.h"
+
+#include <algorithm>
+#include <iostream>
+
+
+#define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); }
+#define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container); }
+
+
+namespace astyle
+{
+vector<const string*> ASBeautifier::headers;
+vector<const string*> ASBeautifier::nonParenHeaders;
+vector<const string*> ASBeautifier::preBlockStatements;
+vector<const string*> ASBeautifier::assignmentOperators;
+vector<const string*> ASBeautifier::nonAssignmentOperators;
+
+
+/*
+ * initialize the static vars
+ */
+void ASBeautifier::initStatic()
+{
+ static int beautifierFileType = 9; // initialized with an invalid type
+
+ if (fileType == beautifierFileType) // don't build unless necessary
+ return;
+
+ beautifierFileType = fileType;
+
+ headers.clear();
+ nonParenHeaders.clear();
+ assignmentOperators.clear();
+ nonAssignmentOperators.clear();
+ preBlockStatements.clear();
+
+ ASResource::buildHeaders(headers, fileType, true);
+ ASResource::buildNonParenHeaders(nonParenHeaders, fileType, true);
+ ASResource::buildAssignmentOperators(assignmentOperators);
+ ASResource::buildNonAssignmentOperators(nonAssignmentOperators);
+ ASResource::buildPreBlockStatements(preBlockStatements);
+
+// cout << "beaut" << endl;
+}
+
+/**
+ * ASBeautifier's constructor
+ */
+ASBeautifier::ASBeautifier()
+{
+ 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);
+ fileType = C_TYPE;
+ setCStyle();
+ setPreprocessorIndent(false);
+}
+
+/**
+ * ASBeautifier's copy constructor
+ */
+ASBeautifier::ASBeautifier(const ASBeautifier &other)
+{
+ waitingBeautifierStack = NULL;
+ activeBeautifierStack = NULL;
+ waitingBeautifierStackLengthStack = NULL;
+ activeBeautifierStackLengthStack = NULL;
+
+ headerStack = new vector<const string*>;
+ *headerStack = *other.headerStack;
+
+ tempStacks = new vector<vector<const string*>*>;
+ vector<vector<const string*>*>::iterator iter;
+ for (iter = other.tempStacks->begin();
+ iter != other.tempStacks->end();
+ ++iter)
+ {
+ vector<const string*> *newVec = new vector<const string*>;
+ *newVec = **iter;
+ tempStacks->push_back(newVec);
+ }
+ blockParenDepthStack = new vector<int>;
+ *blockParenDepthStack = *other.blockParenDepthStack;
+
+ blockStatementStack = new vector<bool>;
+ *blockStatementStack = *other.blockStatementStack;
+
+ parenStatementStack = new vector<bool>;
+ *parenStatementStack = *other.parenStatementStack;
+
+ bracketBlockStateStack = new vector<bool>;
+ *bracketBlockStateStack = *other.bracketBlockStateStack;
+
+ inStatementIndentStack = new vector<int>;
+ *inStatementIndentStack = *other.inStatementIndentStack;
+
+ inStatementIndentStackSizeStack = new vector<int>;
+ *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack;
+
+ parenIndentStack = new vector<int>;
+ *parenIndentStack = *other.parenIndentStack;
+
+ sourceIterator = other.sourceIterator;
+
+ // protected variables
+ fileType = other.fileType;
+ isCStyle = other.isCStyle;
+ isJavaStyle = other.isJavaStyle;
+ isSharpStyle = other.isSharpStyle;
+
+ // variables set by ASFormatter
+ // must also be updated in preprocessor
+ inLineNumber = other.inLineNumber;
+ outLineNumber = other.outLineNumber;
+ lineCommentNoBeautify = other.lineCommentNoBeautify;
+ isNonInStatementArray = other.isNonInStatementArray;
+
+ // private variables
+ indentString = other.indentString;
+ currentHeader = other.currentHeader;
+ previousLastLineHeader = other.previousLastLineHeader;
+ immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp;
+ probationHeader = other.probationHeader;
+ isInQuote = other.isInQuote;
+ isInComment = other.isInComment;
+ isInCase = other.isInCase;
+ isInQuestion = other.isInQuestion;
+ isInStatement = other.isInStatement;
+ isInHeader = other.isInHeader;
+ isInOperator = other.isInOperator;
+ isInTemplate = other.isInTemplate;
+ isInDefine = other.isInDefine;
+ isInDefineDefinition = other.isInDefineDefinition;
+ 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;
+ isInConditional = other.isInConditional;
+ isMinimalConditinalIndentSet = other.isMinimalConditinalIndentSet;
+ shouldForceTabIndentation = other.shouldForceTabIndentation;
+ emptyLineFill = other.emptyLineFill;
+ backslashEndsPrevLine = other.backslashEndsPrevLine;
+ blockCommentNoIndent = other.blockCommentNoIndent;
+ blockCommentNoBeautify = other.blockCommentNoBeautify;
+ previousLineProbationTab = other.previousLineProbationTab;
+ minConditionalIndent = other.minConditionalIndent;
+ parenDepth = other.parenDepth;
+ indentLength = other.indentLength;
+ blockTabCount = other.blockTabCount;
+ leadingWhiteSpaces = other.leadingWhiteSpaces;
+ maxInStatementIndent = other.maxInStatementIndent;
+ templateDepth = other.templateDepth;
+ prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount;
+ prevFinalLineTabCount = other.prevFinalLineTabCount;
+ defineTabCount = other.defineTabCount;
+ quoteChar = other.quoteChar;
+ prevNonSpaceCh = other.prevNonSpaceCh;
+ currentNonSpaceCh = other.currentNonSpaceCh;
+ currentNonLegalCh = other.currentNonLegalCh;
+ prevNonLegalCh = other.prevNonLegalCh;
+}
+
+/**
+ * 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);
+}
+
+/**
+ * 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()
+{
+ initStatic();
+
+ INIT_CONTAINER(waitingBeautifierStack, new vector<ASBeautifier*>);
+ INIT_CONTAINER(activeBeautifierStack, new vector<ASBeautifier*>);
+
+ INIT_CONTAINER(waitingBeautifierStackLengthStack, new vector<int>);
+ INIT_CONTAINER(activeBeautifierStackLengthStack, new vector<int>);
+
+ INIT_CONTAINER(headerStack, new vector<const string*>);
+ INIT_CONTAINER(tempStacks, new vector<vector<const string*>*>);
+ tempStacks->push_back(new vector<const string*>);
+
+ INIT_CONTAINER(blockParenDepthStack, new vector<int>);
+ INIT_CONTAINER(blockStatementStack, new vector<bool>);
+ INIT_CONTAINER(parenStatementStack, new vector<bool>);
+
+ INIT_CONTAINER(bracketBlockStateStack, new vector<bool>);
+ bracketBlockStateStack->push_back(true);
+
+ INIT_CONTAINER(inStatementIndentStack, new vector<int>);
+ INIT_CONTAINER(inStatementIndentStackSizeStack, new vector<int>);
+ inStatementIndentStackSizeStack->push_back(0);
+ INIT_CONTAINER(parenIndentStack, new vector<int>);
+
+ immediatelyPreviousAssignmentOp = NULL;
+ previousLastLineHeader = NULL;
+ currentHeader = NULL;
+
+ isInQuote = false;
+ isInComment = false;
+ isInStatement = false;
+ isInCase = false;
+ isInQuestion = false;
+ isInClassHeader = false;
+ isInClassHeaderTab = false;
+ isInHeader = false;
+ isInOperator = false;
+ isInTemplate = false;
+ isInConditional = false;
+ templateDepth = 0;
+ parenDepth = 0;
+ blockTabCount = 0;
+ leadingWhiteSpaces = 0;
+ prevNonSpaceCh = '{';
+ currentNonSpaceCh = '{';
+ prevNonLegalCh = '{';
+ currentNonLegalCh = '{';
+ quoteChar = ' ';
+ prevFinalLineSpaceTabCount = 0;
+ prevFinalLineTabCount = 0;
+ probationHeader = NULL;
+ backslashEndsPrevLine = false;
+ isInDefine = false;
+ isInDefineDefinition = false;
+ defineTabCount = 0;
+ lineCommentNoBeautify = false;
+ blockCommentNoIndent = false;
+ blockCommentNoBeautify = false;
+ previousLineProbationTab = false;
+ isNonInStatementArray = false;
+ inLineNumber = -1; // for debugging
+ outLineNumber = 0; // for debugging
+}
+
+/**
+ * set indentation style to C/C++.
+ */
+void ASBeautifier::setCStyle()
+{
+ fileType = C_TYPE;
+ isCStyle = true;
+ isJavaStyle = false;
+ isSharpStyle = false;
+}
+
+/**
+ * set indentation style to Java.
+ */
+void ASBeautifier::setJavaStyle()
+{
+ fileType = JAVA_TYPE;
+ isJavaStyle = true;
+ isCStyle = false;
+ isSharpStyle = false;
+}
+
+/**
+ * set indentation style to C#.
+ */
+void ASBeautifier::setSharpStyle()
+{
+ fileType = SHARP_TYPE;
+ isSharpStyle = true;
+ isCStyle = false;
+ isJavaStyle = 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;
+}
+
+/**
+ * get the number of spaces per indent
+ *
+ * @return value of indentLength option.
+*/
+int ASBeautifier::getIndentLength(void)
+{
+ return indentLength;
+}
+
+/**
+ * get the char used for indentation, space or tab
+ *
+ * @return the char used for indentation.
+ */
+string ASBeautifier::getIndentString(void)
+{
+ return indentString;
+}
+
+/**
+ * get the state of the case indentation option. If true, lines of 'case'
+ * statements will be indented one additional indent.
+ *
+ * @return state of caseIndent option.
+ */
+bool ASBeautifier::getCaseIndent(void)
+{
+ return caseIndent;
+}
+
+/**
+ * get C style identifier.
+ * If true, a C source is being indented.
+ *
+ * @return state of isCStyle option.
+ */
+bool ASBeautifier::getCStyle(void)
+{
+ return isCStyle;
+}
+
+/**
+ * get Java style identifier.
+ * If true, a Java source is being indented.
+ *
+ * @return state of isJavaStyle option.
+ */
+bool ASBeautifier::getJavaStyle(void)
+{
+ return isJavaStyle;
+}
+
+/**
+ * get C# style identifier.
+ * If true, a C# source is being indented.
+ *
+ * @return state of isSharpStyle option.
+ */
+bool ASBeautifier::getSharpStyle(void)
+{
+ return isSharpStyle;
+}
+
+/**
+ * get 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.
+ *
+ * @return state of emptyLineFill option.
+ */
+bool ASBeautifier::getEmptyLineFill(void)
+{
+ return emptyLineFill;
+}
+
+/**
+ * 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;
+ size_t headerStackSize = headerStack->size();
+ bool shouldIndentBrackettedLine = true;
+ int lineOpeningBlocksNum = 0;
+ int lineClosingBlocksNum = 0;
+ bool previousLineProbation = (probationHeader != NULL);
+ int i;
+
+ currentHeader = NULL;
+ lineStartsInComment = isInComment;
+ blockCommentNoBeautify = blockCommentNoIndent;
+ previousLineProbationTab = false;
+ outLineNumber++;
+
+ // 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)
+ {
+ int strlen = originalLine.length();
+ leadingWhiteSpaces = 0;
+
+ for (int j = 0; j < strlen && isWhiteSpace(originalLine[j]); j++)
+ {
+ if (originalLine[j] == '\t')
+ leadingWhiteSpaces += indentLength;
+ else
+ leadingWhiteSpaces++;
+ }
+ line = trim(originalLine);
+ }
+ else
+ {
+ // convert leading tabs to spaces
+ string spaceTabs(indentLength, ' ');
+ string newLine = originalLine;
+ int strlen = newLine.length();
+
+ for (int j=0; j < leadingWhiteSpaces && j < strlen; j++)
+ {
+ if (newLine[j] == '\t')
+ {
+ newLine.replace(j, 1, spaceTabs);
+ strlen = newLine.length();
+ }
+ }
+
+ // trim the comment leaving the new leading whitespace
+ int trimSize = 0;
+ strlen = newLine.length();
+
+ while (trimSize < strlen
+ && trimSize < leadingWhiteSpaces
+ && isWhiteSpace(newLine[trimSize]))
+ trimSize++;
+
+
+ while (trimSize < strlen && isWhiteSpace(newLine[strlen-1]))
+ strlen--;
+
+ line = newLine.substr(trimSize, strlen);
+ size_t trimEnd = line.find_last_not_of(" \t");
+ if (trimEnd != string::npos)
+ {
+ int spacesToDelete = line.length() - 1 - trimEnd;
+ if (spacesToDelete > 0)
+ line.erase(trimEnd + 1, spacesToDelete);
+ }
+ }
+
+
+ if (line.length() == 0)
+ {
+ if (backslashEndsPrevLine) // must continue to clear variables
+ line = ' ';
+ else if (emptyLineFill)
+ return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount);
+ else
+ return line;
+ }
+
+ // handle preprocessor commands
+
+ if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine))
+ {
+ if (line[0] == '#')
+ {
+ string preproc = trim(string(line.c_str() + 1));
+
+ // When finding a multi-lined #define statement, the original beautifier
+ // 1. sets its isInDefineDefinition flag
+ // 2. clones a new beautifier that will be used for the actual indentation
+ // of the #define. This clone is put into the activeBeautifierStack in order
+ // to be called for the actual indentation.
+ // The original beautifier will have isInDefineDefinition = true, isInDefine = false
+ // The cloned beautifier will have isInDefineDefinition = true, isInDefine = true
+ if (preprocessorIndent && preproc.compare(0, 6, "define") == 0 && line[line.length() - 1] == '\\')
+ {
+ if (!isInDefineDefinition)
+ {
+ ASBeautifier *defineBeautifier;
+
+ // this is the original beautifier
+ isInDefineDefinition = true;
+
+ // push a new beautifier into the active stack
+ // this beautifier will be used for the indentation of this define
+ defineBeautifier = new ASBeautifier(*this);
+ 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, "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*/, "else") == 0)
+ {
+ if (waitingBeautifierStack && !waitingBeautifierStack->empty())
+ {
+ // MOVE current waiting beautifier to active stack.
+ activeBeautifierStack->push_back(waitingBeautifierStack->back());
+ waitingBeautifierStack->pop_back();
+ }
+ }
+ else if (preproc.compare(0, 4, "elif") == 0)
+ {
+ if (waitingBeautifierStack && !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, "endif") == 0)
+ {
+ int stackLength;
+ ASBeautifier *beautifier;
+
+ if (waitingBeautifierStackLengthStack && !waitingBeautifierStackLengthStack->empty())
+ {
+ stackLength = waitingBeautifierStackLengthStack->back();
+ waitingBeautifierStackLengthStack->pop_back();
+ while ((int) waitingBeautifierStack->size() > stackLength)
+ {
+ beautifier = waitingBeautifierStack->back();
+ waitingBeautifierStack->pop_back();
+ delete beautifier;
+ }
+ }
+
+ if (!activeBeautifierStackLengthStack->empty())
+ {
+ stackLength = activeBeautifierStackLengthStack->back();
+ activeBeautifierStackLengthStack->pop_back();
+ while ((int) 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.
+ // variables set by ASFormatter must be updated.
+ if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty())
+ {
+ activeBeautifierStack->back()->inLineNumber = inLineNumber;
+ activeBeautifierStack->back()->outLineNumber = outLineNumber;
+ activeBeautifierStack->back()->lineCommentNoBeautify = lineCommentNoBeautify;
+ activeBeautifierStack->back()->isNonInStatementArray = isNonInStatementArray;
+ return activeBeautifierStack->back()->beautify(line);
+ }
+
+ // calculate preliminary indentation based on data from past lines
+ if (!inStatementIndentStack->empty())
+ spaceTabCount = inStatementIndentStack->back();
+
+
+ for (i = 0; i < (int) headerStackSize; i++)
+ {
+ isInClass = false;
+
+ if (blockIndent || (!(i > 0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
+ && (*headerStack)[i] == &AS_OPEN_BRACKET)))
+ ++tabCount;
+
+ if (!isJavaStyle && !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; i < (int) line.length(); i++)
+ {
+ tempCh = line[i];
+
+ prevCh = ch;
+ ch = tempCh;
+
+ outBuffer.append(1, ch);
+
+ if (isWhiteSpace(ch))
+ continue;
+
+ // check for utf8 characters
+ // isalnum() will display an assert message in debug if not bypassed here
+ if (ch < 0)
+ continue;
+
+ // handle special characters (i.e. backslash+character such as \n, \t, ...)
+ if (isSpecialChar)
+ {
+ isSpecialChar = false;
+ continue;
+ }
+ if (!(isInComment || isInLineComment) && line.compare(i, 2, "\\\\") == 0)
+ {
+ outBuffer.append(1, '\\');
+ i++;
+ continue;
+ }
+ if (!(isInComment || isInLineComment) && ch == '\\')
+ {
+ isSpecialChar = true;
+ continue;
+ }
+
+ // handle quotes (such as 'x' and "Hello Dolly")
+ if (!(isInComment || isInLineComment) && (ch == '"' || ch == '\''))
+ if (!isInQuote)
+ {
+ quoteChar = ch;
+ isInQuote = true;
+ }
+ else if (quoteChar == ch)
+ {
+ isInQuote = false;
+ isInStatement = true;
+ continue;
+ }
+ if (isInQuote)
+ continue;
+
+ // handle comments
+
+ if (!(isInComment || isInLineComment) && line.compare(i, 2, "//") == 0)
+ {
+ isInLineComment = true;
+ outBuffer.append(1, '/');
+ i++;
+ continue;
+ }
+ else if (!(isInComment || isInLineComment) && line.compare(i, 2, "/*") == 0)
+ {
+ isInComment = true;
+ outBuffer.append(1, '*');
+ i++;
+ size_t j = line.find_first_not_of(" \t");
+ if (!line.compare(j, 2, "/*") == 0) // does line start with comment?
+ blockCommentNoIndent = true; // if no, cannot indent continuation lines
+ continue;
+ }
+ else if ((isInComment || isInLineComment) && line.compare(i, 2, "*/") == 0)
+ {
+ isInComment = false;
+ outBuffer.append(1, '/');
+ i++;
+ blockCommentNoIndent = false; // ok to indent next comment
+ continue;
+ }
+
+ if (isInComment || isInLineComment)
+ continue;
+
+ // if we have reached this far then we are NOT in a comment or string of special character...
+
+ if (probationHeader != NULL)
+ {
+ if (((probationHeader == &AS_STATIC || probationHeader == &AS_CONST) && ch == '{')
+ || (probationHeader == &AS_SYNCHRONIZED && ch == '('))
+ {
+ // insert the probation header as a new header
+ isInHeader = true;
+ headerStack->push_back(probationHeader);
+
+ // handle the specific probation header
+ isInConditional = (probationHeader == &AS_SYNCHRONIZED);
+ if (probationHeader == &AS_CONST)
+ isImmediatelyAfterConst = true;
+
+ isInStatement = false;
+ // if the probation comes from the previous line, then indent by 1 tab count.
+ if (previousLineProbation && ch == '{')
+ {
+ tabCount++;
+ previousLineProbationTab = true;
+ }
+ previousLineProbation = false;
+ }
+
+ // dismiss the probation header
+ probationHeader = NULL;
+ }
+
+ prevNonSpaceCh = currentNonSpaceCh;
+ currentNonSpaceCh = ch;
+ if (!isLegalNameChar(ch) && ch != ',' && ch != ';')
+ {
+ prevNonLegalCh = currentNonLegalCh;
+ currentNonLegalCh = ch;
+ }
+
+ 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())
+ {
+ int previousIndentStackSize = inStatementIndentStackSizeStack->back();
+ inStatementIndentStackSizeStack->pop_back();
+ while (previousIndentStackSize < (int) 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;
+ // first, check if '{' is a block-opener or an static-array opener
+ isBlockOpener = ((prevNonSpaceCh == '{' && bracketBlockStateStack->back())
+ || prevNonSpaceCh == '}'
+ || prevNonSpaceCh == ')'
+ || prevNonSpaceCh == ';'
+ || peekNextChar(line, i) == '{'
+ || isNonInStatementArray
+ || isInClassHeader
+// || isBlockOpener
+ || isImmediatelyAfterConst
+ || (isInDefine &&
+ (prevNonSpaceCh == '('
+ || prevNonSpaceCh == '_'
+ || isalnum(prevNonSpaceCh))));
+
+ isInClassHeader = false;
+ if (!isBlockOpener && currentHeader != NULL)
+ {
+ for (size_t 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;
+ // decrease tab count if bracket is broken
+ size_t firstChar = line.find_first_not_of(" \t");
+ if (firstChar != string::npos)
+ if (line[firstChar] == '{' && (int) firstChar == i)
+ tabCount -= 2;
+ }
+
+ // do not allow inStatementIndent - should occur for Java files only
+ if (inStatementIndentStack->size() > 0)
+ {
+ spaceTabCount = 0;
+ inStatementIndentStack->back() = 0;
+ }
+
+ blockParenDepthStack->push_back(parenDepth);
+ blockStatementStack->push_back(isInStatement);
+
+ inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
+ if (inStatementIndentStack->size() > 0)
+ inStatementIndentStack->back() = 0;
+
+ blockTabCount += isInStatement ? 1 : 0;
+ parenDepth = 0;
+ isInStatement = false;
+
+ tempStacks->push_back(new vector<const string*>);
+ headerStack->push_back(&AS_OPEN_BRACKET);
+ lastLineHeader = &AS_OPEN_BRACKET;
+
+ continue;
+ }
+
+ //check if a header has been reached
+ if (isWhiteSpace(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<const string*> *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)
+ {
+ 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; r < restackSize; r++)
+ {
+ headerStack->push_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; r < restackSize; r++)
+ {
+ headerStack->push_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; r < restackSize; r++)
+ {
+ headerStack->push_back(lastTempStack->back());
+ lastTempStack->pop_back();
+ }
+
+ if (!closingBracketReached)
+ tabCount += restackSize;
+ }
+ }
+ }
+ else if (newHeader == &AS_CASE)
+ {
+ isInCase = true;
+ --tabCount;
+ }
+ else if (newHeader == &AS_DEFAULT)
+ {
+ isInCase = true;
+ --tabCount;
+ }
+ 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)
+ {
+ isIndentableHeader = false;
+ }
+ else if (newHeader == &AS_TEMPLATE)
+ {
+ if (isCStyle)
+ isInTemplate = true;
+ isIndentableHeader = false;
+ }
+
+
+ if (isIndentableHeader)
+ {
+ headerStack->push_back(newHeader);
+ isInStatement = false;
+ if (indexOf(nonParenHeaders, newHeader) == -1)
+ {
+ isInConditional = true;
+ }
+ lastLineHeader = newHeader;
+ }
+ else
+ isInHeader = false;
+
+ outBuffer.append(newHeader->substr(1));
+ i += newHeader->length() - 1;
+
+ continue;
+ }
+ }
+
+ if (isCStyle && !isalpha(prevCh)
+ && line.compare(i, 8, "operator") == 0 && !isalnum(line[i+8]))
+ {
+ isInOperator = true;
+ outBuffer.append(AS_OPERATOR.substr(1));
+ i += 7;
+ continue;
+ }
+
+ // "new" operator is a pointer, not a calculation
+ if (!isalpha(prevCh)
+ && line.compare(i, 3, "new") == 0 && !isalnum(line[i+3]))
+ {
+ if (prevNonSpaceCh == '=' && isInStatement && !inStatementIndentStack->empty())
+ inStatementIndentStack->back() = 0;
+ }
+
+ if (ch == '?')
+ isInQuestion = true;
+
+
+ // special handling of 'case' statements
+ if (ch == ':')
+ {
+ if ((int) line.length() > i + 1 && line[i+1] == ':') // look for ::
+ {
+ ++i;
+ outBuffer.append(1, ':');
+ ch = ' ';
+ continue;
+ }
+
+ else if (isInQuestion)
+ {
+ isInQuestion = false;
+ }
+
+ else if (isCStyle && isInClass && prevNonSpaceCh != ')')
+ {
+ --tabCount;
+ // found a 'private:' or 'public:' inside a class definition
+ // so do nothing special
+ }
+
+ else if (!isJavaStyle && isInClassHeader)
+ {
+ // found a 'class A : public B' definition
+ // so do nothing special
+ }
+
+ else if (isJavaStyle && lastLineHeader == &AS_FOR)
+ {
+ // found a java for-each statement
+ // so do nothing special
+ }
+
+ 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 ';'
+ }
+
+
+ else // is in a label (e.g. 'label1:')
+ {
+ if (labelIndent)
+ --tabCount; // unindent label by one indent
+ else
+ tabCount = 0; // completely flush indent to left
+ }
+
+
+
+ }
+ }
+
+ if ((ch == ';' || (parenDepth > 0 && ch == ',')) && !inStatementIndentStackSizeStack->empty())
+ while ((int) inStatementIndentStackSizeStack->back() + (parenDepth > 0 ? 1 : 0)
+ < (int) 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
+
+ int previousIndentStackSize = inStatementIndentStackSizeStack->back();
+ inStatementIndentStackSizeStack->pop_back();
+ while (previousIndentStackSize < (int) 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<const string*> *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;
+
+ previousLastLineHeader = NULL;
+ isInClassHeader = false;
+ isInQuestion = false;
+
+ continue;
+ }
+
+
+ // check for preBlockStatements ONLY if not within parenthesies
+ // (otherwise 'struct XXX' statements would be wrongly interpreted...)
+ if (isWhiteSpace(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;
+ headerStack->push_back(newHeader);
+ }
+ }
+
+ // Handle operators
+
+ immediatelyPreviousAssignmentOp = NULL;
+
+ // Check if an operator has been reached.
+ const string *foundAssignmentOp = findHeader(line, i, assignmentOperators, false);
+ if (foundAssignmentOp == &AS_RETURN)
+ foundAssignmentOp = findHeader(line, i, assignmentOperators, true);
+ const string *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 && !isNonInStatementArray)
+ {
+ registerInStatementIndent(line, i, spaceTabCount, 0, false);
+ immediatelyPreviousAssignmentOp = foundAssignmentOp;
+ isInStatement = true;
+ }
+ }
+
+ 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.
+ */
+
+ 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
+ && previousLineProbationTab)
+ --tabCount; //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, "define") == 0)
+ {
+ if (!inStatementIndentStack->empty()
+ && inStatementIndentStack->back() > 0)
+ {
+ defineTabCount = tabCount;
+ }
+ else
+ {
+ defineTabCount = tabCount - 1;
+ tabCount--;
+ }
+ }
+ }
+
+ tabCount -= defineTabCount;
+ }
+
+ if (tabCount < 0)
+ tabCount = 0;
+ if (lineCommentNoBeautify || blockCommentNoBeautify)
+ tabCount = spaceTabCount = 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 < tabCount; i++)
+ ws += indentString;
+
+ while ((spaceTabCount--) > 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 = 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();
+
+ if (isNonInStatementArray)
+ inStatementIndent = 0;
+
+ 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;
+ char ch;
+
+ for (charDistance = 1; charDistance < remainingCharNum; charDistance++)
+ {
+ ch = line[i + charDistance];
+ if (inComment)
+ {
+ if (line.compare(i + charDistance, 2, "*/") == 0)
+ {
+ charDistance++;
+ inComment = false;
+ }
+ continue;
+ }
+ else if (isWhiteSpace(ch))
+ continue;
+ else if (ch == '/')
+ {
+ if (line.compare(i + charDistance, 2, "//") == 0)
+ return remainingCharNum;
+ else if (line.compare(i + charDistance, 2, "/*") == 0)
+ {
+ charDistance++;
+ inComment = true;
+ }
+ }
+ else
+ return charDistance;
+ }
+
+ return charDistance;
+}
+
+
+/**
+ * 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<const string*> &possibleHeaders, bool checkBoundry)
+{
+ int maxHeaders = possibleHeaders.size();
+ // const string *header = NULL;
+ int p;
+
+ for (p = 0; p < maxHeaders; p++)
+ {
+ const string *header = possibleHeaders[p];
+
+ if (line.compare(i, header->length(), header->c_str()) == 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;
+}
+
+/**
+ * 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<const string*> &container, const string *element)
+{
+ vector<const string*>::const_iterator where;
+
+ where = find(container.begin(), container.end(), element);
+ if (where == container.end())
+ return -1;
+ else
+ return (int) (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;
+}
+
+/**
+* peek at the next unread character.
+*
+* @return the next unread character.
+* @param line the line to check.
+* @param i the current char position on the line.
+*/
+char ASBeautifier::peekNextChar(string &line, int i)
+{
+ char ch = ' ';
+ size_t peekNum = line.find_first_not_of(" \t", i + 1);
+
+ if (peekNum == string::npos)
+ return ch;
+
+ ch = line[peekNum];
+
+ return ch;
+}
+
+
+} // end namespace astyle
+
diff --git a/lib/astyle/ASEnhancer.cpp b/lib/astyle/ASEnhancer.cpp
new file mode 100644
index 00000000..6fea5970
--- /dev/null
+++ b/lib/astyle/ASEnhancer.cpp
@@ -0,0 +1,483 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * ASEnhancer.cpp
+ *
+ * This file is a part of "Artistic Style" - an indentation and
+ * reformatting tool for C, C++, C# and Java source files.
+ * http://astyle.sourceforge.net
+ *
+ * The "Artistic Style" project, including all files needed to
+ * compile it, is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this project; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ */
+
+// can trace only if NDEBUG is not defined
+#ifndef NDEBUG
+// #define TRACEswitch
+// #define TRACEcase
+// #define TRACEmisc
+#endif
+
+#include "astyle.h"
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#ifdef TRACEswitch
+#define TRswitch(a,b) *traceOut << lineNumber << a << b << endl;
+#else
+#define TRswitch(a,b) ((void)0)
+#endif // TRACEswitch
+#ifdef TRACEcase
+#define TRcase(a,b) *traceOut << lineNumber << a << b << endl;
+#else
+#define TRcase(a,b) ((void)0)
+#endif // TRACEcase
+#ifdef TRACEmisc
+#define TRmisc(a) *traceOut << lineNumber << a << endl;
+#else
+#define TRmisc(a) ((void)0)
+#endif // TRACEmisc
+
+
+namespace astyle
+{
+
+// ---------------------------- functions for ASEnhancer Class -------------------------------------
+
+/**
+ * ASEnhancer constructor
+ */
+ASEnhancer::ASEnhancer()
+{
+ // variables are initialized by init()
+ traceOut = new stringstream;
+}
+
+/**
+ * Destructor of ASEnhancer
+ * Display the TRACE entries.
+ */
+ASEnhancer::~ASEnhancer()
+{
+#if defined(TRACEswitch) || defined(TRACEcase) || defined(TRACEmisc)
+ string line;
+ string msg = "TRACE Entries\n\n";
+ char countLine[50];
+ int count = 0;
+
+ while (getline(*traceOut, line))
+ {
+ msg += line + '\n';
+ count++;
+ }
+ sprintf(countLine, "\n%d Entries", count);
+ msg += countLine;
+ // write a text file to "My Documents" (Windows)
+ char filename [_MAX_PATH + _MAX_FNAME + _MAX_EXT + 1]; // full path and filename
+ strcpy(filename, getenv("USERPROFILE"));
+ strcat(filename, "\\My Documents\\tracee.txt");
+ ofstream outfile(filename);
+ outfile << msg;
+ outfile.close();
+#endif
+ delete traceOut;
+}
+
+/**
+ * initialize the ASEnhancer.
+ *
+ * init() is called each time an ASFormatter object is initialized.
+ */
+void ASEnhancer::init(int _indentLength,
+ string _indentString,
+ bool _isCStyle,
+ bool _isJavaStyle,
+ bool _isSharpStyle,
+ bool _caseIndent,
+ bool _emptyLineFill)
+{
+ // formatting variables from ASFormatter and ASBeautifier
+ indentLength = _indentLength;
+ if (_indentString.compare(0, 1, "\t") == 0)
+ useTabs = true;
+ else
+ useTabs = false;
+ isCStyle = _isCStyle;
+ isJavaStyle = _isJavaStyle;
+ isSharpStyle = _isSharpStyle;
+ caseIndent = _caseIndent;
+ emptyLineFill = _emptyLineFill;
+
+ // unindent variables
+ lineNumber = 0;
+ bracketCount = 0;
+ isInComment = false;
+ isInQuote = false;
+ switchDepth = 0;
+ lookingForCaseBracket = false;
+ unindentNextLine = false;
+
+#if defined(TRACEswitch) || defined(TRACEcase) || defined(TRACEmisc)
+ *traceOut << "New file -------------" << endl;
+#endif
+}
+
+/**
+ * additional formatting for line of source code.
+ * every line of source code in a source code file should be sent
+ * one after the other to this function.
+ * indents event tables
+ * unindents the case blocks
+ *
+ * @param line the original formatted line will be updated if necessary.
+ */
+void ASEnhancer::enhance(string &line)
+{
+ static vector<switchVariables> swVector; // stack vector of switch variables
+ static switchVariables sw; // switch variables struct
+
+ static bool nextLineIsEventTable; // begin event table is reached
+ static bool isInEventTable; // need to indent an event table
+
+ bool isSpecialChar = false;
+ size_t lineLength; // length of the line being parsed
+
+ lineNumber++;
+ lineLength = line.length();
+
+ // check for beginning of event table
+ if (nextLineIsEventTable)
+ {
+ isInEventTable = true;
+ nextLineIsEventTable = false;
+ }
+
+ if (lineLength == 0
+ && ! isInEventTable
+ && ! emptyLineFill)
+ return;
+
+ // test for unindent on attached brackets
+ if (unindentNextLine)
+ {
+ sw.unindentDepth++;
+ sw.unindentCase = true;
+ unindentNextLine = false;
+ TRcase(" unindent case ", sw.unindentDepth);
+ }
+
+ // parse characters in the current line.
+
+ for (size_t i = 0; i < lineLength; i++)
+ {
+ char ch = line[i];
+
+ // bypass whitespace
+ if (isWhiteSpaceX(ch))
+ continue;
+
+ // handle special characters (i.e. backslash+character such as \n, \t, ...)
+ if (isSpecialChar)
+ {
+ isSpecialChar = false;
+ continue;
+ }
+ if (!(isInComment) && line.compare(i, 2, "\\\\") == 0)
+ {
+ i++;
+ continue;
+ }
+ if (!(isInComment) && ch == '\\')
+ {
+ isSpecialChar = true;
+ continue;
+ }
+
+ // handle quotes (such as 'x' and "Hello Dolly")
+ if (!(isInComment) && (ch == '"' || ch == '\''))
+ if (!isInQuote)
+ {
+ quoteChar = ch;
+ isInQuote = true;
+ }
+ else if (quoteChar == ch)
+ {
+ isInQuote = false;
+ continue;
+ }
+
+ if (isInQuote)
+ continue;
+
+ // handle comments
+
+ if (!(isInComment) && line.compare(i, 2, "//") == 0)
+ {
+ // check for windows line markers
+ if (line.compare(i + 2, 1, "\xf0") > 0)
+ lineNumber--;
+ break; // finished with the line
+ }
+ else if (!(isInComment) && line.compare(i, 2, "/*") == 0)
+ {
+ isInComment = true;
+ i++;
+ continue;
+ }
+ else if ((isInComment) && line.compare(i, 2, "*/") == 0)
+ {
+ isInComment = false;
+ i++;
+ continue;
+ }
+
+ if (isInComment)
+ continue;
+
+ // if we have reached this far then we are NOT in a comment or string of special characters
+
+ if (line[i] == '{') // if open bracket
+ bracketCount++;
+
+ if (line[i] == '}') // if close bracket
+ bracketCount--;
+
+ // ---------------- process event tables --------------------------------------
+
+ // check for event table begin
+ if (findKeyword(line, i, "BEGIN_EVENT_TABLE")
+ || findKeyword(line, i, "BEGIN_MESSAGE_MAP"))
+ nextLineIsEventTable = true;
+
+ // check for event table end
+ if (findKeyword(line, i, "END_EVENT_TABLE")
+ || findKeyword(line, i, "END_MESSAGE_MAP"))
+ isInEventTable = false;
+
+ // ---------------- process switch statements ---------------------------------
+
+ if (findKeyword(line, i, "switch")) // if switch statement
+ {
+ switchDepth++; // bump switch depth
+ TRswitch(" switch ", switchDepth);
+ swVector.push_back(sw); // save current variables
+ sw.switchBracketCount = 0;
+ sw.unindentCase = false; // don't clear case until end of switch
+ i += 5; // bypass switch statement
+ continue;
+ }
+
+ // just want switch statements from this point
+
+ if (caseIndent || switchDepth == 0) // from here just want switch statements
+ continue; // get next char
+
+ if (line[i] == '{') // if open bracket
+ {
+ sw.switchBracketCount++;
+ if (lookingForCaseBracket) // if 1st after case statement
+ {
+ sw.unindentCase = true; // unindenting this case
+ sw.unindentDepth++; // bump depth
+ lookingForCaseBracket = false; // not looking now
+ TRcase(" unindent case ", sw.unindentDepth);
+ }
+ continue;
+ }
+
+ lookingForCaseBracket = false; // no opening bracket, don't indent
+
+ if (line[i] == '}') // if close bracket
+ {
+ sw.switchBracketCount--;
+ if (sw.switchBracketCount == 0) // if end of switch statement
+ {
+ TRswitch(" endsw ", switchDepth);
+ switchDepth--; // one less switch
+ sw = swVector.back(); // restore sw struct
+ swVector.pop_back(); // remove last entry from stack
+ }
+ continue;
+ }
+
+ // look for case or default header
+
+ if (findKeyword(line, i, "case") || findKeyword(line, i, "default"))
+ {
+ if (sw.unindentCase) // if unindented last case
+ {
+ sw.unindentCase = false; // stop unindenting previous case
+ sw.unindentDepth--; // reduce depth
+ }
+ for (; i < lineLength; i++) // bypass colon
+ {
+ if (line[i] == ':')
+ if ((i + 1 < lineLength) && (line[i + 1] == ':'))
+ i++; // bypass scope resolution operator
+ else
+ break;
+ }
+ i++;
+ for (; i < lineLength; i++) // bypass whitespace
+ {
+ if (!(isWhiteSpaceX(line[i])))
+ break;
+ }
+ if (i < lineLength) // check for bracket
+ {
+ if (line[i] == '{') // if bracket found
+ {
+ sw.switchBracketCount++;
+ unindentNextLine = true; // start unindenting on next line
+ continue;
+ }
+ }
+ lookingForCaseBracket = true; // bracket must be on next line
+ i--; // need to check for comments
+ continue;
+ }
+ } // end of for loop
+
+ if (isInEventTable) // if need to indent
+ indentLine(line, 1); // do it
+
+ if (sw.unindentDepth > 0) // if need to unindent
+ unindentLine(line, sw.unindentDepth); // do it
+}
+
+/**
+ * indent a line by a given number of tabsets
+ * by inserting leading whitespace to the line argument.
+ *
+ * @param line a pointer to the line to indent.
+ * @param unindent the number of tabsets to insert.
+ * @return the number of characters inserted.
+ */
+int ASEnhancer::indentLine(string &line, const int indent) const
+{
+ if (line.length() == 0
+ && ! emptyLineFill)
+ return 0;
+
+ size_t charsToInsert; // number of chars to insert
+
+ if (useTabs) // if formatted with tabs
+ {
+ charsToInsert = indent; // tabs to insert
+ line.insert((size_t) 0, charsToInsert, '\t'); // insert the tabs
+ }
+ else
+ {
+ charsToInsert = indent * indentLength; // compute chars to insert
+ line.insert((size_t)0, charsToInsert, ' '); // insert the spaces
+ }
+
+ return charsToInsert;
+}
+
+/**
+ * unindent a line by a given number of tabsets
+ * by erasing the leading whitespace from the line argument.
+ *
+ * @param line a pointer to the line to unindent.
+ * @param unindent the number of tabsets to erase.
+ * @return the number of characters erased.
+ */
+int ASEnhancer::unindentLine(string &line, const int unindent) const
+{
+ size_t whitespace = line.find_first_not_of(" \t");
+
+ if (whitespace == string::npos) // if line is blank
+ whitespace = line.length(); // must remove padding, if any
+
+ if (whitespace == 0)
+ return 0;
+
+ size_t charsToErase; // number of chars to erase
+
+ if (useTabs) // if formatted with tabs
+ {
+ charsToErase = unindent; // tabs to erase
+ if (charsToErase <= whitespace) // if there is enough whitespace
+ line.erase(0, charsToErase); // erase the tabs
+ else
+ charsToErase = 0;
+ }
+ else
+ {
+ charsToErase = unindent * indentLength; // compute chars to erase
+ if (charsToErase <= whitespace) // if there is enough whitespace
+ line.erase(0, charsToErase); // erase the spaces
+ else
+ charsToErase = 0;
+ }
+
+ return charsToErase;
+}
+
+/**
+ * check if a specific line position contains a keyword.
+ *
+ * @return true if the word was found. false if the word was not found.
+ */
+bool ASEnhancer::findKeyword(const string &line, int i, const char *keyword) const
+{
+ if (line.compare(i, strlen(keyword), keyword) == 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 wordEnd = i + strlen(keyword);
+ char startCh = keyword[0]; // first char of header
+ char endCh = 0; // char just after header
+ char prevCh = 0; // char just before header
+
+ if (wordEnd < lineLength)
+ {
+ endCh = line[wordEnd];
+ }
+ if (i > 0)
+ {
+ prevCh = line[i-1];
+ }
+
+ if (prevCh != 0
+ && isLegalNameCharX(startCh)
+ && isLegalNameCharX(prevCh))
+ {
+ return false;
+ }
+ else if (wordEnd >= lineLength
+ || !isLegalNameCharX(startCh)
+ || !isLegalNameCharX(endCh))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return false;
+}
+
+} // end namespace astyle
diff --git a/lib/astyle/ASFormatter.cpp b/lib/astyle/ASFormatter.cpp
new file mode 100644
index 00000000..eb418760
--- /dev/null
+++ b/lib/astyle/ASFormatter.cpp
@@ -0,0 +1,2197 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * ASFormatter.cpp
+ *
+ * This file is a part of "Artistic Style" - an indentation and
+ * reformatting tool for C, C++, C# and Java source files.
+ * http://astyle.sourceforge.net
+ *
+ * The "Artistic Style" project, including all files needed to
+ * compile it, is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this project; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ */
+
+#include "astyle.h"
+
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#ifdef __VMS
+#include <assert>
+#else
+#include <cassert>
+#endif
+
+// can trace only if NDEBUG is not defined
+#ifndef NDEBUG
+// #define TRACEunpad
+// #define TRACEcomment
+// #define TRACEheader
+// #define TRACEbracket
+// #define TRACEarray
+#if defined(TRACEunpad) || defined(TRACEcomment) || defined(TRACEheader) \
+|| defined(TRACEbracket) || defined(TRACEarray)
+ofstream *traceOutF;
+#define TRACEF
+#endif
+#endif
+
+#ifdef TRACEunpad
+#define TRunpad(a,b,c) if(b > 0 || c > 0) *traceOutF << outLineNumber << " " << b << a << c << endl
+#else
+#define TRunpad(a,b,c) ((void)0)
+#endif
+
+#ifdef TRACEcomment
+#define TRcomment(a) *traceOutF << outLineNumber << " " << a << endl
+#else
+#define TRcomment(a) ((void)0)
+#endif
+
+#ifdef TRACEheader
+#define TRxtra(a) *traceOutF << outLineNumber << " " << a << endl
+#else
+#define TRxtra(a) ((void)0)
+#endif
+
+#ifdef TRACEbracket
+#define TRbracket(a) *traceOutF << outLineNumber << " " << a << endl
+#else
+#define TRbracket(a) ((void)0)
+#endif
+
+#ifdef TRACEarray
+#define TRarray(a) *traceOutF << outLineNumber << " " << a << endl
+#else
+#define TRarray(a) ((void)0)
+#endif
+
+#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))
+
+using namespace std;
+
+namespace astyle
+{
+vector<const string*> ASFormatter::headers;
+vector<const string*> ASFormatter::nonParenHeaders;
+vector<const string*> ASFormatter::preDefinitionHeaders;
+vector<const string*> ASFormatter::preCommandHeaders;
+vector<const string*> ASFormatter::operators;
+vector<const string*> ASFormatter::assignmentOperators;
+vector<const string*> ASFormatter::castOperators;
+
+/**
+ * Constructor of ASFormatter
+ */
+ASFormatter::ASFormatter()
+{
+ preBracketHeaderStack = NULL;
+ bracketTypeStack = NULL;
+ parenStack = NULL;
+ lineCommentNoIndent = false;
+ sourceIterator = NULL;
+ bracketFormatMode = NONE_MODE;
+ shouldPadOperators = false;
+ shouldPadParensOutside = false;
+ shouldPadParensInside = false;
+ shouldUnPadParens = false;
+ shouldBreakOneLineBlocks = true;
+ shouldBreakOneLineStatements = true;
+ shouldConvertTabs = false;
+ shouldBreakBlocks = false;
+ shouldBreakClosingHeaderBlocks = false;
+ shouldBreakClosingHeaderBrackets = false;
+ shouldBreakElseIfs = false;
+#ifdef TRACEF
+ // create a trace text file
+ string filename = "tracef.txt";
+ char* env = getenv("HOME");
+ if (env != NULL)
+ filename = string(env) + string("/tracef.txt");
+ else
+ {
+ env = getenv("USERPROFILE");
+ if (env != NULL)
+ filename = string(env) + string("\\My Documents\\tracef.txt");
+ else
+ {
+ cout << "\nCould not open tracef.txt\n" << endl;
+ exit(1);
+ }
+ }
+ traceOutF = new ofstream(filename.c_str());
+#endif
+}
+
+/**
+ * Destructor of ASFormatter
+ */
+ASFormatter::~ASFormatter()
+{
+ DELETE_CONTAINER(preBracketHeaderStack);
+#ifdef TRACEF
+ delete traceOutF;
+#endif
+}
+
+/**
+ * initialization of static data of ASFormatter.
+ */
+void ASFormatter::staticInit()
+{
+ static int formatterFileType = 9; // initialized with an invalid type
+
+ if (fileType == formatterFileType) // don't build unless necessary
+ return;
+
+ formatterFileType = fileType;
+
+ headers.clear();
+ nonParenHeaders.clear();
+ assignmentOperators.clear();
+ operators.clear();
+ preDefinitionHeaders.clear();
+ preCommandHeaders.clear();
+ castOperators.clear();
+
+ ASResource::buildHeaders(headers, fileType);
+ ASResource::buildNonParenHeaders(nonParenHeaders, fileType);
+ ASResource::buildAssignmentOperators(assignmentOperators);
+ ASResource::buildOperators(operators);
+ ASResource::buildPreDefinitionHeaders(preDefinitionHeaders);
+ ASResource::buildPreCommandHeaders(preCommandHeaders);
+ ASResource::buildCastOperators(castOperators);
+}
+
+/**
+ * initialize the ASFormatter.
+ *
+ * init() should be called every time a ASFormatter object is to start
+ * formatting 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 ASFormatter's destruction, and thus should not be
+ * deleted elsewhere.
+ *
+ * @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
+ */
+void ASFormatter::init(ASSourceIterator *si)
+{
+ staticInit();
+
+ ASBeautifier::init(si);
+ ASEnhancer::init(ASBeautifier::getIndentLength(),
+ ASBeautifier::getIndentString(),
+ ASBeautifier::getCStyle(),
+ ASBeautifier::getJavaStyle(),
+ ASBeautifier::getSharpStyle(),
+ ASBeautifier::getCaseIndent(),
+ ASBeautifier::getEmptyLineFill());
+ sourceIterator = si;
+
+ INIT_CONTAINER(preBracketHeaderStack, new vector<const string*>);
+ INIT_CONTAINER(bracketTypeStack, new vector<BracketType>);
+ bracketTypeStack->push_back(NULL_TYPE);
+ INIT_CONTAINER(parenStack, new vector<int>);
+ parenStack->push_back(0);
+
+ currentHeader = NULL;
+ currentLine = string("");
+ readyFormattedLine = string("");
+ formattedLine = "";
+ currentChar = ' ';
+ previousChar = ' ';
+ previousCommandChar = ' ';
+ previousNonWSChar = ' ';
+ quoteChar = '"';
+ charNum = 0;
+ spacePadNum = 0;
+ previousReadyFormattedLineLength = string::npos;
+ templateDepth = 0;
+ previousBracketType = NULL_TYPE;
+ previousOperator = NULL;
+
+ isVirgin = true;
+ isInLineComment = false;
+ isInComment = false;
+ isInPreprocessor = false;
+ doesLineStartComment = false;
+ isInQuote = false;
+ isSpecialChar = false;
+ isNonParenHeader = true;
+ foundNamespaceHeader = false;
+ foundClassHeader = false;
+ foundPreDefinitionHeader = false;
+ foundPreCommandHeader = false;
+ foundCastOperator = false;
+ foundQuestionMark = false;
+ isInLineBreak = false;
+ endOfCodeReached = false;
+ isLineReady = false;
+ isPreviousBracketBlockRelated = true;
+ isInPotentialCalculation = false;
+ shouldReparseCurrentChar = false;
+ passedSemicolon = false;
+ passedColon = false;
+ isInTemplate = false;
+ isInBlParen = false;
+ shouldBreakLineAfterComments = false;
+ isImmediatelyPostComment = false;
+ isImmediatelyPostLineComment = false;
+ isImmediatelyPostEmptyBlock = false;
+ isImmediatelyPostPreprocessor = false;
+
+ isPrependPostBlockEmptyLineRequested = false;
+ isAppendPostBlockEmptyLineRequested = false;
+ prependEmptyLine = false;
+ appendOpeningBracket = false;
+
+ foundClosingHeader = false;
+ previousReadyFormattedLineLength = 0;
+
+ isImmediatelyPostHeader = false;
+ isInHeader = false;
+#ifdef TRACEF
+ // fileName will be empty if ASTYLE_LIB is defined
+ if (fileName.empty())
+ *traceOutF << "new file" << endl;
+ else
+ *traceOutF << fileName << endl;
+#endif
+}
+
+/**
+ * get the next formatted line.
+ *
+ * @return formatted line.
+ */
+
+string ASFormatter::nextLine()
+{
+ // these are reset with each new line
+ const string *newHeader;
+ bool isInVirginLine = isVirgin;
+ isCharImmediatelyPostComment = false;
+ isPreviousCharPostComment = false;
+ isCharImmediatelyPostLineComment = false;
+ isCharImmediatelyPostOpenBlock = false;
+ isCharImmediatelyPostCloseBlock = false;
+ isCharImmediatelyPostTemplate = false;
+
+ while (!isLineReady)
+ {
+ if (shouldReparseCurrentChar)
+ shouldReparseCurrentChar = false;
+ else if (!getNextChar())
+ {
+ breakLine();
+ return beautify(readyFormattedLine);
+ }
+ else // stuff to do when reading a new character...
+ {
+ // make sure that a virgin '{' at the begining ofthe file will be treated as a block...
+ if (isInVirginLine && currentChar == '{')
+ previousCommandChar = '{';
+ isPreviousCharPostComment = isCharImmediatelyPostComment;
+ isCharImmediatelyPostComment = false;
+ isCharImmediatelyPostTemplate = false;
+ }
+
+ //if (inLineNumber >= 185)
+ // int x = 1;
+
+ if (isInLineComment)
+ {
+ appendCurrentChar();
+
+ // explicitely break a line when a line comment's end is found.
+ if (charNum + 1 == (int) currentLine.length())
+ {
+ isInLineBreak = true;
+ isInLineComment = false;
+ isImmediatelyPostLineComment = true;
+ currentChar = 0; //make sure it is a neutral char.
+ }
+ continue;
+ }
+ else if (isInComment)
+ {
+ if (isSequenceReached("*/"))
+ {
+ isInComment = false;
+ isImmediatelyPostComment = true;
+ appendSequence(AS_CLOSE_COMMENT);
+ goForward(1);
+ }
+ else
+ appendCurrentChar();
+
+ continue;
+ }
+
+ // not in line comment or comment
+
+ else if (isInQuote)
+ {
+ if (isSpecialChar)
+ {
+ isSpecialChar = false;
+ appendCurrentChar();
+ }
+ else if (currentChar == '\\')
+ {
+ isSpecialChar = true;
+ appendCurrentChar();
+ }
+ else if (quoteChar == currentChar)
+ {
+ isInQuote = false;
+ appendCurrentChar();
+ }
+ else
+ {
+ appendCurrentChar();
+ }
+
+ continue;
+ }
+
+ // handle white space - needed to simplify the rest.
+ if (isWhiteSpace(currentChar) || isInPreprocessor)
+ {
+ appendCurrentChar();
+ continue;
+ }
+
+ /* not in MIDDLE of quote or comment or white-space of any type ... */
+
+ if (isSequenceReached("//"))
+ {
+ if (currentLine[charNum+2] == '\xf2') // check for windows line marker
+ isAppendPostBlockEmptyLineRequested = false;
+ isInLineComment = true;
+ // do not indent if in column 1 or 2
+ if (lineCommentNoIndent == false)
+ {
+ if (charNum == 0)
+ lineCommentNoIndent = true;
+ else if (charNum == 1 && currentLine[0] == ' ')
+ lineCommentNoIndent = true;
+ }
+ // move comment if spaces were added or deleted
+ if (lineCommentNoIndent == false && spacePadNum != 0)
+ adjustComments();
+ formattedLineCommentNum = formattedLine.length();
+ appendSequence(AS_OPEN_LINE_COMMENT);
+ goForward(1);
+ // explicitely break a line when a line comment's end is found.
+ if (charNum + 1 == (int) currentLine.length())
+ {
+ isInLineBreak = true;
+ isInLineComment = false;
+ isImmediatelyPostLineComment = true;
+ currentChar = 0; //make sure it is a neutral char.
+ }
+ continue;
+ }
+ else if (isSequenceReached("/*"))
+ {
+ isInComment = true;
+ if (spacePadNum != 0)
+ adjustComments();
+ formattedLineCommentNum = formattedLine.length();
+ appendSequence(AS_OPEN_COMMENT);
+ goForward(1);
+ continue;
+ }
+ else if (currentChar == '"' || currentChar == '\'')
+ {
+ isInQuote = true;
+ quoteChar = currentChar;
+ appendCurrentChar();
+ continue;
+ }
+
+ /* not in quote or comment or white-space of any type ... */
+
+ // check if in preprocessor
+ // ** isInPreprocessor will be automatically reset at the begining
+ // of a new line in getnextChar()
+ if (currentChar == '#')
+ {
+ isInPreprocessor = true;
+ appendCurrentChar();
+ continue;
+ }
+
+ /* not in preprocessor ... */
+
+ if (isImmediatelyPostComment)
+ {
+ isImmediatelyPostComment = false;
+ isCharImmediatelyPostComment = true;
+ }
+
+ if (isImmediatelyPostLineComment)
+ {
+ isImmediatelyPostLineComment = false;
+ isCharImmediatelyPostLineComment = true;
+ }
+
+ if (shouldBreakLineAfterComments)
+ {
+ shouldBreakLineAfterComments = false;
+ shouldReparseCurrentChar = true;
+ breakLine();
+ continue;
+ }
+
+ // reset isImmediatelyPostHeader information
+ if (isImmediatelyPostHeader)
+ {
+ isImmediatelyPostHeader = false;
+
+ // Make sure headers are broken from their succeeding blocks
+ // (e.g.
+ // if (isFoo) DoBar();
+ // should become
+ // if (isFoo)
+ // DoBar;
+ // )
+ // But treat else if() as a special case which should not be broken!
+ if (shouldBreakOneLineStatements)
+ {
+ // if may break 'else if()'s, then simply break the line
+
+ if (shouldBreakElseIfs)
+ isInLineBreak = true;
+ }
+ }
+
+ if (passedSemicolon) // need to break the formattedLine
+ {
+ passedSemicolon = false;
+ if (parenStack->back() == 0 && currentChar != ';') // allow ;;
+ {
+ // does a one-line statement have ending comments?
+ if (IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE))
+ {
+ size_t blockEnd = currentLine.rfind(AS_CLOSE_BRACKET);
+ assert(blockEnd != string::npos);
+ // move ending comments to this formattedLine
+ if (isBeforeLineEndComment(blockEnd))
+ {
+ size_t commentStart = currentLine.find_first_not_of(" \t", blockEnd + 1);
+ assert(commentStart != string::npos);
+ assert((currentLine.compare(commentStart, 2, "//") == 0)
+ || (currentLine.compare(commentStart, 2, "/*") == 0));
+ size_t commentLength = currentLine.length() - commentStart;
+ int tabCount = getIndentLength();
+ appendSpacePad();
+ for (int i=1; i<tabCount; i++)
+ formattedLine.append(1, ' ');
+ formattedLine.append(currentLine, commentStart, commentLength);
+ currentLine.erase(commentStart, commentLength);
+ }
+ }
+ shouldReparseCurrentChar = true;
+ isInLineBreak = true;
+ continue;
+ }
+ }
+
+ if (passedColon)
+ {
+ passedColon = false;
+ if (parenStack->back() == 0 && !isBeforeComment())
+ {
+ shouldReparseCurrentChar = true;
+ isInLineBreak = true;
+ continue;
+ }
+ }
+
+ // Check if in template declaration, e.g. foo<bar> or foo<bar,fig>
+ // If so, set isInTemplate to true
+ if (!isInTemplate && currentChar == '<')
+ {
+ int maxTemplateDepth = 0;
+ templateDepth = 0;
+ const string *oper;
+ for (size_t i = charNum;
+ i < currentLine.length();
+ i += (oper ? oper->length() : 1))
+ {
+ oper = ASBeautifier::findHeader(currentLine, i, operators);
+
+ if (oper == &AS_LS)
+ {
+ templateDepth++;
+ maxTemplateDepth++;
+ }
+ else if (oper == &AS_GR)
+ {
+ templateDepth--;
+ if (templateDepth == 0)
+ {
+ // this is a template!
+ isInTemplate = true;
+ templateDepth = maxTemplateDepth;
+ break;
+ }
+ }
+ else if (oper == &AS_COMMA // comma, e.g. A<int, char>
+ || oper == &AS_BIT_AND // reference, e.g. A<int&>
+ || oper == &AS_MULT // pointer, e.g. A<int*>
+ || oper == &AS_COLON_COLON) // ::, e.g. std::string
+ {
+ continue;
+ }
+ else if (!isLegalNameChar(currentLine[i]) && !isWhiteSpace(currentLine[i]))
+ {
+ // this is not a template -> leave...
+ isInTemplate = false;
+ break;
+ }
+ }
+ }
+
+ // handle parenthesies
+ if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
+ {
+ parenStack->back()++;
+ if (currentChar == '[')
+ isInBlParen = true;
+ }
+ else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
+ {
+ parenStack->back()--;
+ if (isInTemplate && currentChar == '>')
+ {
+ templateDepth--;
+ if (templateDepth == 0)
+ {
+ isInTemplate = false;
+ isCharImmediatelyPostTemplate = true;
+ }
+ }
+
+ // check if this parenthesis closes a header, e.g. if (...), while (...)
+ if (isInHeader && parenStack->back() == 0)
+ {
+ isInHeader = false;
+ isImmediatelyPostHeader = true;
+ }
+ if (currentChar == ']')
+ isInBlParen = false;
+ if (currentChar == ')')
+ foundCastOperator = false;
+ }
+
+ // handle brackets
+ if (currentChar == '{' || currentChar == '}')
+ {
+ if (currentChar == '{')
+ {
+ BracketType newBracketType = getBracketType();
+ foundNamespaceHeader = false;
+ foundClassHeader = false;
+ foundPreDefinitionHeader = false;
+ foundPreCommandHeader = false;
+ isInPotentialCalculation = false;
+
+ bracketTypeStack->push_back(newBracketType);
+ preBracketHeaderStack->push_back(currentHeader);
+ currentHeader = NULL;
+
+ isPreviousBracketBlockRelated = !IS_A(newBracketType, ARRAY_TYPE);
+ }
+
+ // this must be done before the bracketTypeStack is popped
+ BracketType bracketType = bracketTypeStack->back();
+ bool isOpeningArrayBracket = (IS_A(bracketType, ARRAY_TYPE)
+ && bracketTypeStack->size() >= 2
+ && !IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], ARRAY_TYPE)
+ );
+
+ if (currentChar == '}')
+ {
+ // if a request has been made to append a post block empty line,
+ // but the block exists immediately before a closing bracket,
+ // then there is not need for the post block empty line.
+ //
+ isAppendPostBlockEmptyLineRequested = false;
+
+ if (!bracketTypeStack->empty())
+ {
+ previousBracketType = bracketTypeStack->back();
+ bracketTypeStack->pop_back();
+ isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
+ }
+
+ if (!preBracketHeaderStack->empty())
+ {
+ currentHeader = preBracketHeaderStack->back();
+ preBracketHeaderStack->pop_back();
+ }
+ else
+ currentHeader = NULL;
+ }
+
+ // format brackets
+ if (IS_A(bracketType, ARRAY_TYPE))
+ formatArrayBrackets(bracketType, isOpeningArrayBracket);
+ else
+ formatBrackets(bracketType);
+ continue;
+ }
+
+ if (((previousCommandChar == '{' && isPreviousBracketBlockRelated)
+ || (previousCommandChar == '}'
+ && bracketFormatMode != NONE_MODE
+ && !isImmediatelyPostEmptyBlock
+ && isPreviousBracketBlockRelated
+ && !isPreviousCharPostComment // Fixes wrongly appended newlines after '}' immediately after comments
+ && peekNextChar() != ' '
+ && !IS_A(previousBracketType, DEFINITION_TYPE)
+ && !(ASBeautifier::isJavaStyle && currentChar == ')'))
+ && !IS_A(bracketTypeStack->back(), DEFINITION_TYPE))
+ && (shouldBreakOneLineBlocks
+ || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE)))
+ {
+ isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
+ isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
+
+ //if (bracketFormatMode != NONE_MODE)
+ //{
+ previousCommandChar = ' ';
+ isInLineBreak = true;
+ //}
+ }
+
+ // reset block handling flags
+ isImmediatelyPostEmptyBlock = false;
+
+ // look for headers
+ if (!isInTemplate)
+ {
+ if ((newHeader = findHeader(headers)) != NULL)
+ {
+ foundClosingHeader = false;
+ const string *previousHeader;
+
+ // recognize closing headers of do..while, if..else, try..catch..finally
+ if ((newHeader == &AS_ELSE && currentHeader == &AS_IF)
+ || (newHeader == &AS_WHILE && currentHeader == &AS_DO)
+ || (newHeader == &AS_CATCH && currentHeader == &AS_TRY)
+ || (newHeader == &AS_CATCH && currentHeader == &AS_CATCH)
+ || (newHeader == &AS_FINALLY && currentHeader == &AS_TRY)
+ || (newHeader == &AS_FINALLY && currentHeader == &AS_CATCH))
+ foundClosingHeader = true;
+
+ previousHeader = currentHeader;
+ currentHeader = newHeader;
+
+ // If in ATTACH or LINUX bracket modes, attach closing headers (e.g. 'else', 'catch')
+ // to their preceding bracket,
+ // But do not perform the attachment if the shouldBreakClosingHeaderBrackets is set!
+ if (!shouldBreakClosingHeaderBrackets
+ && foundClosingHeader
+ && (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE)
+ && (shouldBreakOneLineBlocks || !IS_A(previousBracketType, SINGLE_LINE_TYPE))
+ && previousNonWSChar == '}')
+ {
+ spacePadNum = 0; // don't count as padding
+
+ size_t firstChar = formattedLine.find_first_not_of(" \t");
+ if (firstChar != string::npos) // if a blank line does not preceed this
+ {
+ isInLineBreak = false;
+ appendSpacePad();
+ }
+
+ if (shouldBreakBlocks)
+ isAppendPostBlockEmptyLineRequested = false;
+ }
+
+ // If NONE bracket mode, leave closing headers as they are (e.g. 'else', 'catch')
+ if (foundClosingHeader && bracketFormatMode == NONE_MODE && previousCommandChar == '}')
+ {
+ if (lineBeginsWith('}')) // is closing bracket broken?
+ {
+ isInLineBreak = false;
+ appendSpacePad();
+ }
+
+ if (shouldBreakBlocks)
+ isAppendPostBlockEmptyLineRequested = false;
+ }
+
+ if (foundClosingHeader && bracketFormatMode == BREAK_MODE && previousCommandChar == '}')
+ breakLine();
+
+ //Check if a template definition as been reached, e.g. template<class A>
+ //if (newHeader == &AS_TEMPLATE)
+ //{
+ // isInTemplate = true;
+ //}
+
+ // check if the found header is non-paren header
+ isNonParenHeader = (find(nonParenHeaders.begin(), nonParenHeaders.end(),
+ newHeader) != nonParenHeaders.end());
+
+ appendSequence(*currentHeader);
+ goForward(currentHeader->length() - 1);
+ // if a paren-header is found add a space after it, if needed
+ // this checks currentLine, appendSpacePad() checks formattedLine
+ if (!isNonParenHeader && charNum < (int) currentLine.length() && !isWhiteSpace(currentLine[charNum+1]))
+ appendSpacePad();
+
+ // Signal that a header has been reached
+ // *** But treat a closing while() (as in do...while)
+ // as if it where NOT a header since a closing while()
+ // should never have a block after it!
+ if (!(foundClosingHeader && currentHeader == &AS_WHILE))
+ {
+ isInHeader = true;
+ if (isNonParenHeader)
+ {
+ isImmediatelyPostHeader = true;
+ isInHeader = false;
+ }
+ }
+
+ if (currentHeader == &AS_IF && previousHeader == &AS_ELSE)
+ isInLineBreak = false;
+
+ if (shouldBreakBlocks)
+ {
+ if (previousHeader == NULL
+ && !foundClosingHeader
+ && !isCharImmediatelyPostOpenBlock)
+ {
+ isPrependPostBlockEmptyLineRequested = true;
+ }
+
+ if (currentHeader == &AS_ELSE
+ || currentHeader == &AS_CATCH
+ || currentHeader == &AS_FINALLY
+ || foundClosingHeader)
+ {
+ isPrependPostBlockEmptyLineRequested = false;
+ }
+
+ if (shouldBreakClosingHeaderBlocks
+ && isCharImmediatelyPostCloseBlock)
+ {
+ isPrependPostBlockEmptyLineRequested = true;
+ }
+
+ }
+
+ continue;
+ }
+ else if ((newHeader = findHeader(preDefinitionHeaders)) != NULL
+ && parenStack->back() == 0)
+ {
+ if (newHeader == &AS_NAMESPACE)
+ foundNamespaceHeader = true;
+ if (newHeader == &AS_CLASS)
+ foundClassHeader = true;
+ foundPreDefinitionHeader = true;
+ appendSequence(*newHeader);
+ goForward(newHeader->length() - 1);
+
+ if (shouldBreakBlocks)
+ isPrependPostBlockEmptyLineRequested = true;
+
+ continue;
+ }
+ else if ((newHeader = findHeader(preCommandHeaders)) != NULL)
+ {
+ if (ASBeautifier::isJavaStyle
+ || (*newHeader == AS_CONST && previousCommandChar == ')') // 'const' member functions is a command bracket
+ || *newHeader == AS_EXTERN)
+ foundPreCommandHeader = true;
+ appendSequence(*newHeader);
+ goForward(newHeader->length() - 1);
+
+ continue;
+ }
+ else if ((newHeader = findHeader(castOperators)) != NULL)
+ {
+ foundCastOperator = true;
+ appendSequence(*newHeader);
+ goForward(newHeader->length() - 1);
+
+ continue;
+ }
+
+ }
+
+ if (isInLineBreak) // OK to break line here
+ breakLine();
+
+ if (previousNonWSChar == '}' || currentChar == ';')
+ {
+ if (shouldBreakOneLineStatements && currentChar == ';'
+ && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE))
+ //&& (! bracketFormatMode == NONE_MODE)
+ )
+ {
+ passedSemicolon = true;
+ }
+
+ if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0)
+ {
+ isAppendPostBlockEmptyLineRequested = true;
+ }
+
+ if (currentChar != ';')
+ currentHeader = NULL;
+
+ foundQuestionMark = false;
+ foundNamespaceHeader = false;
+ foundClassHeader = false;
+ foundPreDefinitionHeader = false;
+ foundPreCommandHeader = false;
+ foundCastOperator = false;
+ isInPotentialCalculation = false;
+ isNonInStatementArray = false;
+ }
+
+ if (currentChar == ':'
+ && shouldBreakOneLineStatements
+ && !foundQuestionMark // not in a ... ? ... : ... sequence
+ && !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar
+ && previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...)
+ && previousChar != ':' // not part of '::'
+ && peekNextChar() != ':') // not part of '::'
+ {
+ passedColon = true;
+ if (shouldBreakBlocks)
+ isPrependPostBlockEmptyLineRequested = true;
+ }
+
+ if (currentChar == '?')
+ foundQuestionMark = true;
+
+ // determine if this is a potential calculation
+ newHeader = findHeader(operators);
+
+ if (newHeader != NULL)
+ {
+ if (!isInPotentialCalculation)
+ {
+ if (find(assignmentOperators.begin(), assignmentOperators.end(), newHeader)
+ != assignmentOperators.end())
+ {
+ char peekedChar = peekNextChar();
+ isInPotentialCalculation = (newHeader != &AS_RETURN
+ && !(newHeader == &AS_EQUAL && peekedChar == '*')
+ && !(newHeader == &AS_EQUAL && peekedChar == '&'));
+ }
+ }
+ }
+ else
+ {
+ // the following are not calculations
+ if (currentLine.compare(charNum, 3, "new") == 0 && !isLegalNameChar(currentLine[charNum+3]))
+ isInPotentialCalculation = false;
+ }
+
+ if (shouldPadOperators && newHeader != NULL)
+ {
+ padOperators(newHeader);
+ continue;
+ }
+
+ if ((shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens)
+ && (currentChar == '(' || currentChar == ')'))
+ {
+ padParens();
+ continue;
+ }
+
+ appendCurrentChar();
+ } // end of while loop * end of while loop * end of while loop * end of while loop
+
+ // return a beautified (i.e. correctly indented) line.
+
+ string beautifiedLine;
+ size_t readyFormattedLineLength = trim(readyFormattedLine).length();
+
+ if (prependEmptyLine // prepend a blank line before this formatted line
+ && readyFormattedLineLength > 0
+ && previousReadyFormattedLineLength > 0)
+ {
+ isLineReady = true; // signal that a readyFormattedLine is still waiting
+ beautifiedLine = beautify("");
+ previousReadyFormattedLineLength = 0;
+ }
+ else // format the current formatted line
+ {
+ isLineReady = false;
+ beautifiedLine = beautify(readyFormattedLine);
+ previousReadyFormattedLineLength = readyFormattedLineLength;
+ lineCommentNoBeautify = lineCommentNoIndent;
+ lineCommentNoIndent = false;
+ if (appendOpeningBracket) // insert bracket after this formatted line
+ {
+ appendOpeningBracket = false;
+ isLineReady = true; // signal that a readyFormattedLine is still waiting
+ readyFormattedLine = "{";
+ isPrependPostBlockEmptyLineRequested = false; // next line should not be empty
+ }
+ }
+
+ prependEmptyLine = false;
+ enhance(beautifiedLine); // call the enhancer function
+ return beautifiedLine;
+}
+
+
+/**
+* check if there are any indented lines ready to be read by nextLine()
+*
+* @return are there any indented lines ready?
+*/
+bool ASFormatter::hasMoreLines() const
+{
+ return !endOfCodeReached;
+}
+
+/**
+ * set the bracket formatting mode.
+ * options:
+ * astyle::NONE_MODE no formatting of brackets.
+ * astyle::ATTACH_MODE Java, K&R style bracket placement.
+ * astyle::BREAK_MODE ANSI C/C++ style bracket placement.
+ *
+ * @param mode the bracket formatting mode.
+ */
+void ASFormatter::setBracketFormatMode(BracketMode mode)
+{
+ bracketFormatMode = mode;
+}
+
+/**
+ * set closing header bracket breaking mode
+ * options:
+ * true brackets just before closing headers (e.g. 'else', 'catch')
+ * will be broken, even if standard brackets are attached.
+ * false closing header brackets will be treated as standard brackets.
+ *
+ * @param state the closing header bracket breaking mode.
+ */
+void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
+{
+ shouldBreakClosingHeaderBrackets = state;
+}
+
+/**
+ * set 'else if()' breaking mode
+ * options:
+ * true 'else' headers will be broken from their succeeding 'if' headers.
+ * false 'else' headers will be attached to their succeeding 'if' headers.
+ *
+ * @param state the 'else if()' breaking mode.
+ */
+void ASFormatter::setBreakElseIfsMode(bool state)
+{
+ shouldBreakElseIfs = state;
+}
+
+/**
+ * set operator padding mode.
+ * options:
+ * true statement operators will be padded with spaces around them.
+ * false statement operators will not be padded.
+ *
+ * @param state the padding mode.
+ */
+void ASFormatter::setOperatorPaddingMode(bool state)
+{
+ shouldPadOperators = state;
+}
+
+/**
+* set parenthesis outside padding mode.
+* options:
+* true statement parenthesiss will be padded with spaces around them.
+* false statement parenthesiss will not be padded.
+*
+* @param state the padding mode.
+*/
+void ASFormatter::setParensOutsidePaddingMode(bool state)
+{
+ shouldPadParensOutside = state;
+}
+
+/**
+* set parenthesis inside padding mode.
+* options:
+* true statement parenthesis will be padded with spaces around them.
+* false statement parenthesis will not be padded.
+*
+* @param state the padding mode.
+*/
+void ASFormatter::setParensInsidePaddingMode(bool state)
+{
+ shouldPadParensInside = state;
+}
+
+/**
+* set parenthesis unpadding mode.
+* options:
+* true statement parenthesis will be unpadded with spaces removed around them.
+* false statement parenthesis will not be unpadded.
+*
+* @param state the padding mode.
+*/
+void ASFormatter::setParensUnPaddingMode(bool state)
+{
+ shouldUnPadParens = state;
+}
+
+/**
+ * set option to break/not break one-line blocks
+ *
+ * @param state true = break, false = don't break.
+ */
+void ASFormatter::setBreakOneLineBlocksMode(bool state)
+{
+ shouldBreakOneLineBlocks = state;
+}
+
+/**
+ * set option to break/not break lines consisting of multiple statements.
+ *
+ * @param state true = break, false = don't break.
+ */
+void ASFormatter::setSingleStatementsMode(bool state)
+{
+ shouldBreakOneLineStatements = state;
+}
+
+/**
+ * set option to convert tabs to spaces.
+ *
+ * @param state true = convert, false = don't convert.
+ */
+void ASFormatter::setTabSpaceConversionMode(bool state)
+{
+ shouldConvertTabs = state;
+}
+
+
+/**
+ * set option to break unrelated blocks of code with empty lines.
+ *
+ * @param state true = convert, false = don't convert.
+ */
+void ASFormatter::setBreakBlocksMode(bool state)
+{
+ shouldBreakBlocks = state;
+}
+
+/**
+ * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
+ *
+ * @param state true = convert, false = don't convert.
+ */
+void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
+{
+ shouldBreakClosingHeaderBlocks = state;
+}
+
+/**
+ * jump over several characters.
+ *
+ * @param i the number of characters to jump over.
+ */
+void ASFormatter::goForward(int i)
+{
+ while (--i >= 0)
+ getNextChar();
+}
+
+/**
+* peek at the next unread character.
+*
+* @return the next unread character.
+*/
+char ASFormatter::peekNextChar() const
+{
+ char ch = ' ';
+ size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
+
+ if (peekNum == string::npos)
+ return ch;
+
+ ch = currentLine[peekNum];
+
+// if (shouldConvertTabs && ch == '\t')
+// ch = ' ';
+
+ return ch;
+}
+
+/**
+* check if current placement is before a comment or line-comment
+*
+* @return is before a comment or line-comment.
+*/
+bool ASFormatter::isBeforeComment() const
+{
+ bool foundComment = false;
+ size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
+
+ if (peekNum == string::npos)
+ return foundComment;
+
+ foundComment = (currentLine.compare(peekNum, 2, "/*") == 0
+ || currentLine.compare(peekNum, 2, "//") == 0);
+
+ return foundComment;
+}
+
+/**
+* check if current placement is before a comment or line-comment
+* if a block comment it must be at the end of the line
+*
+* @return is before a comment or line-comment.
+*/
+bool ASFormatter::isBeforeLineEndComment(int startPos) const
+{
+ bool foundLineEndComment = false;
+ size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
+
+ if (peekNum != string::npos)
+ {
+ if (currentLine.compare(peekNum, 2, "//") == 0)
+ foundLineEndComment = true;
+ else if (currentLine.compare(peekNum, 2, "/*") == 0)
+ {
+ // comment must be closed on this line with nothing after it
+ size_t endNum = currentLine.find("*/", peekNum + 2);
+ if (endNum != string::npos)
+ if (currentLine.find_first_not_of(" \t", endNum + 2) == string::npos)
+ foundLineEndComment = true;
+ }
+ }
+ return foundLineEndComment;
+}
+
+
+/**
+* get the next character, increasing the current placement in the process.
+* the new character is inserted into the variable currentChar.
+*
+* @return whether succeded to recieve the new character.
+*/
+bool ASFormatter::getNextChar()
+{
+ isInLineBreak = false;
+ previousChar = currentChar;
+
+ if (!isWhiteSpace(currentChar))
+ {
+ previousNonWSChar = currentChar;
+ if (!isInComment && !isInLineComment && !isInQuote
+ && !isImmediatelyPostComment
+ && !isImmediatelyPostLineComment
+ && !isSequenceReached("/*")
+ && !isSequenceReached("//"))
+ previousCommandChar = previousNonWSChar;
+ }
+
+ int currentLineLength = currentLine.length();
+
+ if (charNum + 1 < currentLineLength
+ && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
+ {
+ currentChar = currentLine[++charNum];
+
+ if (shouldConvertTabs && currentChar == '\t')
+ currentChar = ' ';
+
+ return true;
+ }
+ else // end of line has been reached
+ {
+ if (sourceIterator->hasMoreLines())
+ {
+ currentLine = sourceIterator->nextLine();
+ spacePadNum = 0;
+ inLineNumber++;
+
+ if (currentLine.length() == 0)
+ {
+ currentLine = string(" "); // a null is inserted if this is not done
+ }
+
+ // unless reading in the first line of the file,
+ // break a new line.
+ if (!isVirgin)
+ isInLineBreak = true;
+ else
+ isVirgin = false;
+
+ if (isInLineComment)
+ isImmediatelyPostLineComment = true;
+ isInLineComment = false;
+
+ // check if is in preprocessor before line trimming
+ isImmediatelyPostPreprocessor = isInPreprocessor;
+ if (previousNonWSChar != '\\')
+ isInPreprocessor = false;
+
+ trimNewLine();
+ currentChar = currentLine[charNum];
+
+ if (shouldConvertTabs && currentChar == '\t')
+ currentChar = ' ';
+
+ return true;
+ }
+ else
+ {
+ endOfCodeReached = true;
+ return false;
+ }
+ }
+}
+
+/**
+* jump over the leading white space in the current line,
+* IF the line does not begin a comment or is in a preprocessor definition.
+*/
+void ASFormatter::trimNewLine()
+{
+ int len = currentLine.length();
+ charNum = 0;
+
+ if (isInComment || isInPreprocessor)
+ return;
+
+ while (isWhiteSpace(currentLine[charNum]) && charNum + 1 < len)
+ ++charNum;
+
+ doesLineStartComment = false;
+ if (isSequenceReached("/*"))
+ {
+ charNum = 0;
+ doesLineStartComment = true;
+ }
+}
+
+/**
+ * append a character to the current formatted line.
+ * Unless disabled (via canBreakLine == false), first check if a
+ * line-break has been registered, and if so break the
+ * formatted line, and only then append the character into
+ * the next formatted line.
+ *
+ * @param ch the character to append.
+ * @param canBreakLine if true, a registered line-break
+ */
+void ASFormatter::appendChar(char ch, bool canBreakLine)
+{
+ if (canBreakLine && isInLineBreak)
+ breakLine();
+ formattedLine.append(1, ch);
+}
+
+/**
+ * append a string sequence to the current formatted line.
+ * Unless disabled (via canBreakLine == false), first check if a
+ * line-break has been registered, and if so break the
+ * formatted line, and only then append the sequence into
+ * the next formatted line.
+ *
+ * @param sequence the sequence to append.
+ * @param canBreakLine if true, a registered line-break
+ */
+void ASFormatter::appendSequence(const string &sequence, bool canBreakLine)
+{
+ if (canBreakLine && isInLineBreak)
+ breakLine();
+ formattedLine.append(sequence);
+}
+
+/**
+ * append a space to the current formattedline, UNLESS the
+ * last character is already a white-space character.
+ */
+void ASFormatter::appendSpacePad()
+{
+ int len = formattedLine.length();
+ if (len > 0 && !isWhiteSpace(formattedLine[len-1]))
+ {
+ formattedLine.append(1, ' ');
+ spacePadNum++;
+ }
+}
+
+/**
+ * append a space to the current formattedline, UNLESS the
+ * next character is already a white-space character.
+ */
+void ASFormatter::appendSpaceAfter()
+{
+ int len = currentLine.length();
+ if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum+1]))
+ {
+ formattedLine.append(1, ' ');
+ spacePadNum++;
+ }
+}
+
+/**
+ * register a line break for the formatted line.
+ */
+void ASFormatter::breakLine()
+{
+ isLineReady = true;
+ isInLineBreak = false;
+ spacePadNum = 0;
+ formattedLineCommentNum = string::npos;
+
+ // queue an empty line prepend request if one exists
+ prependEmptyLine = isPrependPostBlockEmptyLineRequested;
+
+ readyFormattedLine = formattedLine;
+ if (isAppendPostBlockEmptyLineRequested)
+ {
+ isAppendPostBlockEmptyLineRequested = false;
+ isPrependPostBlockEmptyLineRequested = true;
+ }
+ else
+ {
+ isPrependPostBlockEmptyLineRequested = false;
+ }
+
+ formattedLine = "";
+}
+
+/**
+ * check if the currently reached open-bracket (i.e. '{')
+ * opens a:
+ * - a definition type block (such as a class or namespace),
+ * - a command block (such as a method block)
+ * - a static array
+ * this method takes for granted that the current character
+ * is an opening bracket.
+ *
+ * @return the type of the opened block.
+ */
+BracketType ASFormatter::getBracketType() const
+{
+ BracketType returnVal;
+
+ if (foundPreDefinitionHeader)
+ {
+ returnVal = DEFINITION_TYPE;
+ if (foundNamespaceHeader)
+ returnVal = (BracketType)(returnVal | NAMESPACE_TYPE);
+ else if (foundClassHeader)
+ returnVal = (BracketType)(returnVal | CLASS_TYPE);
+ }
+ else
+ {
+ bool isCommandType = false;
+
+ if (previousNonWSChar != '=')
+ isCommandType = (foundPreCommandHeader
+ || (currentHeader != NULL && isNonParenHeader)
+ || (previousCommandChar == ')')
+ || (previousCommandChar == ':' && !foundQuestionMark)
+ || (previousCommandChar == ';')
+ || ((previousCommandChar == '{' || previousCommandChar == '}')
+ && isPreviousBracketBlockRelated));
+
+ returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
+ }
+
+ if (isOneLineBlockReached())
+ returnVal = (BracketType)(returnVal | SINGLE_LINE_TYPE);
+
+ TRbracket(returnVal);
+ return returnVal;
+}
+
+/**
+ * check if the currently reached '*' or '&' character is
+ * a pointer-or-reference symbol, or another operator.
+ * this method takes for granted that the current character
+ * is either a '*' or '&'.
+ *
+ * @return whether current character is a reference-or-pointer
+ */
+bool ASFormatter::isPointerOrReference() const
+{
+ bool isPR;
+ isPR = (!isInPotentialCalculation
+ || IS_A(bracketTypeStack->back(), DEFINITION_TYPE)
+ || (!isLegalNameChar(previousNonWSChar)
+ && previousNonWSChar != ')'
+ && previousNonWSChar != ']')
+ );
+
+ if (!isPR)
+ {
+ char nextChar = peekNextChar();
+ isPR |= (!isWhiteSpace(nextChar)
+ && nextChar != '-'
+ && nextChar != '('
+ && nextChar != '['
+ && !isLegalNameChar(nextChar));
+ }
+
+ return isPR;
+}
+
+
+/**
+ * check if the currently reached '-' character is
+ * a unary minus
+ * this method takes for granted that the current character
+ * is a '-'.
+ *
+ * @return whether the current '-' is a unary minus.
+ */
+bool ASFormatter::isUnaryMinus() const
+{
+ return ((previousOperator == &AS_RETURN || !isalnum(previousCommandChar))
+ && previousCommandChar != '.'
+ && previousCommandChar != ')'
+ && previousCommandChar != ']');
+}
+
+
+/**
+ * check if the currently reached '-' or '+' character is
+ * part of an exponent, i.e. 0.2E-5.
+ * this method takes for granted that the current character
+ * is a '-' or '+'.
+ *
+ * @return whether the current '-' is in an exponent.
+ */
+bool ASFormatter::isInExponent() const
+{
+ int formattedLineLength = formattedLine.length();
+ if (formattedLineLength >= 2)
+ {
+ char prevPrevFormattedChar = formattedLine[formattedLineLength - 2];
+ char prevFormattedChar = formattedLine[formattedLineLength - 1];
+
+ return ((prevFormattedChar == 'e' || prevFormattedChar == 'E')
+ && (prevPrevFormattedChar == '.' || isdigit(prevPrevFormattedChar)));
+ }
+ else
+ return false;
+}
+
+/**
+ * check if a one-line bracket has been reached,
+ * i.e. if the currently reached '{' character is closed
+ * with a complimentry '}' elsewhere on the current line,
+ *.
+ * @return has a one-line bracket been reached?
+ */
+bool ASFormatter::isOneLineBlockReached() const
+{
+ bool isInComment = false;
+ bool isInQuote = false;
+ int bracketCount = 1;
+ int currentLineLength = currentLine.length();
+ char quoteChar = ' ';
+
+ for (int i = charNum + 1; i < currentLineLength; ++i)
+ {
+ char ch = currentLine[i];
+
+ if (isInComment)
+ {
+ if (currentLine.compare(i, 2, "*/") == 0)
+ {
+ isInComment = false;
+ ++i;
+ }
+ continue;
+ }
+
+ if (ch == '\\')
+ {
+ ++i;
+ continue;
+ }
+
+ if (isInQuote)
+ {
+ if (ch == quoteChar)
+ isInQuote = false;
+ continue;
+ }
+
+ if (ch == '"' || ch == '\'')
+ {
+ isInQuote = true;
+ quoteChar = ch;
+ continue;
+ }
+
+ if (currentLine.compare(i, 2, "//") == 0)
+ break;
+
+ if (currentLine.compare(i, 2, "/*") == 0)
+ {
+ isInComment = true;
+ ++i;
+ continue;
+ }
+
+ if (ch == '{')
+ ++bracketCount;
+ else if (ch == '}')
+ --bracketCount;
+
+ if (bracketCount == 0)
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * check if one of a set of headers has been reached in the
+ * current position of the current line.
+ *
+ * @return a pointer to the found header. Or a NULL if no header has been reached.
+ * @param headers a vector of headers.
+ * @param checkBoundry
+ */
+const string *ASFormatter::findHeader(const vector<const string*> &headers, bool checkBoundry)
+{
+ return ASBeautifier::findHeader(currentLine, charNum, headers, checkBoundry);
+}
+
+/**
+ * check if a line begins with the specified character
+ * i.e. if the current line begins with a open bracket.
+ *
+ * @return true or false
+ */
+bool ASFormatter::lineBeginsWith(char charToCheck) const
+{
+ bool beginsWith = false;
+ size_t i = currentLine.find_first_not_of(" \t");
+
+ if (i != string::npos)
+ if (currentLine[i] == charToCheck && (int) i == charNum)
+ beginsWith = true;
+
+ return beginsWith;
+}
+
+/**
+ * adjust comment position because of adding or deleting spaces
+ * the spaces are added or deleted to formattedLine
+ * spacePadNum contains the adjustment
+ */
+void ASFormatter::adjustComments(void)
+{
+ assert(spacePadNum != 0);
+ assert(currentLine.compare(charNum, 2, "//") == 0
+ || currentLine.compare(charNum, 2, "/*") == 0);
+
+
+ // block comment must be closed on this line with nothing after it
+ if (currentLine.compare(charNum, 2, "/*") == 0)
+ {
+ size_t endNum = currentLine.find("*/", charNum + 2);
+ if (endNum == string::npos)
+ return;
+ if (currentLine.find_first_not_of(" \t", endNum + 2) != string::npos)
+ return;
+ }
+
+ size_t len = formattedLine.length();
+ // if spaces were removed, need to add spaces before the comment
+ if (spacePadNum < 0)
+ {
+ int adjust = -spacePadNum; // make the number positive
+ if (formattedLine[len-1] != '\t') // don't adjust if a tab
+ formattedLine.append(adjust, ' ');
+// else // comment out to avoid compiler warning
+// adjust = 0;
+// TRcomment(adjust); // trace macro
+ }
+ // if spaces were added, need to delete spaces before the comment, if possible
+ else if (spacePadNum > 0)
+ {
+ int adjust = spacePadNum;
+ if (formattedLine.find_last_not_of(' ') < len - adjust - 1
+ && formattedLine[len-1] != '\t') // don't adjust a tab
+ formattedLine.resize(len - adjust);
+ // the following are commented out to avoid a Borland compiler warning
+ //else
+ // adjust = 0;
+ TRcomment(-adjust); // trace macro
+ }
+}
+
+/**
+ * append the current bracket inside the end of line comments
+ * currentChar contains the bracket, it will be appended to formattedLine
+ * formattedLineCommentNum is the comment location on formattedLine
+ */
+void ASFormatter::appendCharInsideComments(void)
+{
+ if (formattedLineCommentNum == string::npos // does the comment start on the previous line?
+ || isBeforeComment()) // does a comment follow on this line?
+ {
+ appendCurrentChar(true); // don't attach
+ return;
+ }
+ assert(formattedLine.compare(formattedLineCommentNum, 2, "//") == 0
+ || formattedLine.compare(formattedLineCommentNum, 2, "/*") == 0);
+
+ // find the previous non space char
+ size_t end = formattedLineCommentNum;
+ size_t beg = formattedLine.find_last_not_of(" \t", end-1);
+ if (beg == string::npos) // is the previous line comment only?
+ {
+ appendCurrentChar(true); // don't attach
+ return;
+ }
+ beg++;
+
+ // insert the bracket
+ if (end - beg < 3) // is there room to insert?
+ formattedLine.insert(beg, 3-end+beg, ' ');
+ if (formattedLine[beg] == '\t') // don't pad with a tab
+ formattedLine.insert(beg, 1, ' ');
+ formattedLine[beg+1] = currentChar;
+}
+
+/**
+ * add or remove space padding to operators
+ * currentChar contains the paren
+ * the operators and necessary padding will be appended to formattedLine
+ * the calling function should have a continue statement after calling this method
+ *
+ * @param *newOperator the operator to be padded
+ */
+void ASFormatter::padOperators(const string *newOperator)
+{
+ assert (shouldPadOperators);
+ assert(newOperator != NULL);
+
+ bool shouldPad = (newOperator != &AS_COLON_COLON
+ && newOperator != &AS_PAREN_PAREN
+ && newOperator != &AS_BLPAREN_BLPAREN
+ && newOperator != &AS_PLUS_PLUS
+ && newOperator != &AS_MINUS_MINUS
+ && newOperator != &AS_NOT
+ && newOperator != &AS_BIT_NOT
+ && newOperator != &AS_ARROW
+ && newOperator != &AS_OPERATOR
+ && newOperator != &AS_RETURN
+ && !(newOperator == &AS_MINUS && isInExponent())
+ && !(newOperator == &AS_MINUS // check for negative number
+ && (previousNonWSChar == '('
+ || previousNonWSChar == '='
+ || previousNonWSChar == ','))
+ && !(newOperator == &AS_PLUS && isInExponent())
+ && previousOperator != &AS_OPERATOR
+ && !((newOperator == &AS_MULT || newOperator == &AS_BIT_AND)
+ && isPointerOrReference())
+ && !(newOperator == &AS_MULT
+ && (previousNonWSChar == '.'
+ || previousNonWSChar == '>')) // check for ->
+ && !((isInTemplate || isCharImmediatelyPostTemplate)
+ && (newOperator == &AS_LS || newOperator == &AS_GR))
+ );
+ // pad before operator
+ if (shouldPad
+ && !isInBlParen
+ && !(newOperator == &AS_COLON && !foundQuestionMark)
+ && newOperator != &AS_SEMICOLON
+ && newOperator != &AS_COMMA)
+ appendSpacePad();
+ appendSequence(*newOperator);
+ goForward(newOperator->length() - 1);
+
+ // since this block handles '()' and '[]',
+ // the parenStack must be updated here accordingly!
+ if (newOperator == &AS_PAREN_PAREN
+ || newOperator == &AS_BLPAREN_BLPAREN)
+ parenStack->back()--;
+
+ currentChar = (*newOperator)[newOperator->length() - 1];
+ // pad after operator
+ // but do not pad after a '-' that is a unary-minus.
+ if (shouldPad
+ && !isInBlParen
+ && !isBeforeComment()
+ && !(newOperator == &AS_MINUS && isUnaryMinus())
+ && !(currentLine.compare(charNum + 1, 1, ";") == 0)
+ && !(currentLine.compare(charNum + 1, 2, "::") == 0))
+ appendSpaceAfter();
+
+ previousOperator = newOperator;
+ return;
+}
+
+/**
+ * add or remove space padding to parens
+ * currentChar contains the paren
+ * the parens and necessary padding will be appended to formattedLine
+ * the calling function should have a continue statement after calling this method
+ */
+void ASFormatter::padParens(void)
+{
+ assert(shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens);
+ assert (currentChar == '(' || currentChar == ')');
+
+ if (currentChar == '(')
+ {
+ int spacesOutsideToDelete = formattedLine.length() - 1;
+ int spacesInsideToDelete = 0;
+
+ // compute spaces outside the opening paren to delete
+ if (shouldUnPadParens)
+ {
+ char lastChar = ' ';
+ bool prevIsParenHeader = false;
+ size_t i = formattedLine.find_last_not_of(" \t");
+ if (i != string::npos)
+ {
+ size_t end = i;
+ spacesOutsideToDelete -= i;
+ lastChar = formattedLine[i];
+ // was last word a paren header?
+ int start; // start of the previous word
+ for (start = i; start > 0; start--)
+ {
+ if (isLegalNameChar(formattedLine[start]) || formattedLine[start] == '*')
+ continue;
+ start++;
+ break;
+ }
+ string prevWord = formattedLine.substr(start, end-start+1);
+ // if previous word is a header, it will be a paren header
+ const string *prevWordH = ASBeautifier::findHeader(formattedLine, start, headers);
+ if (prevWordH != NULL)
+ {
+ prevIsParenHeader = true;
+ TRxtra(*prevWordH); // trace macro
+ }
+ else if (prevWord == "return" // don't unpad return statements
+ || prevWord == "*") // don't unpad multiply or pointer
+ {
+ prevIsParenHeader = true;
+ TRxtra(prevWord); // trace macro
+ }
+ // don't unpad variables
+ else if (prevWord == "bool"
+ || prevWord == "int"
+ || prevWord == "void"
+ || prevWord == "void*"
+ || (prevWord.length() >= 6 // check end of word for _t
+ && prevWord.compare(prevWord.length()-2, 2, "_t") == 0)
+ || prevWord == "BOOL"
+ || prevWord == "DWORD"
+ || prevWord == "HWND"
+ || prevWord == "INT"
+ || prevWord == "LPSTR"
+ || prevWord == "VOID"
+ || prevWord == "LPVOID"
+ )
+ {
+ prevIsParenHeader = true;
+ TRxtra(prevWord); // trace macro
+ }
+ }
+ // do not unpad operators, but leave them if already padded
+ if (shouldPadParensOutside || prevIsParenHeader)
+ spacesOutsideToDelete--;
+ else if (lastChar == '|' // check for ||
+ || lastChar == '&' // check for &&
+ || lastChar == ','
+ || (lastChar == '>' && !foundCastOperator)
+ || lastChar == '<'
+ || lastChar == '?'
+ || lastChar == ':'
+ || lastChar == ';'
+ || lastChar == '='
+ || lastChar == '+'
+ || lastChar == '-'
+ || (lastChar == '*' && isInPotentialCalculation)
+ || lastChar == '/'
+ || lastChar == '%')
+ spacesOutsideToDelete--;
+
+ if (spacesOutsideToDelete > 0)
+ {
+ formattedLine.erase(i + 1, spacesOutsideToDelete);
+ spacePadNum -= spacesOutsideToDelete;
+ }
+ }
+
+ // pad open paren outside
+ char peekedCharOutside = peekNextChar();
+ if (shouldPadParensOutside)
+ if (!(currentChar == '(' && peekedCharOutside == ')'))
+ appendSpacePad();
+
+ appendCurrentChar();
+
+ // unpad open paren inside
+ if (shouldUnPadParens)
+ {
+ size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
+ if (j != string::npos)
+ spacesInsideToDelete = j - charNum - 1;
+ if (shouldPadParensInside)
+ spacesInsideToDelete--;
+ if (spacesInsideToDelete > 0)
+ {
+ currentLine.erase(charNum + 1, spacesInsideToDelete);
+ spacePadNum -= spacesInsideToDelete;
+ }
+ }
+
+ // pad open paren inside
+ char peekedCharInside = peekNextChar();
+ if (shouldPadParensInside)
+ if (!(currentChar == '(' && peekedCharInside == ')'))
+ appendSpaceAfter();
+
+ TRunpad('(', spacesOutsideToDelete, spacesInsideToDelete); // trace macro
+ }
+ else if (currentChar == ')' /*|| currentChar == ']'*/)
+ {
+ int spacesOutsideToDelete = 0;
+ int spacesInsideToDelete = formattedLine.length();
+
+ // unpad close paren inside
+ if (shouldUnPadParens)
+ {
+ size_t i = formattedLine.find_last_not_of(" \t");
+ if (i != string::npos)
+ spacesInsideToDelete = formattedLine.length() - 1 - i;
+ if (shouldPadParensInside)
+ spacesInsideToDelete--;
+ if (spacesInsideToDelete > 0)
+ {
+ formattedLine.erase(i + 1, spacesInsideToDelete);
+ spacePadNum -= spacesInsideToDelete;
+ }
+ }
+
+ // pad close paren inside
+ if (shouldPadParensInside)
+ if (!(previousChar == '(' && currentChar == ')'))
+ appendSpacePad();
+
+ appendCurrentChar();
+
+ // unpad close paren outside
+ if (shouldUnPadParens)
+ {
+ // may have end of line comments
+ size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
+ if (j != string::npos)
+ if (currentLine[j] == '[' || currentLine[j] == ']')
+ spacesOutsideToDelete = j - charNum - 1;
+ if (shouldPadParensOutside)
+ spacesOutsideToDelete--;
+// spacesOutsideToDelete--; // always leave 1 space
+
+ if (spacesOutsideToDelete > 0)
+ {
+ currentLine.erase(charNum + 1, spacesOutsideToDelete);
+ spacePadNum -= spacesOutsideToDelete;
+ }
+ }
+
+ // pad close paren outside
+ char peekedCharOutside = peekNextChar();
+ if (shouldPadParensOutside)
+ if (peekedCharOutside != ';'
+ && peekedCharOutside != ','
+ && peekedCharOutside != '.'
+ && peekedCharOutside != '-') // check for ->
+// && !(currentChar == ']' && peekedCharOutside == '['))
+ appendSpaceAfter();
+
+ TRunpad(')', spacesInsideToDelete, 0 /*spacesOutsideToDelete*/); // trace macro
+ }
+ return;
+}
+
+/**
+ * format brackets as attached or broken
+ * currentChar contains the bracket
+ * the brackets will be appended to the current formattedLine or a new formattedLine as necessary
+ * the calling function should have a continue statement after calling this method
+ *
+ * @param bracketType the type of bracket to be formatted.
+ */
+void ASFormatter::formatBrackets(BracketType bracketType)
+{
+ assert(!IS_A(bracketType, ARRAY_TYPE));
+ assert (currentChar == '{' || currentChar == '}');
+
+ if (currentChar == '{')
+ {
+ parenStack->push_back(0);
+ }
+ else if (currentChar == '}')
+ {
+ if (!parenStack->empty())
+ {
+ parenStack->pop_back();
+ }
+ }
+
+ if (currentChar == '{')
+ {
+ bool bdacBreak = false;
+ // should a Linux bracket be broken?
+ if (bracketFormatMode == BDAC_MODE)
+ {
+ // always break a class
+ if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], CLASS_TYPE))
+ bdacBreak = true;
+ // break a namespace and the first bracket if a function
+ else if (bracketTypeStack->size() <= 2)
+ {
+ if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], NAMESPACE_TYPE)
+ || IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
+ bdacBreak = true;
+ }
+ // break the first bracket after a namespace if a function
+ else if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], NAMESPACE_TYPE))
+ {
+ if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
+ bdacBreak = true;
+ }
+ // if not C style then break the first bracket after a class if a function
+ else if (!ASBeautifier::isCStyle)
+ {
+ if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], CLASS_TYPE)
+ && IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
+ bdacBreak = true;
+ }
+ }
+ if (bracketFormatMode == ATTACH_MODE
+ || (bracketFormatMode == BDAC_MODE && !bdacBreak))
+ {
+ // are there comments before the bracket?
+ if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
+ {
+ if ((shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE))
+ && peekNextChar() != '}')
+ appendCharInsideComments();
+ else
+ appendCurrentChar(true); // don't attach
+ }
+ else if (previousCommandChar == '{'
+ || previousCommandChar == '}'
+ || previousCommandChar == ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
+ {
+ appendCurrentChar(true); // don't attach
+ }
+ else
+ {
+ size_t firstChar = formattedLine.find_first_not_of(" \t");
+ if (firstChar == string::npos) // if a blank line preceeds this
+ appendCurrentChar(true); // don't attach
+ else if (shouldBreakOneLineBlocks
+ || !IS_A(bracketType, SINGLE_LINE_TYPE)
+ || peekNextChar() == '}')
+ {
+ appendSpacePad();
+ appendCurrentChar(false); // OK to attach
+ }
+ else
+ appendCurrentChar(true); // don't attach
+ }
+ }
+ else if (bracketFormatMode == BREAK_MODE
+ || (bracketFormatMode == BDAC_MODE && bdacBreak))
+ {
+ if (isBeforeComment())
+ {
+ // do not break unless comment is at line end
+ if (isBeforeLineEndComment(charNum))
+ {
+ currentChar = ' '; // remove bracket from current line
+ appendOpeningBracket = true; // append bracket to following line
+ }
+ }
+ else if (!IS_A(bracketType, SINGLE_LINE_TYPE))
+ breakLine();
+ else if (shouldBreakOneLineBlocks && peekNextChar() != '}')
+ breakLine();
+
+ appendCurrentChar();
+ }
+ else if (bracketFormatMode == NONE_MODE)
+ {
+ if (lineBeginsWith('{')) // is opening bracket broken?
+ appendCurrentChar(true);
+ else
+ appendCurrentChar(false);
+ }
+ }
+ else if (currentChar == '}')
+ {
+ // mark state of immediately after empty block
+ // this state will be used for locating brackets that appear immedately AFTER an empty block (e.g. '{} \n}').
+ if (previousCommandChar == '{')
+ isImmediatelyPostEmptyBlock = true;
+
+ if ((!(previousCommandChar == '{' && isPreviousBracketBlockRelated)) // this '{' does not close an empty block
+ && (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)) // astyle is allowed to break on line blocks
+ && (!(bracketFormatMode == NONE_MODE && IS_A(bracketType, SINGLE_LINE_TYPE)))
+ && !isImmediatelyPostEmptyBlock) // this '}' does not immediately follow an empty block
+ {
+ breakLine();
+ appendCurrentChar();
+ }
+ else
+ {
+ if (!isCharImmediatelyPostComment
+ && !bracketFormatMode == NONE_MODE
+ && !isImmediatelyPostEmptyBlock)
+ isInLineBreak = false;
+
+ appendCurrentChar();
+
+ //if (!bracketFormatMode == NONE_MODE)
+ // if ((shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE))
+ // && !(currentChar == '}' && peekNextChar() == ';')) // fixes }; placed on separate lines
+ // shouldBreakLineAfterComments = true;
+ }
+
+ if (shouldBreakBlocks)
+ {
+ isAppendPostBlockEmptyLineRequested = true;
+ }
+ }
+ return;
+}
+
+/**
+ * format array brackets as attached or broken
+ * determine if the brackets can have an inStatement indent
+ * currentChar contains the bracket
+ * the brackets will be appended to the current formattedLine or a new formattedLine as necessary
+ * the calling function should have a continue statement after calling this method
+ *
+ * @param bracketType the type of bracket to be formatted, must be an ARRAY_TYPE.
+ * @param isOpeningArrayBracket indicates if this is the opening bracket for the array block.
+ */
+void ASFormatter::formatArrayBrackets(BracketType bracketType, bool isOpeningArrayBracket)
+{
+ assert(IS_A(bracketType, ARRAY_TYPE));
+ assert (currentChar == '{' || currentChar == '}');
+
+ if (currentChar == '{')
+ {
+ // is this the first opening bracket in the array?
+ if (isOpeningArrayBracket)
+ {
+ if (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE)
+ {
+ // don't attach to a preprocessor directive
+ if (isImmediatelyPostPreprocessor)
+ appendCurrentChar(true); // don't attach
+ // are there comments before the bracket?
+ else if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
+ {
+ appendCharInsideComments();
+ }
+ else
+ {
+ // if bracket is broken or not an assignment
+ if (lineBeginsWith('{') || previousNonWSChar != '=')
+ appendSpacePad();
+ appendCurrentChar(false); // OK to attach
+ }
+ }
+ else if (bracketFormatMode == BREAK_MODE)
+ {
+ if (isWhiteSpace(peekNextChar()))
+ breakLine();
+ else if (isBeforeComment())
+ {
+ // do not break unless comment is at line end
+ if (isBeforeLineEndComment(charNum))
+ {
+ currentChar = ' '; // remove bracket from current line
+ appendOpeningBracket = true; // append bracket to following line
+ }
+ }
+ appendCurrentChar();
+ }
+ else if (bracketFormatMode == NONE_MODE)
+ {
+ if (lineBeginsWith('{')) // is opening bracket broken?
+ appendCurrentChar();
+ else
+ appendCurrentChar(false);
+ }
+ }
+ else
+ appendCurrentChar(); // not the first opening bracket - don't change
+
+ // if an opening bracket ends the line there will be no inStatement indent
+ char nextChar = peekNextChar();
+ if (isWhiteSpace(nextChar)
+ || isBeforeLineEndComment(charNum)
+ || nextChar == '{')
+ isNonInStatementArray = true;
+ if (isNonInStatementArray)
+ TRarray('x');
+ else
+ TRarray(' ');
+
+ }
+ else if (currentChar == '}')
+ {
+ // does this close the first opening bracket in the array?
+ if (isOpeningArrayBracket && !IS_A(bracketType, SINGLE_LINE_TYPE) )
+ {
+ breakLine();
+ appendCurrentChar();
+ }
+ else
+ appendCurrentChar();
+ }
+}
+
+
+} // end namespace astyle
diff --git a/lib/astyle/ASResource.cpp b/lib/astyle/ASResource.cpp
new file mode 100644
index 00000000..0c554ac0
--- /dev/null
+++ b/lib/astyle/ASResource.cpp
@@ -0,0 +1,389 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * ASResource.cpp
+ *
+ * This file is a part of "Artistic Style" - an indentation and
+ * reformatting tool for C, C++, C# and Java source files.
+ * http://astyle.sourceforge.net
+ *
+ * The "Artistic Style" project, including all files needed to
+ * compile it, is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this project; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ */
+
+#include "astyle.h"
+
+
+namespace astyle
+{
+const string ASResource::AS_IF = string("if");
+const string ASResource::AS_ELSE = string("else");
+const string ASResource::AS_FOR = string("for");
+const string ASResource::AS_DO = string("do");
+const string ASResource::AS_WHILE = string("while");
+const string ASResource::AS_SWITCH = string("switch");
+const string ASResource::AS_CASE = string("case");
+const string ASResource::AS_DEFAULT = string("default");
+const string ASResource::AS_CLASS = string("class");
+const string ASResource::AS_STRUCT = string("struct");
+const string ASResource::AS_UNION = string("union");
+const string ASResource::AS_INTERFACE = string("interface");
+const string ASResource::AS_NAMESPACE = string("namespace");
+const string ASResource::AS_EXTERN = string("extern");
+const string ASResource::AS_PUBLIC = string("public");
+const string ASResource::AS_PROTECTED = string("protected");
+const string ASResource::AS_PRIVATE = string("private");
+const string ASResource::AS_STATIC = string("static");
+const string ASResource::AS_SYNCHRONIZED = string("synchronized");
+const string ASResource::AS_OPERATOR = string("operator");
+const string ASResource::AS_TEMPLATE = string("template");
+const string ASResource::AS_TRY = string("try");
+const string ASResource::AS_CATCH = string("catch");
+const string ASResource::AS_FINALLY = string("finally");
+const string ASResource::AS_THROWS = string("throws");
+const string ASResource::AS_CONST = string("const");
+
+const string ASResource::AS_ASM = string("asm");
+
+const string ASResource::AS_BAR_DEFINE = string("#define");
+const string ASResource::AS_BAR_INCLUDE = string("#include");
+const string ASResource::AS_BAR_IF = string("#if");
+const string ASResource::AS_BAR_EL = string("#el");
+const string ASResource::AS_BAR_ENDIF = string("#endif");
+
+const string ASResource::AS_OPEN_BRACKET = string("{");
+const string ASResource::AS_CLOSE_BRACKET = string("}");
+const string ASResource::AS_OPEN_LINE_COMMENT = string("//");
+const string ASResource::AS_OPEN_COMMENT = string("/*");
+const string ASResource::AS_CLOSE_COMMENT = string("*/");
+
+const string ASResource::AS_ASSIGN = string("=");
+const string ASResource::AS_PLUS_ASSIGN = string("+=");
+const string ASResource::AS_MINUS_ASSIGN = string("-=");
+const string ASResource::AS_MULT_ASSIGN = string("*=");
+const string ASResource::AS_DIV_ASSIGN = string("/=");
+const string ASResource::AS_MOD_ASSIGN = string("%=");
+const string ASResource::AS_OR_ASSIGN = string("|=");
+const string ASResource::AS_AND_ASSIGN = string("&=");
+const string ASResource::AS_XOR_ASSIGN = string("^=");
+const string ASResource::AS_GR_GR_ASSIGN = string(">>=");
+const string ASResource::AS_LS_LS_ASSIGN = string("<<=");
+const string ASResource::AS_GR_GR_GR_ASSIGN = string(">>>=");
+const string ASResource::AS_LS_LS_LS_ASSIGN = string("<<<=");
+const string ASResource::AS_RETURN = string("return");
+
+const string ASResource::AS_EQUAL = string("==");
+const string ASResource::AS_PLUS_PLUS = string("++");
+const string ASResource::AS_MINUS_MINUS = string("--");
+const string ASResource::AS_NOT_EQUAL = string("!=");
+const string ASResource::AS_GR_EQUAL = string(">=");
+const string ASResource::AS_GR_GR = string(">>");
+const string ASResource::AS_GR_GR_GR = string(">>>");
+const string ASResource::AS_LS_EQUAL = string("<=");
+const string ASResource::AS_LS_LS = string("<<");
+const string ASResource::AS_LS_LS_LS = string("<<<");
+const string ASResource::AS_ARROW = string("->");
+const string ASResource::AS_AND = string("&&");
+const string ASResource::AS_OR = string("||");
+const string ASResource::AS_COLON_COLON = string("::");
+const string ASResource::AS_PAREN_PAREN = string("()");
+const string ASResource::AS_BLPAREN_BLPAREN = string("[]");
+
+const string ASResource::AS_PLUS = string("+");
+const string ASResource::AS_MINUS = string("-");
+const string ASResource::AS_MULT = string("*");
+const string ASResource::AS_DIV = string("/");
+const string ASResource::AS_MOD = string("%");
+const string ASResource::AS_GR = string(">");
+const string ASResource::AS_LS = string("<");
+const string ASResource::AS_NOT = string("!");
+const string ASResource::AS_BIT_OR = string("|");
+const string ASResource::AS_BIT_AND = string("&");
+const string ASResource::AS_BIT_NOT = string("~");
+const string ASResource::AS_BIT_XOR = string("^");
+const string ASResource::AS_QUESTION = string("?");
+const string ASResource::AS_COLON = string(":");
+const string ASResource::AS_COMMA = string(",");
+const string ASResource::AS_SEMICOLON = string(";");
+
+const string ASResource::AS_FOREACH = string("foreach");
+const string ASResource::AS_LOCK = string("lock");
+const string ASResource::AS_UNSAFE = string("unsafe");
+const string ASResource::AS_FIXED = string("fixed");
+const string ASResource::AS_GET = string("get");
+const string ASResource::AS_SET = string("set");
+const string ASResource::AS_ADD = string("add");
+const string ASResource::AS_REMOVE = string("remove");
+
+const string ASResource::AS_CONST_CAST = string("const_cast");
+const string ASResource::AS_DYNAMIC_CAST = string("dynamic_cast");
+const string ASResource::AS_REINTERPRET_CAST = string("reinterpret_cast");
+const string ASResource::AS_STATIC_CAST = string("static_cast");
+
+
+/**
+ * Build the vector of assignment operators.
+ * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
+ *
+ * @param assignmentOperators a reference to the vector to be built.
+ */
+void ASResource::buildAssignmentOperators(vector<const string*> &assignmentOperators)
+{
+ 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);
+
+ // Java
+ assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
+ assignmentOperators.push_back(&AS_GR_GR_ASSIGN);
+ assignmentOperators.push_back(&AS_LS_LS_ASSIGN);
+
+ // Unknown
+ assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
+
+ assignmentOperators.push_back(&AS_RETURN);
+}
+
+/**
+ * Build the vector of C++ cast operators.
+ * Used by ONLY ASFormatter.cpp
+ *
+ * @param castOperators a reference to the vector to be built.
+ */
+void ASResource::buildCastOperators(vector<const string*> &castOperators)
+{
+ castOperators.push_back(&AS_CONST_CAST);
+ castOperators.push_back(&AS_DYNAMIC_CAST);
+ castOperators.push_back(&AS_REINTERPRET_CAST);
+ castOperators.push_back(&AS_STATIC_CAST);
+}
+
+/**
+ * Build the vector of header words.
+ * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
+ *
+ * @param headers a reference to the vector to be built.
+ */
+void ASResource::buildHeaders(vector<const string*> &headers, int fileType, bool beautifier)
+{
+ 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_SWITCH);
+ headers.push_back(&AS_TRY);
+ headers.push_back(&AS_CATCH);
+
+ if (beautifier)
+ {
+ headers.push_back(&AS_CASE);
+ headers.push_back(&AS_DEFAULT);
+ headers.push_back(&AS_CONST);
+ headers.push_back(&AS_STATIC);
+ headers.push_back(&AS_EXTERN);
+ headers.push_back(&AS_TEMPLATE);
+ }
+
+ if (fileType == JAVA_TYPE)
+ {
+ headers.push_back(&AS_FINALLY);
+ headers.push_back(&AS_SYNCHRONIZED);
+ }
+
+ if (fileType == SHARP_TYPE)
+ {
+ headers.push_back(&AS_FINALLY);
+ 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);
+ }
+}
+
+/**
+ * Build the vector of non-assignment operators.
+ * Used by ONLY ASBeautifier.cpp
+ *
+ * @param nonParenHeaders a reference to the vector to be built.
+ */
+void ASResource::buildNonAssignmentOperators(vector<const string*> &nonAssignmentOperators)
+{
+ 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);
+}
+
+/**
+ * Build the vector of header non-paren headers.
+ * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
+ *
+ * @param nonParenHeaders a reference to the vector to be built.
+ */
+void ASResource::buildNonParenHeaders(vector<const string*> &nonParenHeaders, int fileType, bool beautifier)
+{
+ nonParenHeaders.push_back(&AS_ELSE);
+ nonParenHeaders.push_back(&AS_DO);
+ nonParenHeaders.push_back(&AS_TRY);
+
+ if (beautifier)
+ {
+ nonParenHeaders.push_back(&AS_CASE);
+ nonParenHeaders.push_back(&AS_DEFAULT);
+ nonParenHeaders.push_back(&AS_CONST);
+ nonParenHeaders.push_back(&AS_STATIC);
+ nonParenHeaders.push_back(&AS_EXTERN);
+ nonParenHeaders.push_back(&AS_TEMPLATE);
+ }
+
+ if (fileType == JAVA_TYPE)
+ {
+ nonParenHeaders.push_back(&AS_FINALLY);
+ }
+
+ if (fileType == SHARP_TYPE)
+ {
+ nonParenHeaders.push_back(&AS_FINALLY);
+ 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);
+ }
+}
+
+/**
+ * Build the vector of operators.
+ * Used by ONLY ASFormatter.cpp
+ *
+ * @param operators a reference to the vector to be built.
+ */
+void ASResource::buildOperators(vector<const string*> &operators)
+{
+ operators.push_back(&AS_PLUS_ASSIGN);
+ operators.push_back(&AS_MINUS_ASSIGN);
+ operators.push_back(&AS_MULT_ASSIGN);
+ operators.push_back(&AS_DIV_ASSIGN);
+ operators.push_back(&AS_MOD_ASSIGN);
+ operators.push_back(&AS_OR_ASSIGN);
+ operators.push_back(&AS_AND_ASSIGN);
+ operators.push_back(&AS_XOR_ASSIGN);
+ operators.push_back(&AS_EQUAL);
+ operators.push_back(&AS_PLUS_PLUS);
+ operators.push_back(&AS_MINUS_MINUS);
+ operators.push_back(&AS_NOT_EQUAL);
+ operators.push_back(&AS_GR_EQUAL);
+ operators.push_back(&AS_GR_GR_GR_ASSIGN);
+ operators.push_back(&AS_GR_GR_ASSIGN);
+ operators.push_back(&AS_GR_GR_GR);
+ operators.push_back(&AS_GR_GR);
+ operators.push_back(&AS_LS_EQUAL);
+ operators.push_back(&AS_LS_LS_LS_ASSIGN);
+ operators.push_back(&AS_LS_LS_ASSIGN);
+ operators.push_back(&AS_LS_LS_LS);
+ operators.push_back(&AS_LS_LS);
+ operators.push_back(&AS_ARROW);
+ operators.push_back(&AS_AND);
+ operators.push_back(&AS_OR);
+ operators.push_back(&AS_COLON_COLON);
+ operators.push_back(&AS_PLUS);
+ operators.push_back(&AS_MINUS);
+ operators.push_back(&AS_MULT);
+ operators.push_back(&AS_DIV);
+ operators.push_back(&AS_MOD);
+ operators.push_back(&AS_QUESTION);
+ operators.push_back(&AS_COLON);
+ operators.push_back(&AS_ASSIGN);
+ operators.push_back(&AS_LS);
+ operators.push_back(&AS_GR);
+ operators.push_back(&AS_NOT);
+ operators.push_back(&AS_BIT_OR);
+ operators.push_back(&AS_BIT_AND);
+ operators.push_back(&AS_BIT_NOT);
+ operators.push_back(&AS_BIT_XOR);
+ operators.push_back(&AS_OPERATOR);
+ operators.push_back(&AS_COMMA);
+ operators.push_back(&AS_RETURN);
+}
+
+/**
+ * Build the vector of pre-block statements.
+ * Used by ONLY ASBeautifier.cpp
+ *
+ * @param preBlockStatements a reference to the vector to be built.
+ */
+void ASResource::buildPreBlockStatements(vector<const string*> &preBlockStatements)
+{
+ 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);
+}
+
+/**
+ * Build the vector of pre-command headers.
+ * Used by ONLY ASFormatter.cpp
+ *
+ * @param preCommandHeaders a reference to the vector to be built.
+ */
+void ASResource::buildPreCommandHeaders(vector<const string*> &preCommandHeaders)
+{
+ preCommandHeaders.push_back(&AS_EXTERN);
+ preCommandHeaders.push_back(&AS_THROWS);
+ preCommandHeaders.push_back(&AS_CONST);
+}
+
+/**
+ * Build the vector of pre-definition headers.
+ * Used by ONLY ASFormatter.cpp
+ *
+ * @param preDefinitionHeaders a reference to the vector to be built.
+ */
+void ASResource::buildPreDefinitionHeaders(vector<const string*> &preDefinitionHeaders)
+{
+ preDefinitionHeaders.push_back(&AS_CLASS);
+ preDefinitionHeaders.push_back(&AS_INTERFACE);
+ preDefinitionHeaders.push_back(&AS_NAMESPACE);
+ preDefinitionHeaders.push_back(&AS_STRUCT);
+}
+
+
+} // end namespace astyle
diff --git a/lib/astyle/Makefile.am b/lib/astyle/Makefile.am
new file mode 100644
index 00000000..dbafd18e
--- /dev/null
+++ b/lib/astyle/Makefile.am
@@ -0,0 +1,4 @@
+INCLUDES = $(all_includes)
+noinst_LTLIBRARIES = libastyle.la
+libastyle_la_LDFLAGS = $(all_libraries)
+libastyle_la_SOURCES = ASBeautifier.cpp ASEnhancer.cpp ASFormatter.cpp ASResource.cpp
diff --git a/lib/astyle/astyle.h b/lib/astyle/astyle.h
new file mode 100644
index 00000000..445aacf6
--- /dev/null
+++ b/lib/astyle/astyle.h
@@ -0,0 +1,497 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * astyle.h
+ *
+ * This file is a part of "Artistic Style" - an indentation and
+ * reformatting tool for C, C++, C# and Java source files.
+ * http://astyle.sourceforge.net
+ *
+ * The "Artistic Style" project, including all files needed to
+ * compile it, is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this project; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ */
+
+#ifndef ASTYLE_H
+#define ASTYLE_H
+
+#ifdef __VMS
+#define __USE_STD_IOSTREAM 1
+#include <sstream>
+#endif
+
+#include <string>
+#include <vector>
+#include <cctype>
+
+#include <string.h>
+
+using namespace std;
+
+
+// 4996 - secure version deprecation warnings for .NET 2005
+// 4267 - 64 bit signed/unsigned loss of data
+#ifdef _MSC_VER
+#pragma warning(disable: 4996)
+#pragma warning(disable: 4267)
+#endif
+
+namespace astyle
+{
+
+enum FileType { C_TYPE=0, JAVA_TYPE=1, SHARP_TYPE=2 };
+
+/* The enums below are not recognized by 'vectors' in Microsoft Visual C++
+ V5 when they are part of a namespace!!! Use Visual C++ V6 or higher.
+*/
+enum BracketMode { NONE_MODE, ATTACH_MODE, BREAK_MODE, BDAC_MODE };
+
+enum BracketType { NULL_TYPE = 0,
+ NAMESPACE_TYPE = 1, // also a DEFINITION_TYPE
+ CLASS_TYPE = 2, // also a DEFINITION_TYPE
+ DEFINITION_TYPE = 4,
+ COMMAND_TYPE = 8,
+ ARRAY_TYPE = 16, // arrays and enums
+ SINGLE_LINE_TYPE = 32
+ };
+
+class ASSourceIterator
+{
+ public:
+ int eolWindows;
+ int eolLinux;
+ int eolMacOld;
+ char outputEOL[4]; // output end of line char
+ ASSourceIterator() { eolWindows = eolLinux = eolMacOld = 0; }
+ virtual ~ASSourceIterator() {}
+ virtual bool hasMoreLines() const = 0;
+ virtual string nextLine() = 0;
+};
+
+class ASResource
+{
+ public:
+ void buildAssignmentOperators(vector<const string*> &assignmentOperators);
+ void buildCastOperators(vector<const string*> &castOperators);
+ void buildHeaders(vector<const string*> &headers, int fileType, bool beautifier=false);
+ void buildNonAssignmentOperators(vector<const string*> &nonAssignmentOperators);
+ void buildNonParenHeaders(vector<const string*> &nonParenHeaders, int fileType, bool beautifier=false);
+ void buildOperators(vector<const string*> &operators);
+ void buildPreBlockStatements(vector<const string*> &preBlockStatements);
+ void buildPreCommandHeaders(vector<const string*> &preCommandHeaders);
+ void buildPreDefinitionHeaders(vector<const string*> &preDefinitionHeaders);
+
+ public:
+ static const string AS_IF, AS_ELSE;
+ static const string AS_DO, AS_WHILE;
+ static const string AS_FOR;
+ static const string AS_SWITCH, AS_CASE, AS_DEFAULT;
+ static const string AS_TRY, AS_CATCH, AS_THROWS, AS_FINALLY;
+ static const string AS_PUBLIC, AS_PROTECTED, AS_PRIVATE;
+ static const string AS_CLASS, AS_STRUCT, AS_UNION, AS_INTERFACE, AS_NAMESPACE, AS_EXTERN;
+ static const string AS_STATIC;
+ static const string AS_CONST;
+ static const string AS_SYNCHRONIZED;
+ static const string AS_OPERATOR, AS_TEMPLATE;
+ static const string AS_OPEN_BRACKET, AS_CLOSE_BRACKET;
+ static const string AS_OPEN_LINE_COMMENT, AS_OPEN_COMMENT, AS_CLOSE_COMMENT;
+ static const string AS_BAR_DEFINE, AS_BAR_INCLUDE, AS_BAR_IF, AS_BAR_EL, AS_BAR_ENDIF;
+ static const string AS_RETURN;
+ static const string AS_ASSIGN, AS_PLUS_ASSIGN, AS_MINUS_ASSIGN, AS_MULT_ASSIGN;
+ static const string AS_DIV_ASSIGN, AS_MOD_ASSIGN, AS_XOR_ASSIGN, AS_OR_ASSIGN, AS_AND_ASSIGN;
+ static const string AS_GR_GR_ASSIGN, AS_LS_LS_ASSIGN, AS_GR_GR_GR_ASSIGN, AS_LS_LS_LS_ASSIGN;
+ static const string AS_EQUAL, AS_PLUS_PLUS, AS_MINUS_MINUS, AS_NOT_EQUAL, AS_GR_EQUAL, AS_GR_GR_GR, AS_GR_GR;
+ static const string AS_LS_EQUAL, AS_LS_LS_LS, AS_LS_LS, AS_ARROW, AS_AND, AS_OR;
+ static const string AS_COLON_COLON, AS_PAREN_PAREN, AS_BLPAREN_BLPAREN;
+ static const string AS_PLUS, AS_MINUS, AS_MULT, AS_DIV, AS_MOD, AS_GR, AS_LS;
+ static const string AS_NOT, AS_BIT_XOR, AS_BIT_OR, AS_BIT_AND, AS_BIT_NOT;
+ static const string AS_QUESTION, AS_COLON, AS_SEMICOLON, AS_COMMA;
+ static const string AS_ASM;
+ static const string AS_FOREACH, AS_LOCK, AS_UNSAFE, AS_FIXED;
+ static const string AS_GET, AS_SET, AS_ADD, AS_REMOVE;
+ static const string AS_CONST_CAST, AS_DYNAMIC_CAST, AS_REINTERPRET_CAST, AS_STATIC_CAST;
+};
+
+class ASBeautifier : protected ASResource
+{
+ public:
+ ASBeautifier();
+ virtual ~ASBeautifier();
+ virtual void init(ASSourceIterator* iter); // pointer to dynamically created iterator.
+ 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 setSharpStyle();
+ void setEmptyLineFill(bool state);
+ void setPreprocessorIndent(bool state);
+ int getIndentLength(void);
+ string getIndentString(void);
+ bool getCaseIndent(void);
+ bool getCStyle(void);
+ bool getJavaStyle(void);
+ bool getSharpStyle(void);
+ bool getEmptyLineFill(void);
+
+ protected:
+ int getNextProgramCharDistance(const string &line, int i);
+// bool isLegalNameChar(char ch) const;
+ const string *findHeader(const string &line, int i,
+ const vector<const string*> &possibleHeaders,
+ bool checkBoundry = true);
+ string trim(const string &str);
+ int indexOf(vector<const string*> &container, const string *element);
+ int fileType;
+ bool isCStyle;
+ bool isJavaStyle;
+ bool isSharpStyle;
+
+ // variables set by ASFormatter - must be updated in preprocessor
+ int inLineNumber; // for debugging
+ int outLineNumber; // for debugging
+ bool lineCommentNoBeautify;
+ bool isNonInStatementArray;
+
+ private:
+ ASBeautifier(const ASBeautifier &copy);
+ 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<const string*> headers;
+ static vector<const string*> nonParenHeaders;
+ static vector<const string*> preBlockStatements;
+ static vector<const string*> assignmentOperators;
+ static vector<const string*> nonAssignmentOperators;
+
+ ASSourceIterator *sourceIterator;
+ vector<ASBeautifier*> *waitingBeautifierStack;
+ vector<ASBeautifier*> *activeBeautifierStack;
+ vector<int> *waitingBeautifierStackLengthStack;
+ vector<int> *activeBeautifierStackLengthStack;
+ vector<const string*> *headerStack;
+ vector< vector<const string*>* > *tempStacks;
+ vector<int> *blockParenDepthStack;
+ vector<bool> *blockStatementStack;
+ vector<bool> *parenStatementStack;
+ vector<int> *inStatementIndentStack;
+ vector<int> *inStatementIndentStackSizeStack;
+ vector<int> *parenIndentStack;
+ vector<bool> *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 isInOperator;
+ bool isInTemplate;
+ 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;
+ bool emptyLineFill;
+ bool backslashEndsPrevLine;
+ bool blockCommentNoIndent;
+ bool blockCommentNoBeautify;
+ bool previousLineProbationTab;
+ int minConditionalIndent;
+ int parenDepth;
+ int indentLength;
+ int blockTabCount;
+ int leadingWhiteSpaces;
+ int maxInStatementIndent;
+ int templateDepth;
+ int prevFinalLineSpaceTabCount;
+ int prevFinalLineTabCount;
+ int defineTabCount;
+ char quoteChar;
+ char prevNonSpaceCh;
+ char currentNonSpaceCh;
+ char currentNonLegalCh;
+ char prevNonLegalCh;
+ char peekNextChar(string &line, int i);
+
+ protected: // inline functions
+ // check if a specific character can be used in a legal variable/method/class name
+ inline bool isLegalNameChar(char ch) const {
+ return (isalnum(ch) || ch == '.' || ch == '_' || (isJavaStyle && ch == '$') || (isCStyle && ch == '~'));
+ }
+
+ // check if a specific character is a whitespace character
+ inline bool isWhiteSpace(char ch) const {
+ return (ch == ' ' || ch == '\t');
+ }
+};
+
+
+class ASEnhancer
+{
+ public:
+ // functions
+ ASEnhancer();
+ ~ASEnhancer();
+ void init(int, string, bool, bool, bool, bool, bool);
+ void enhance(string &line);
+
+ private:
+ // set by init function
+ int indentLength;
+ bool useTabs;
+ bool isCStyle;
+ bool isJavaStyle;
+ bool isSharpStyle;
+ bool caseIndent;
+ bool emptyLineFill;
+
+ // parsing variables
+ int lineNumber;
+ bool isInQuote;
+ bool isInComment;
+ char quoteChar;
+
+ // unindent variables
+ int bracketCount;
+ int switchDepth;
+ bool lookingForCaseBracket;
+ bool unindentNextLine;
+
+ // stringstream for trace
+ stringstream *traceOut;
+
+ private: // private functions
+ bool findKeyword(const string &line, int i, const char *header) const;
+ int indentLine(string &line, const int indent) const;
+ int unindentLine(string &line, const int unindent) const;
+
+ private:
+ // struct used by ParseFormattedLine function
+ // contains variables used to unindent the case blocks
+ struct switchVariables {
+ int switchBracketCount;
+ int unindentDepth;
+ bool unindentCase;
+
+ switchVariables() { // constructor
+ switchBracketCount = 0;
+ unindentDepth = 0;
+ unindentCase = false;
+ }
+ };
+
+ private: // inline functions
+ // check if a specific character can be used in a legal variable/method/class name
+ inline bool isLegalNameCharX(char ch) const {
+ return (isalnum(ch) || ch == '.' || ch == '_' || (isJavaStyle && ch == '$') || (isCStyle && ch == '~'));
+ }
+
+ // check if a specific character is a whitespace character
+ inline bool isWhiteSpaceX(char ch) const {
+ return (ch == ' ' || ch == '\t');
+ }
+};
+
+
+class ASFormatter : public ASBeautifier, private ASEnhancer
+{
+ public:
+ ASFormatter();
+ virtual ~ASFormatter();
+ virtual void init(ASSourceIterator* iter);
+ virtual bool hasMoreLines() const;
+ virtual string nextLine();
+ void setBracketFormatMode(BracketMode mode);
+ void setBreakClosingHeaderBracketsMode(bool state);
+ void setOperatorPaddingMode(bool mode);
+ void setParensOutsidePaddingMode(bool mode);
+ void setParensInsidePaddingMode(bool mode);
+ void setParensUnPaddingMode(bool state);
+ void setBreakOneLineBlocksMode(bool state);
+ void setSingleStatementsMode(bool state);
+ void setTabSpaceConversionMode(bool state);
+ void setBreakBlocksMode(bool state);
+ void setBreakClosingHeaderBlocksMode(bool state);
+ void setBreakElseIfsMode(bool state);
+ string fileName;
+
+ private:
+ void ASformatter(ASFormatter &copy); // not to be imlpemented
+ void operator=(ASFormatter&); // not to be implemented
+ void staticInit();
+ void goForward(int i);
+ void trimNewLine();
+ char peekNextChar() const;
+ BracketType getBracketType() const;
+ bool getNextChar();
+ bool isBeforeComment() const;
+ bool isBeforeLineEndComment(int startPos) const;
+ bool isPointerOrReference() const;
+ bool isUnaryMinus() const;
+ bool isInExponent() const;
+ bool isOneLineBlockReached() const;
+// bool isNextCharWhiteSpace() const;
+ bool lineBeginsWith(char charToCheck) const;
+ void appendChar(char ch, bool canBreakLine = true);
+ void appendCharInsideComments();
+ void appendSequence(const string &sequence, bool canBreakLine = true);
+ void appendSpacePad();
+ void appendSpaceAfter();
+ void breakLine();
+ void padOperators(const string *newOperator);
+ void padParens();
+ void formatBrackets(BracketType bracketType);
+ void formatArrayBrackets(BracketType bracketType, bool isOpeningArrayBracket);
+ void adjustComments();
+ const string *findHeader(const vector<const string*> &headers, bool checkBoundry = true);
+
+ static vector<const string*> headers;
+ static vector<const string*> nonParenHeaders;
+ static vector<const string*> preDefinitionHeaders;
+ static vector<const string*> preCommandHeaders;
+ static vector<const string*> operators;
+ static vector<const string*> assignmentOperators;
+ static vector<const string*> castOperators;
+
+ ASSourceIterator *sourceIterator;
+ vector<const string*> *preBracketHeaderStack;
+ vector<BracketType> *bracketTypeStack;
+ vector<int> *parenStack;
+ string readyFormattedLine;
+ string currentLine;
+ string formattedLine;
+ const string *currentHeader;
+ const string *previousOperator; // used ONLY by pad=oper
+ char currentChar;
+ char previousChar;
+ char previousNonWSChar;
+ char previousCommandChar;
+ char quoteChar;
+ int charNum;
+ int spacePadNum;
+ int templateDepth;
+ int traceFileNumber;
+ size_t formattedLineCommentNum; // comment location on formattedLine
+ size_t previousReadyFormattedLineLength;
+ BracketMode bracketFormatMode;
+ BracketType previousBracketType;
+ bool isVirgin;
+ bool shouldPadOperators;
+ bool shouldPadParensOutside;
+ bool shouldPadParensInside;
+ bool shouldUnPadParens;
+ bool shouldConvertTabs;
+ bool isInLineComment;
+ bool isInComment;
+ bool isInPreprocessor;
+ bool isInTemplate; // true both in template definitions (e.g. template<class A>) and template usage (e.g. F<int>).
+ bool doesLineStartComment;
+ bool isInQuote;
+ bool isInBlParen;
+ bool isSpecialChar;
+ bool isNonParenHeader;
+ bool foundQuestionMark;
+ bool foundPreDefinitionHeader;
+ bool foundNamespaceHeader;
+ bool foundClassHeader;
+ bool foundPreCommandHeader;
+ bool foundCastOperator;
+ bool isInLineBreak;
+// bool isInClosingBracketLineBreak;
+ bool endOfCodeReached;
+ bool lineCommentNoIndent;
+ bool isLineReady;
+ bool isPreviousBracketBlockRelated;
+ bool isInPotentialCalculation;
+ bool isCharImmediatelyPostComment;
+ bool isPreviousCharPostComment;
+ bool isCharImmediatelyPostLineComment;
+ bool isCharImmediatelyPostOpenBlock;
+ bool isCharImmediatelyPostCloseBlock;
+ bool isCharImmediatelyPostTemplate;
+ bool shouldBreakOneLineBlocks;
+ bool shouldReparseCurrentChar;
+ bool shouldBreakOneLineStatements;
+ bool shouldBreakLineAfterComments;
+ bool shouldBreakClosingHeaderBrackets;
+ bool shouldBreakElseIfs;
+ bool passedSemicolon;
+ bool passedColon;
+ bool isImmediatelyPostComment;
+ bool isImmediatelyPostLineComment;
+ bool isImmediatelyPostEmptyBlock;
+ bool isImmediatelyPostPreprocessor;
+
+ bool shouldBreakBlocks;
+ bool shouldBreakClosingHeaderBlocks;
+ bool isPrependPostBlockEmptyLineRequested;
+ bool isAppendPostBlockEmptyLineRequested;
+
+ bool prependEmptyLine;
+ bool appendOpeningBracket;
+ bool foundClosingHeader;
+
+ bool isInHeader;
+ bool isImmediatelyPostHeader;
+
+ private: // inline functions
+ // append the CURRENT character (curentChar)to the current formatted line.
+ inline void appendCurrentChar(bool canBreakLine = true) {
+ appendChar(currentChar, canBreakLine);
+ }
+
+ // check if a specific sequence exists in the current placement of the current line
+ inline bool isSequenceReached(const char *sequence) const {
+ return currentLine.compare(charNum, strlen(sequence), sequence) == 0;
+ }
+};
+
+} // end of namespace astyle
+
+#endif // closes ASTYLE_H
+
diff --git a/lib/astyle/compiler_defines.h b/lib/astyle/compiler_defines.h
new file mode 100644
index 00000000..347ac40d
--- /dev/null
+++ b/lib/astyle/compiler_defines.h
@@ -0,0 +1,49 @@
+
+/*
+ * Copyright (c) 1998, 1999 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, 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 EITHER the "Artistic License" OR
+ * 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 EITHER the "Artistic License" or
+ * the GNU General Public License along with this program.
+ */
+
+
+
+
+
+/*
+ * comment out the line below if your compiler does NOT understand NAMESPACES
+ */
+#define USES_NAMESPACE
+
+
+#if defined(__GNUC__) && __GNUC__ < 3
+// for G++ implementation of string.compare:
+#define COMPARE(place, length, str) compare((str), (place), (length))
+#else
+// for standard implementation of string.compare:
+#define COMPARE(place, length, str) compare((place), (length), (str))
+#endif
+
+
+// Fix by John A. McNamara
+// Get rid of annoying MSVC warnings on debug builds about lengths of
+// identifiers in template instantiations.
+#ifdef _MSC_VER
+#pragma warning( disable:4786 )
+#endif
+