diff options
Diffstat (limited to 'lib/astyle')
| -rw-r--r-- | lib/astyle/ASBeautifier.cpp | 1933 | ||||
| -rw-r--r-- | lib/astyle/ASEnhancer.cpp | 483 | ||||
| -rw-r--r-- | lib/astyle/ASFormatter.cpp | 2197 | ||||
| -rw-r--r-- | lib/astyle/ASResource.cpp | 389 | ||||
| -rw-r--r-- | lib/astyle/Makefile.am | 4 | ||||
| -rw-r--r-- | lib/astyle/astyle.h | 497 | ||||
| -rw-r--r-- | lib/astyle/compiler_defines.h | 49 | 
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 ©); +		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 ©);            // 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 +  | 
