Hana 9e216da9ef go.mod: add go.mod and move pygments to third_party
After go1.16, go will use module mode by default,
even when the repository is checked out under GOPATH
or in a one-off directory. Add go.mod, go.sum to keep
this repo buildable without opting out of the module
mode.

> go mod init github.com/mmcgrana/gobyexample
> go mod tidy
> go mod vendor

In module mode, the 'vendor' directory is special
and its contents will be actively maintained by the
go command. pygments aren't the dependency the go will
know about, so it will delete the contents from vendor
directory. Move it to `third_party` directory now.

And, vendor the blackfriday package.

Note: the tutorial contents are not affected by the
change in go1.16 because all the examples in this
tutorial ask users to run the go command with the
explicit list of files to be compiled (e.g.
`go run hello-world.go` or `go build command-line-arguments.go`).
When the source list is provided, the go command does
not have to compute the build list and whether it's
running in GOPATH mode or module mode becomes irrelevant.
2021-02-15 16:45:26 -05:00

2364 lines
78 KiB
C++

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