/*************************************************************************** ansigenerator.cpp - description ------------------- begin : Jul 5 2004 copyright : (C) 2004 by André Simon email : andre.simon1@gmx.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "ansigenerator.h" using namespace std; namespace highlight { string AnsiGenerator::getOpenTag(const string&font, const string&fgCol, const string&bgCol) { ostringstream s; s << "\033["< #include #include #include #include "codegenerator.h" #include "charcodes.h" #include "version.h" namespace highlight { /** \brief This class generates ANSI escape sequences. It contains information about the resulting document structure (document header and footer), the colour system, white space handling and text formatting attributes. * @author Andre Simon */ class AnsiGenerator : public highlight::CodeGenerator { public: /** Constructor \param colourTheme Name of Colour theme to use */ AnsiGenerator( const string &colourTheme); AnsiGenerator(); ~AnsiGenerator(); /** prints document header \param title Title of the document */ string getHeader(const string & title); /** Prints document footer*/ string getFooter(); /** Prints document body*/ void printBody(); private: /** \return escaped character*/ virtual string maskCharacter(unsigned char ); /** gibt ANSI-"Tags" zurueck (Farbindex+bold+kursiv)*/ string getOpenTag(const string&font, const string&fgCol, const string&bgCol=""); string getMatchingOpenTag(unsigned int styleID); string getMatchingCloseTag(unsigned int styleID); }; } #endif /* * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved. * * ASBeautifier.cpp * by Tal Davidson (davidsont@bigfoot.com) * This file is a part of "Artistic Style" - an indentater and reformatter * of C, C, C# and Java source files. * * The "Artistic Style" project, including all files needed to compile it, * is free software; you can redistribute it and/or use it and/or modify it * under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU General Public * License along with this program. * * Patches: * 18 March 1999 - Brian Rampel - * Fixed inverse insertion of spaces vs. tabs when in -t mode. * 08 may 2004 * applied ASBeautifier.cpp.BITFIELD.patch.bz2 */ #include "compiler_defines.h" #include "ASBeautifier.h" #include #include #include #include #include #define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); } #define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container) ; } #ifdef USES_NAMESPACE using namespace std; #endif #ifdef USES_NAMESPACE namespace astyle { #endif bool ASBeautifier::calledInitStatic = false; vector ASBeautifier::headers; vector ASBeautifier::nonParenHeaders; vector ASBeautifier::preBlockStatements; vector ASBeautifier::assignmentOperators; vector ASBeautifier::nonAssignmentOperators; /* * initialize the static vars */ void ASBeautifier::initStatic() { if (calledInitStatic) return; calledInitStatic = true; headers.push_back(&AS_IF); headers.push_back(&AS_ELSE); headers.push_back(&AS_FOR); headers.push_back(&AS_WHILE); headers.push_back(&AS_DO); headers.push_back(&AS_TRY); headers.push_back(&AS_CATCH); headers.push_back(&AS_FINALLY); headers.push_back(&AS_SYNCHRONIZED); headers.push_back(&AS_SWITCH); headers.push_back(&AS_CASE); headers.push_back(&AS_DEFAULT); headers.push_back(&AS_FOREACH); headers.push_back(&AS_LOCK); headers.push_back(&AS_UNSAFE); headers.push_back(&AS_FIXED); headers.push_back(&AS_GET); headers.push_back(&AS_SET); headers.push_back(&AS_ADD); headers.push_back(&AS_REMOVE); //headers.push_back(&AS_PUBLIC); //headers.push_back(&AS_PRIVATE); //headers.push_back(&AS_PROTECTED); //headers.push_back(&AS_OPERATOR); headers.push_back(&AS_TEMPLATE); headers.push_back(&AS_CONST); /**/ headers.push_back(&AS_STATIC); headers.push_back(&AS_EXTERN); nonParenHeaders.push_back(&AS_ELSE); nonParenHeaders.push_back(&AS_DO); nonParenHeaders.push_back(&AS_TRY); nonParenHeaders.push_back(&AS_FINALLY); nonParenHeaders.push_back(&AS_STATIC); nonParenHeaders.push_back(&AS_CONST); nonParenHeaders.push_back(&AS_EXTERN); nonParenHeaders.push_back(&AS_CASE); nonParenHeaders.push_back(&AS_DEFAULT); nonParenHeaders.push_back(&AS_UNSAFE); nonParenHeaders.push_back(&AS_GET); nonParenHeaders.push_back(&AS_SET); nonParenHeaders.push_back(&AS_ADD); nonParenHeaders.push_back(&AS_REMOVE); nonParenHeaders.push_back(&AS_PUBLIC); nonParenHeaders.push_back(&AS_PRIVATE); nonParenHeaders.push_back(&AS_PROTECTED); nonParenHeaders.push_back(&AS_TEMPLATE); nonParenHeaders.push_back(&AS_CONST); /// nonParenHeaders.push_back(&AS_ASM); preBlockStatements.push_back(&AS_CLASS); preBlockStatements.push_back(&AS_STRUCT); preBlockStatements.push_back(&AS_UNION); preBlockStatements.push_back(&AS_INTERFACE); preBlockStatements.push_back(&AS_NAMESPACE); preBlockStatements.push_back(&AS_THROWS); preBlockStatements.push_back(&AS_EXTERN); assignmentOperators.push_back(&AS_ASSIGN); assignmentOperators.push_back(&AS_PLUS_ASSIGN); assignmentOperators.push_back(&AS_MINUS_ASSIGN); assignmentOperators.push_back(&AS_MULT_ASSIGN); assignmentOperators.push_back(&AS_DIV_ASSIGN); assignmentOperators.push_back(&AS_MOD_ASSIGN); assignmentOperators.push_back(&AS_OR_ASSIGN); assignmentOperators.push_back(&AS_AND_ASSIGN); assignmentOperators.push_back(&AS_XOR_ASSIGN); assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN); assignmentOperators.push_back(&AS_GR_GR_ASSIGN); assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN); assignmentOperators.push_back(&AS_LS_LS_ASSIGN); assignmentOperators.push_back(&AS_RETURN); nonAssignmentOperators.push_back(&AS_EQUAL); nonAssignmentOperators.push_back(&AS_PLUS_PLUS); nonAssignmentOperators.push_back(&AS_MINUS_MINUS); nonAssignmentOperators.push_back(&AS_NOT_EQUAL); nonAssignmentOperators.push_back(&AS_GR_EQUAL); nonAssignmentOperators.push_back(&AS_GR_GR_GR); nonAssignmentOperators.push_back(&AS_GR_GR); nonAssignmentOperators.push_back(&AS_LS_EQUAL); nonAssignmentOperators.push_back(&AS_LS_LS_LS); nonAssignmentOperators.push_back(&AS_LS_LS); nonAssignmentOperators.push_back(&AS_ARROW); nonAssignmentOperators.push_back(&AS_AND); nonAssignmentOperators.push_back(&AS_OR); } /** * ASBeautifier's constructor */ ASBeautifier::ASBeautifier() { initStatic(); waitingBeautifierStack = NULL; activeBeautifierStack = NULL; waitingBeautifierStackLengthStack = NULL; activeBeautifierStackLengthStack = NULL; headerStack = NULL; tempStacks = NULL; blockParenDepthStack = NULL; blockStatementStack = NULL; parenStatementStack = NULL; bracketBlockStateStack = NULL; inStatementIndentStack = NULL; inStatementIndentStackSizeStack = NULL; parenIndentStack = NULL; sourceIterator = NULL; isMinimalConditinalIndentSet = false; shouldForceTabIndentation = false; setSpaceIndentation(4); setMaxInStatementIndentLength(40); setClassIndent(false); setSwitchIndent(false); setCaseIndent(false); setBlockIndent(false); setBracketIndent(false); setNamespaceIndent(false); setLabelIndent(false); setEmptyLineFill(false); setCStyle(); setPreprocessorIndent(false); } ASBeautifier::ASBeautifier(const ASBeautifier &other) { waitingBeautifierStack = NULL; activeBeautifierStack = NULL; waitingBeautifierStackLengthStack = NULL; activeBeautifierStackLengthStack = NULL; headerStack = new vector; *headerStack = *other.headerStack; tempStacks = new vector< vector* >; vector< vector* >::iterator iter; for (iter = other.tempStacks->begin(); iter != other.tempStacks->end(); ++iter) { vector *newVec = new vector; *newVec = **iter; tempStacks->push_back(newVec); } blockParenDepthStack = new vector; *blockParenDepthStack = *other.blockParenDepthStack; blockStatementStack = new vector; *blockStatementStack = *other.blockStatementStack; parenStatementStack = new vector; *parenStatementStack = *other.parenStatementStack; bracketBlockStateStack = new vector; *bracketBlockStateStack = *other.bracketBlockStateStack; inStatementIndentStack = new vector; *inStatementIndentStack = *other.inStatementIndentStack; inStatementIndentStackSizeStack = new vector; *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack; parenIndentStack = new vector; *parenIndentStack = *other.parenIndentStack; sourceIterator = other.sourceIterator; indentString = other.indentString; currentHeader = other.currentHeader; previousLastLineHeader = other.previousLastLineHeader; immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp; isInQuote = other.isInQuote; isInComment = other.isInComment; isInCase = other.isInCase; isInQuestion = other.isInQuestion; isInStatement =other. isInStatement; isInHeader = other.isInHeader; isCStyle = other.isCStyle; isInOperator = other.isInOperator; isInTemplate = other.isInTemplate; isInConst = other.isInConst; classIndent = other.classIndent; isInClassHeader = other.isInClassHeader; isInClassHeaderTab = other.isInClassHeaderTab; switchIndent = other.switchIndent; caseIndent = other.caseIndent; namespaceIndent = other.namespaceIndent; bracketIndent = other.bracketIndent; blockIndent = other.blockIndent; labelIndent = other.labelIndent; preprocessorIndent = other.preprocessorIndent; parenDepth = other.parenDepth; indentLength = other.indentLength; blockTabCount = other.blockTabCount; leadingWhiteSpaces = other.leadingWhiteSpaces; maxInStatementIndent = other.maxInStatementIndent; templateDepth = other.templateDepth; quoteChar = other.quoteChar; prevNonSpaceCh = other.prevNonSpaceCh; currentNonSpaceCh = other.currentNonSpaceCh; currentNonLegalCh = other.currentNonLegalCh; prevNonLegalCh = other.prevNonLegalCh; isInConditional = other.isInConditional; minConditionalIndent = other.minConditionalIndent; prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount; prevFinalLineTabCount = other.prevFinalLineTabCount; emptyLineFill = other.emptyLineFill; probationHeader = other.probationHeader; isInDefine = other.isInDefine; isInDefineDefinition = other.isInDefineDefinition; backslashEndsPrevLine = other.backslashEndsPrevLine; defineTabCount = other.defineTabCount; } /** * ASBeautifier's destructor */ ASBeautifier::~ASBeautifier() { DELETE_CONTAINER( headerStack ); DELETE_CONTAINER( tempStacks ); DELETE_CONTAINER( blockParenDepthStack ); DELETE_CONTAINER( blockStatementStack ); DELETE_CONTAINER( parenStatementStack ); DELETE_CONTAINER( bracketBlockStateStack ); DELETE_CONTAINER( inStatementIndentStack ); DELETE_CONTAINER( inStatementIndentStackSizeStack ); DELETE_CONTAINER( parenIndentStack ); // DELETE_CONTAINER( sourceIterator ); } /** * initialize the ASBeautifier. * * init() should be called every time a ABeautifier object is to start * beautifying a NEW source file. * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object * that will be used to iterate through the source code. This object will be * deleted during the ASBeautifier's destruction, and thus should not be * deleted elsewhere. * * @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object. */ void ASBeautifier::init(ASSourceIterator *iter) { sourceIterator = iter; init(); } /** * initialize the ASBeautifier. */ void ASBeautifier::init() { INIT_CONTAINER( waitingBeautifierStack, new vector ); INIT_CONTAINER( activeBeautifierStack, new vector ); INIT_CONTAINER( waitingBeautifierStackLengthStack, new vector ); INIT_CONTAINER( activeBeautifierStackLengthStack, new vector ); INIT_CONTAINER( headerStack, new vector ); INIT_CONTAINER( tempStacks, new vector< vector* > ); tempStacks->push_back(new vector); INIT_CONTAINER( blockParenDepthStack, new vector ); INIT_CONTAINER( blockStatementStack, new vector ); INIT_CONTAINER( parenStatementStack, new vector ); INIT_CONTAINER( bracketBlockStateStack, new vector ); bracketBlockStateStack->push_back(true); INIT_CONTAINER( inStatementIndentStack, new vector ); INIT_CONTAINER( inStatementIndentStackSizeStack, new vector ); inStatementIndentStackSizeStack->push_back(0); INIT_CONTAINER( parenIndentStack, new vector ); immediatelyPreviousAssignmentOp = NULL; previousLastLineHeader = NULL; isInQuote = false; isInComment = false; isInStatement = false; isInCase = false; isInQuestion = false; isInClassHeader = false; isInClassHeaderTab = false; isInHeader = false; isInOperator = false; isInTemplate = false; isInConst = false; isInConditional = false; templateDepth = 0; parenDepth=0; blockTabCount = 0; leadingWhiteSpaces = 0; prevNonSpaceCh = '{'; currentNonSpaceCh = '{'; prevNonLegalCh = '{'; currentNonLegalCh = '{'; prevFinalLineSpaceTabCount = 0; prevFinalLineTabCount = 0; probationHeader = NULL; backslashEndsPrevLine = false; isInDefine = false; isInDefineDefinition = false; defineTabCount = 0; } /** * set indentation style to ANSI C/C++. */ void ASBeautifier::setCStyle() { isCStyle = true; } /** * set indentation style to Java / K&R. */ void ASBeautifier::setJavaStyle() { isCStyle = false; } /** * indent using one tab per indentation */ void ASBeautifier::setTabIndentation(int length, bool forceTabs) { indentString = "\t"; indentLength = length; shouldForceTabIndentation = forceTabs; if (!isMinimalConditinalIndentSet) minConditionalIndent = indentLength * 2; } /** * indent using a number of spaces per indentation. * * @param length number of spaces per indent. */ void ASBeautifier::setSpaceIndentation(int length) { indentString=string(length, ' '); indentLength = length; if (!isMinimalConditinalIndentSet) minConditionalIndent = indentLength * 2; } /** * set the maximum indentation between two lines in a multi-line statement. * * @param max maximum indentation length. */ void ASBeautifier::setMaxInStatementIndentLength(int max) { maxInStatementIndent = max; } /** * set the minimum indentation between two lines in a multi-line condition. * * @param min minimal indentation length. */ void ASBeautifier::setMinConditionalIndentLength(int min) { minConditionalIndent = min; isMinimalConditinalIndentSet = true; } /** * set the state of the bracket indentation option. If true, brackets will * be indented one additional indent. * * @param state state of option. */ void ASBeautifier::setBracketIndent(bool state) { bracketIndent = state; } /** * set the state of the block indentation option. If true, entire blocks * will be indented one additional indent, similar to the GNU indent style. * * @param state state of option. */ void ASBeautifier::setBlockIndent(bool state) { if (state) setBracketIndent(false); // so that we don't have both bracket and block indent blockIndent = state; } /** * set the state of the class indentation option. If true, C++ class * definitions will be indented one additional indent. * * @param state state of option. */ void ASBeautifier::setClassIndent(bool state) { classIndent = state; } /** * set the state of the switch indentation option. If true, blocks of 'switch' * statements will be indented one additional indent. * * @param state state of option. */ void ASBeautifier::setSwitchIndent(bool state) { switchIndent = state; } /** * set the state of the case indentation option. If true, lines of 'case' * statements will be indented one additional indent. * * @param state state of option. */ void ASBeautifier::setCaseIndent(bool state) { caseIndent = state; } /** * set the state of the namespace indentation option. * If true, blocks of 'namespace' statements will be indented one * additional indent. Otherwise, NO indentation will be added. * * @param state state of option. */ void ASBeautifier::setNamespaceIndent(bool state) { namespaceIndent = state; } /** * set the state of the label indentation option. * If true, labels will be indented one indent LESS than the * current indentation level. * If false, labels will be flushed to the left with NO * indent at all. * * @param state state of option. */ void ASBeautifier::setLabelIndent(bool state) { labelIndent = state; } /** * set the state of the preprocessor indentation option. * If true, multiline #define statements will be indented. * * @param state state of option. */ void ASBeautifier::setPreprocessorIndent(bool state) { preprocessorIndent = state; } /** * set the state of the empty line fill option. * If true, empty lines will be filled with the whitespace. * of their previous lines. * If false, these lines will remain empty. * * @param state state of option. */ void ASBeautifier::setEmptyLineFill(bool state) { emptyLineFill = state; } /** * check if there are any indented lines ready to be read by nextLine() * * @return are there any indented lines ready? */ bool ASBeautifier::hasMoreLines() const { return sourceIterator->hasMoreLines(); } /** * get the next indented line. * * @return indented line. */ string ASBeautifier::nextLine() { return beautify(sourceIterator->nextLine()); } /** * beautify a line of source code. * every line of source code in a source code file should be sent * one after the other to the beautify method. * * @return the indented line. * @param originalLine the original unindented line. */ string ASBeautifier::beautify(const string &originalLine) { string line; bool isInLineComment = false; bool lineStartsInComment = false; bool isInClass = false; bool isInSwitch = false; bool isImmediatelyAfterConst = false; bool isSpecialChar = false; char ch = ' '; char prevCh; string outBuffer; // the newly idented line is bufferd here int tabCount = 0; const string *lastLineHeader = NULL; bool closingBracketReached = false; int spaceTabCount = 0; char tempCh; unsigned int headerStackSize = headerStack->size(); //bool isLineInStatement = isInStatement; bool shouldIndentBrackettedLine = true; int lineOpeningBlocksNum = 0; int lineClosingBlocksNum = 0; bool previousLineProbation = (probationHeader != NULL); unsigned int i; currentHeader = NULL; lineStartsInComment = isInComment; // handle and remove white spaces around the line: // If not in comment, first find out size of white space before line, // so that possible comments starting in the line continue in // relation to the preliminary white-space. if (!isInComment) { leadingWhiteSpaces = 0; while (leadingWhiteSpacesinit(); //defineBeautifier->isInDefineDefinition = true; //defineBeautifier->beautify(""); activeBeautifierStack->push_back(defineBeautifier); } else { // the is the cloned beautifier that is in charge of indenting the #define. isInDefine = true; } } else if (preproc.COMPARE(0, 2, string("if")) == 0) { // push a new beautifier into the stack waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size()); activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size()); waitingBeautifierStack->push_back(new ASBeautifier(*this)); } else if (preproc.COMPARE(0, 4/*2*/, string("else")) == 0) { if (!waitingBeautifierStack->empty()) { // MOVE current waiting beautifier to active stack. activeBeautifierStack->push_back(waitingBeautifierStack->back()); waitingBeautifierStack->pop_back(); } } else if (preproc.COMPARE(0, 4, string("elif")) == 0) { if (!waitingBeautifierStack->empty()) { // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original. activeBeautifierStack->push_back( new ASBeautifier( *(waitingBeautifierStack->back()) ) ); } } else if (preproc.COMPARE(0, 5, string("endif")) == 0) { unsigned int stackLength; ASBeautifier *beautifier; if (!waitingBeautifierStackLengthStack->empty()) { stackLength = waitingBeautifierStackLengthStack->back(); waitingBeautifierStackLengthStack->pop_back(); while (waitingBeautifierStack->size() > stackLength) { beautifier = waitingBeautifierStack->back(); waitingBeautifierStack->pop_back(); delete beautifier; } } if (!activeBeautifierStackLengthStack->empty()) { stackLength = activeBeautifierStackLengthStack->back(); activeBeautifierStackLengthStack->pop_back(); while (activeBeautifierStack->size() > stackLength) { beautifier = activeBeautifierStack->back(); activeBeautifierStack->pop_back(); delete beautifier; } } } } // check if the last char is a backslash if(line.length() > 0) backslashEndsPrevLine = (line[line.length() - 1] == '\\'); else backslashEndsPrevLine = false; // check if this line ends a multi-line #define // if so, use the #define's cloned beautifier for the line's indentation // and then remove it from the active beautifier stack and delete it. if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine) { string beautifiedLine; ASBeautifier *defineBeautifier; isInDefineDefinition = false; defineBeautifier = activeBeautifierStack->back(); activeBeautifierStack->pop_back(); beautifiedLine = defineBeautifier->beautify(line); delete defineBeautifier; return beautifiedLine; } // unless this is a multi-line #define, return this precompiler line as is. if (!isInDefine && !isInDefineDefinition) return originalLine; } // if there exists any worker beautifier in the activeBeautifierStack, // then use it instead of me to indent the current line. if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty()) { return activeBeautifierStack->back()->beautify(line); } // calculate preliminary indentation based on data from past lines if (!inStatementIndentStack->empty()) spaceTabCount = inStatementIndentStack->back(); for (i=0; i0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET && (*headerStack)[i] == &AS_OPEN_BRACKET))) ++tabCount; if (isCStyle && !namespaceIndent && i >= 1 && (*headerStack)[i-1] == &AS_NAMESPACE && (*headerStack)[i] == &AS_OPEN_BRACKET) --tabCount; if (isCStyle && i >= 1 && (*headerStack)[i-1] == &AS_CLASS && (*headerStack)[i] == &AS_OPEN_BRACKET ) { if (classIndent) ++tabCount; isInClass = true; } // is the switchIndent option is on, indent switch statements an additional indent. else if (switchIndent && i > 1 && (*headerStack)[i-1] == &AS_SWITCH && (*headerStack)[i] == &AS_OPEN_BRACKET ) { ++tabCount; isInSwitch = true; } } if (!lineStartsInComment && isCStyle && isInClass && classIndent && headerStackSize >= 2 &&(*headerStack)[headerStackSize-2] == &AS_CLASS && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET && line[0] == '}') --tabCount; else if (!lineStartsInComment && isInSwitch && switchIndent && headerStackSize >= 2 && (*headerStack)[headerStackSize-2] == &AS_SWITCH && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET && line[0] == '}') --tabCount; if (isInClassHeader) { isInClassHeaderTab = true; tabCount += 2; } if (isInConditional) { --tabCount; } // parse characters in the current line. for (i=0; ipush_back(probationHeader); // handle the specific probation header isInConditional = (probationHeader == &AS_SYNCHRONIZED); if (probationHeader == &AS_CONST) isImmediatelyAfterConst = true; // isInConst = true; /* TODO: * There is actually no more need for the global isInConst variable. * The only reason for checking const is to see if there is a const * immediately before an open-bracket. * Since CONST is now put into probation and is checked during itspost-char, * isImmediatelyAfterConst can be set by its own... */ isInStatement = false; // if the probation comes from the previous line, then indent by 1 tab count. if (previousLineProbation && ch == '{') tabCount++; previousLineProbation = false; } // dismiss the probation header probationHeader = NULL; } prevNonSpaceCh = currentNonSpaceCh; currentNonSpaceCh = ch; if (!isLegalNameChar(ch) && ch != ',' && ch != ';' ) { prevNonLegalCh = currentNonLegalCh; currentNonLegalCh = ch; } //if (isInConst) //{ // isInConst = false; // isImmediatelyAfterConst = true; //} if (isInHeader) { isInHeader = false; currentHeader = headerStack->back(); } else currentHeader = NULL; if (isCStyle && isInTemplate && (ch == '<' || ch == '>') && findHeader(line, i, nonAssignmentOperators) == NULL) //; { if (ch == '<') { ++templateDepth; } else if (ch == '>') { if (--templateDepth <= 0) { if (isInTemplate) ch = ';'; else ch = 't'; isInTemplate = false; templateDepth = 0; } } } // handle parenthesies if (ch == '(' || ch == '[' || ch == ')' || ch == ']') { if (ch == '(' || ch == '[') { if (parenDepth == 0) { parenStatementStack->push_back(isInStatement); isInStatement = true; } parenDepth++; inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); if (currentHeader != NULL) registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true); else registerInStatementIndent(line, i, spaceTabCount, 0, true); } else if (ch == ')' || ch == ']') { parenDepth--; if (parenDepth == 0) { isInStatement = parenStatementStack->back(); parenStatementStack->pop_back(); ch = ' '; isInConditional = false; } if (!inStatementIndentStackSizeStack->empty()) { unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back(); inStatementIndentStackSizeStack->pop_back(); while (previousIndentStackSize < inStatementIndentStack->size()) inStatementIndentStack->pop_back(); if (!parenIndentStack->empty()) { int poppedIndent = parenIndentStack->back(); parenIndentStack->pop_back(); if (i == 0) spaceTabCount = poppedIndent; } } } continue; } if (ch == '{') { bool isBlockOpener = false; // first, check if '{' is a block-opener or an static-array opener isBlockOpener = ( (prevNonSpaceCh == '{' && bracketBlockStateStack->back()) || prevNonSpaceCh == '}' || prevNonSpaceCh == ')' || prevNonSpaceCh == ';' || isInClassHeader || isBlockOpener || isImmediatelyAfterConst || (isInDefine && (prevNonSpaceCh == '(' || prevNonSpaceCh == '_' || isalnum(prevNonSpaceCh))) ); isInClassHeader = false; if (!isBlockOpener && currentHeader != NULL) { for (unsigned int n=0; n < nonParenHeaders.size(); n++) if (currentHeader == nonParenHeaders[n]) { isBlockOpener = true; break; } } bracketBlockStateStack->push_back(isBlockOpener); if (!isBlockOpener) { inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); registerInStatementIndent(line, i, spaceTabCount, 0, true); parenDepth++; if (i == 0) shouldIndentBrackettedLine = false; continue; } // this bracket is a block opener... ++lineOpeningBlocksNum; if (isInClassHeader) isInClassHeader = false; if (isInClassHeaderTab) { isInClassHeaderTab = false; tabCount -= 2; } blockParenDepthStack->push_back(parenDepth); blockStatementStack->push_back(isInStatement); inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); blockTabCount += isInStatement? 1 : 0; parenDepth = 0; isInStatement = false; tempStacks->push_back(new vector); headerStack->push_back(&AS_OPEN_BRACKET); lastLineHeader = &AS_OPEN_BRACKET; // <------ continue; } //check if a header has been reached if (prevCh == ' ') { bool isIndentableHeader = true; const string *newHeader = findHeader(line, i, headers); if (newHeader != NULL) { // if we reached here, then this is a header... isInHeader = true; vector *lastTempStack; if (tempStacks->empty()) lastTempStack = NULL; else lastTempStack = tempStacks->back(); // if a new block is opened, push a new stack into tempStacks to hold the // future list of headers in the new block. // take care of the special case: 'else if (...)' if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE) { //spaceTabCount += indentLength; // to counter the opposite addition that occurs when the 'if' is registered below... headerStack->pop_back(); } // take care of 'else' else if (newHeader == &AS_ELSE) { if (lastTempStack != NULL) { int indexOfIf = indexOf(*lastTempStack, &AS_IF); // <--- if (indexOfIf != -1) { // recreate the header list in headerStack up to the previous 'if' // from the temporary snapshot stored in lastTempStack. int restackSize = lastTempStack->size() - indexOfIf - 1; for (int r=0; rpush_back(lastTempStack->back()); lastTempStack->pop_back(); } if (!closingBracketReached) tabCount += restackSize; } /* * If the above if is not true, i.e. no 'if' before the 'else', * then nothing beautiful will come out of this... * I should think about inserting an Exception here to notify the caller of this... */ } } // check if 'while' closes a previous 'do' else if (newHeader == &AS_WHILE) { if (lastTempStack != NULL) { int indexOfDo = indexOf(*lastTempStack, &AS_DO); // <--- if (indexOfDo != -1) { // recreate the header list in headerStack up to the previous 'do' // from the temporary snapshot stored in lastTempStack. int restackSize = lastTempStack->size() - indexOfDo - 1; for (int r=0; rpush_back(lastTempStack->back()); lastTempStack->pop_back(); } if (!closingBracketReached) tabCount += restackSize; } } } // check if 'catch' closes a previous 'try' or 'catch' else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY) { if (lastTempStack != NULL) { int indexOfTry = indexOf(*lastTempStack, &AS_TRY); if (indexOfTry == -1) indexOfTry = indexOf(*lastTempStack, &AS_CATCH); if (indexOfTry != -1) { // recreate the header list in headerStack up to the previous 'try' // from the temporary snapshot stored in lastTempStack. int restackSize = lastTempStack->size() - indexOfTry - 1; for (int r=0; rpush_back(lastTempStack->back()); lastTempStack->pop_back(); } if (!closingBracketReached) tabCount += restackSize; } } } else if (newHeader == &AS_CASE) { isInCase = true; if (!caseIndent) --tabCount; } else if(newHeader == &AS_DEFAULT) { isInCase = true; if (!caseIndent) --tabCount; } else if (newHeader == &AS_PUBLIC || newHeader == &AS_PROTECTED || newHeader == &AS_PRIVATE) { if (isCStyle && !isInClassHeader) --tabCount; isIndentableHeader = false; } //else if ((newHeader == &STATIC || newHeader == &SYNCHRONIZED) && // !headerStack->empty() && // (headerStack->back() == &STATIC || headerStack->back() == &SYNCHRONIZED)) //{ // isIndentableHeader = false; //} else if (newHeader == &AS_STATIC || newHeader == &AS_SYNCHRONIZED || (newHeader == &AS_CONST && isCStyle)) { if (!headerStack->empty() && (headerStack->back() == &AS_STATIC || headerStack->back() == &AS_SYNCHRONIZED || headerStack->back() == &AS_CONST)) { isIndentableHeader = false; } else { isIndentableHeader = false; probationHeader = newHeader; } } else if (newHeader == &AS_CONST) { // this will be entered only if NOT in C style // since otherwise the CONST would be found to be a probstion header... //if (isCStyle) // isInConst = true; isIndentableHeader = false; } /* else if (newHeader == &OPERATOR) { if (isCStyle) isInOperator = true; isIndentableHeader = false; } */ else if (newHeader == &AS_TEMPLATE) { if (isCStyle) isInTemplate = true; isIndentableHeader = false; } if (isIndentableHeader) { // 3.2.99 //spaceTabCount-=indentLength; headerStack->push_back(newHeader); isInStatement = false; if (indexOf(nonParenHeaders, newHeader) == -1) { isInConditional = true; } lastLineHeader = newHeader; } else isInHeader = false; //lastLineHeader = newHeader; outBuffer.append(newHeader->substr(1)); i += newHeader->length() - 1; continue; } } if (isCStyle && !isalpha(prevCh) && line.COMPARE(i, 8, AS_OPERATOR) == 0 && !isalnum(line[i+8])) { isInOperator = true; outBuffer.append(AS_OPERATOR.substr(1)); i += 7; continue; } if (ch == '?') isInQuestion = true; // special handling of 'case' statements if (ch == ':') { if (line.length() > i+1 && line[i+1] == ':') // look for :: { ++i; outBuffer.append(1, ':'); ch = ' '; continue; } else if (isCStyle && isInClass && prevNonSpaceCh != ')') { // BEGIN Content of ASBeautifier.cpp.BITFIELD.patch: unsigned int chIndex; char nextCh = 0; for (chIndex = i+1; chIndex < line.length(); chIndex++) if (!isWhiteSpace(line[chIndex])) break; if (chIndex< line.length()) nextCh = line[chIndex]; int nWord =0; for (chIndex = 0; chIndex < i; chIndex++) { if (!isWhiteSpace(line[chIndex])) { nWord ++; while (!isWhiteSpace(line[++chIndex])); } } if ((nextCh >= '0' && nextCh <= '9') || (nWord >1)) continue; // END Content of ASBeautifier.cpp.BITFIELD.patch: --tabCount; // found a 'private:' or 'public:' inside a class definition // so do nothing special } else if (isCStyle && isInClassHeader) { // found a 'class A : public B' definition // so do nothing special } else if (isInQuestion) { isInQuestion = false; } else if (isCStyle && prevNonSpaceCh == ')') { isInClassHeader = true; if (i==0) tabCount += 2; } else { currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers if (isInCase) { isInCase = false; ch = ';'; // from here on, treat char as ';' } // BEGIN content of ASBeautifier.cpp.BITFIELD.patch.bz2 else // bitfield or labels { unsigned int chIndex; char nextCh = 0; for (chIndex = i+1; (isCStyle && chIndex < line.length()); chIndex++) if (!isWhiteSpace(line[chIndex])) break; if (chIndex< line.length()) nextCh = line[chIndex]; int nWord =0; for (chIndex = 0; chIndex < i; chIndex++) { if (!isWhiteSpace(line[chIndex])) { nWord ++; while (!isWhiteSpace(line[++chIndex])); } } if (isCStyle && (nextCh >= '0' && nextCh <= '9') || (nWord >1)) { continue; } // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2 else // is in a label (e.g. 'label1:') { if (labelIndent) --tabCount; // unindent label by one indent else tabCount = 0; // completely flush indent to left } // BEGIN content of ASASBeautifier.cpp.BITFIELD.patch.bz2 } // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2 } } if ((ch == ';' || (parenDepth>0 && ch == ',')) && !inStatementIndentStackSizeStack->empty()) while ((unsigned int)inStatementIndentStackSizeStack->back() + (parenDepth>0 ? 1 : 0) < inStatementIndentStack->size()) inStatementIndentStack->pop_back(); // handle ends of statements if ( (ch == ';' && parenDepth == 0) || ch == '}'/* || (ch == ',' && parenDepth == 0)*/) { if (ch == '}') { // first check if this '}' closes a previous block, or a static array... if (!bracketBlockStateStack->empty()) { bool bracketBlockState = bracketBlockStateStack->back(); bracketBlockStateStack->pop_back(); if (!bracketBlockState) { if (!inStatementIndentStackSizeStack->empty()) { // this bracket is a static array unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back(); inStatementIndentStackSizeStack->pop_back(); while (previousIndentStackSize < inStatementIndentStack->size()) inStatementIndentStack->pop_back(); parenDepth--; if (i == 0) shouldIndentBrackettedLine = false; if (!parenIndentStack->empty()) { int poppedIndent = parenIndentStack->back(); parenIndentStack->pop_back(); if (i == 0) spaceTabCount = poppedIndent; } } continue; } } // this bracket is block closer... ++lineClosingBlocksNum; if(!inStatementIndentStackSizeStack->empty()) inStatementIndentStackSizeStack->pop_back(); if (!blockParenDepthStack->empty()) { parenDepth = blockParenDepthStack->back(); blockParenDepthStack->pop_back(); isInStatement = blockStatementStack->back(); blockStatementStack->pop_back(); if (isInStatement) blockTabCount--; } closingBracketReached = true; int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET); // <--- if (headerPlace != -1) { const string *popped = headerStack->back(); while (popped != &AS_OPEN_BRACKET) { headerStack->pop_back(); popped = headerStack->back(); } headerStack->pop_back(); if (!tempStacks->empty()) { vector *temp = tempStacks->back(); tempStacks->pop_back(); delete temp; } } ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified... } /* * Create a temporary snapshot of the current block's header-list in the * uppermost inner stack in tempStacks, and clear the headerStack up to * the begining of the block. * Thus, the next future statement will think it comes one indent past * the block's '{' unless it specifically checks for a companion-header * (such as a previous 'if' for an 'else' header) within the tempStacks, * and recreates the temporary snapshot by manipulating the tempStacks. */ if (!tempStacks->back()->empty()) while (!tempStacks->back()->empty()) tempStacks->back()->pop_back(); while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET) { tempStacks->back()->push_back(headerStack->back()); headerStack->pop_back(); } if (parenDepth == 0 && ch == ';') isInStatement=false; isInClassHeader = false; continue; } // check for preBlockStatements ONLY if not within parenthesies // (otherwise 'struct XXX' statements would be wrongly interpreted...) if (prevCh == ' ' && !isInTemplate && parenDepth == 0) { const string *newHeader = findHeader(line, i, preBlockStatements); if (newHeader != NULL) { isInClassHeader = true; outBuffer.append(newHeader->substr(1)); i += newHeader->length() - 1; //if (isCStyle) headerStack->push_back(newHeader); } } // Handle operators // //// // PRECHECK if a '==' or '--' or '++' operator was reached. //// // If not, then register an indent IF an assignment operator was reached. //// // The precheck is important, so that statements such as 'i--==2' are not recognized //// // to have assignment operators (here, '-=') in them . . . const string *foundAssignmentOp = NULL; const string *foundNonAssignmentOp = NULL; immediatelyPreviousAssignmentOp = NULL; // Check if an operator has been reached. foundAssignmentOp = findHeader(line, i, assignmentOperators, false); foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false); // Since findHeader's boundry checking was not used above, it is possible // that both an assignment op and a non-assignment op where found, // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the // found operator. if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL) if (foundAssignmentOp->length() < foundNonAssignmentOp->length()) foundAssignmentOp = NULL; else foundNonAssignmentOp = NULL; if (foundNonAssignmentOp != NULL) { if (foundNonAssignmentOp->length() > 1) { outBuffer.append(foundNonAssignmentOp->substr(1)); i += foundNonAssignmentOp->length() - 1; } } else if (foundAssignmentOp != NULL) { if (foundAssignmentOp->length() > 1) { outBuffer.append(foundAssignmentOp->substr(1)); i += foundAssignmentOp->length() - 1; } if (!isInOperator && !isInTemplate) { registerInStatementIndent(line, i, spaceTabCount, 0, false); immediatelyPreviousAssignmentOp = foundAssignmentOp; isInStatement = true; } } /* immediatelyPreviousAssignmentOp = NULL; bool isNonAssingmentOperator = false; for (int n = 0; n < nonAssignmentOperators.size(); n++) if (line.COMPARE(i, nonAssignmentOperators[n]->length(), *(nonAssignmentOperators[n])) == 0) { if (nonAssignmentOperators[n]->length() > 1) { outBuffer.append(nonAssignmentOperators[n]->substr(1)); i += nonAssignmentOperators[n]->length() - 1; } isNonAssingmentOperator = true; break; } if (!isNonAssingmentOperator) { for (int a = 0; a < assignmentOperators.size(); a++) if (line.COMPARE(i, assignmentOperators[a]->length(), *(assignmentOperators[a])) == 0) { if (assignmentOperators[a]->length() > 1) { outBuffer.append(assignmentOperators[a]->substr(1)); i += assignmentOperators[a]->length() - 1; } if (!isInOperator && !isInTemplate) { registerInStatementIndent(line, i, spaceTabCount, 0, false); immediatelyPreviousAssignmentOp = assignmentOperators[a]; isInStatement = true; } break; } } */ if (isInOperator) isInOperator = false; } // handle special cases of unindentation: /* * if '{' doesn't follow an immediately previous '{' in the headerStack * (but rather another header such as "for" or "if", then unindent it * by one indentation relative to its block. */ // cerr << endl << lineOpeningBlocksNum << " " << lineClosingBlocksNum << " " << previousLastLineHeader << endl; // indent #define lines with one less tab //if (isInDefine) // tabCount -= defineTabCount-1; if (!lineStartsInComment && !blockIndent && outBuffer.length()>0 && outBuffer[0]=='{' && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum) && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET) && shouldIndentBrackettedLine) --tabCount; else if (!lineStartsInComment && outBuffer.length()>0 && outBuffer[0]=='}' && shouldIndentBrackettedLine ) --tabCount; // correctly indent one-line-blocks... else if (!lineStartsInComment && outBuffer.length()>0 && lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum && previousLastLineHeader != NULL && previousLastLineHeader != &AS_OPEN_BRACKET) tabCount -= 1; //lineOpeningBlocksNum - (blockIndent ? 1 : 0); if (tabCount < 0) tabCount = 0; // take care of extra bracket indentatation option... if (bracketIndent && outBuffer.length()>0 && shouldIndentBrackettedLine) if (outBuffer[0]=='{' || outBuffer[0]=='}') tabCount++; if (isInDefine) { if (outBuffer[0] == '#') { string preproc = trim(string(outBuffer.c_str() + 1)); if (preproc.COMPARE(0, 6, string("define")) == 0) { if (!inStatementIndentStack->empty() && inStatementIndentStack->back() > 0) { defineTabCount = tabCount; } else { defineTabCount = tabCount - 1; tabCount--; } } } tabCount -= defineTabCount; } if (tabCount < 0) tabCount = 0; // finally, insert indentations into begining of line prevFinalLineSpaceTabCount = spaceTabCount; prevFinalLineTabCount = tabCount; if (shouldForceTabIndentation) { tabCount += spaceTabCount / indentLength; spaceTabCount = spaceTabCount % indentLength; } outBuffer = preLineWS(spaceTabCount,tabCount) + outBuffer; if (lastLineHeader != NULL) previousLastLineHeader = lastLineHeader; return outBuffer; } string ASBeautifier::preLineWS(int spaceTabCount, int tabCount) { string ws; for (int i=0; i 0) ws += string(" "); return ws; } /** * register an in-statement indent. */ void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount, int minIndent, bool updateParenStack) { int inStatementIndent; int remainingCharNum = line.length() - i; int nextNonWSChar = 1; nextNonWSChar = getNextProgramCharDistance(line, i); // if indent is around the last char in the line, indent instead 2 spaces from the previous indent if (nextNonWSChar == remainingCharNum) { int previousIndent = spaceTabCount; if (!inStatementIndentStack->empty()) previousIndent = inStatementIndentStack->back(); inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent ); if (updateParenStack) parenIndentStack->push_back( previousIndent ); return; } if (updateParenStack) parenIndentStack->push_back(i+spaceTabCount); inStatementIndent = i + nextNonWSChar + spaceTabCount; if (i + nextNonWSChar < minIndent) inStatementIndent = minIndent + spaceTabCount; if (i + nextNonWSChar > maxInStatementIndent) inStatementIndent = indentLength*2 + spaceTabCount; if (!inStatementIndentStack->empty() && inStatementIndent < inStatementIndentStack->back()) inStatementIndent = inStatementIndentStack->back(); inStatementIndentStack->push_back(inStatementIndent); } /** * get distance to the next non-white sspace, non-comment character in the line. * if no such character exists, return the length remaining to the end of the line. */ int ASBeautifier::getNextProgramCharDistance(const string &line, int i) { bool inComment = false; int remainingCharNum = line.length() - i; int charDistance = 1; int ch; for (charDistance = 1; charDistance < remainingCharNum; charDistance++) { ch = line[i + charDistance]; if (inComment) { if (line.COMPARE(i + charDistance, 2, AS_CLOSE_COMMENT) == 0) { charDistance++; inComment = false; } continue; } else if (isWhiteSpace(ch)) continue; else if (ch == '/') { if (line.COMPARE(i + charDistance, 2, AS_OPEN_LINE_COMMENT) == 0) return remainingCharNum; else if (line.COMPARE(i + charDistance, 2, AS_OPEN_COMMENT) == 0) { charDistance++; inComment = true; } } else return charDistance; } return charDistance; } /** * check if a specific character can be used in a legal variable/method/class name * * @return legality of the char. * @param ch the character to be checked. */ bool ASBeautifier::isLegalNameChar(char ch) const { return (isalnum(ch) //(ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9') || || ch=='.' || ch=='_' || (!isCStyle && ch=='$') || (isCStyle && ch=='~')); } /** * check if a specific line position contains a header, out of several possible headers. * * @return a pointer to the found header. if no header was found then return NULL. */ const string *ASBeautifier::findHeader(const string &line, int i, const vector &possibleHeaders, bool checkBoundry) { int maxHeaders = possibleHeaders.size(); const string *header = NULL; int p; for (p=0; p < maxHeaders; p++) { header = possibleHeaders[p]; if (line.COMPARE(i, header->length(), *header) == 0) { // check that this is a header and not a part of a longer word // (e.g. not at its begining, not at its middle...) int lineLength = line.length(); int headerEnd = i + header->length(); char startCh = (*header)[0]; // first char of header char endCh = 0; // char just after header char prevCh = 0; // char just before header if (headerEnd < lineLength) { endCh = line[headerEnd]; } if (i > 0) { prevCh = line[i-1]; } if (!checkBoundry) { return header; } else if (prevCh != 0 && isLegalNameChar(startCh) && isLegalNameChar(prevCh)) { return NULL; } else if (headerEnd >= lineLength || !isLegalNameChar(startCh) || !isLegalNameChar(endCh)) { return header; } else { return NULL; } } } return NULL; } /** * check if a specific character can be used in a legal variable/method/class name * * @return legality of the char. * @param ch the character to be checked. */ bool ASBeautifier::isWhiteSpace(char ch) const { return (ch == ' ' || ch == '\t'); } /** * find the index number of a string element in a container of strings * * @return the index number of element in the ocntainer. -1 if element not found. * @param container a vector of strings. * @param element the element to find . */ int ASBeautifier::indexOf(vector &container, const string *element) { vector::const_iterator where; where= find(container.begin(), container.end(), element); if (where == container.end()) return -1; else return where - container.begin(); } /** * trim removes the white space surrounding a line. * * @return the trimmed line. * @param str the line to trim. */ string ASBeautifier::trim(const string &str) { int start = 0; int end = str.length() - 1; while (start < end && isWhiteSpace(str[start])) start++; while (start <= end && isWhiteSpace(str[end])) end--; string returnStr(str, start, end+1-start); return returnStr; } #ifdef USES_NAMESPACE } #endif /* * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved. * * compiler_defines.h (1 January 1999) * by Tal Davidson (davidsont@bigfoot.com) * This file is a part of "Artistic Style" - an indentater and reformatter * of C, C++, C# and Java source files. * * The "Artistic Style" project, including all files needed to compile it, * is free software; you can redistribute it and/or use it and/or modify it * under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU General Public * License along with this program. */ #ifndef ASBEAUTIFIER_H #define ASBEAUTIFIER_H #include "ASResource.h" #include "compiler_defines.h" #include "ASSourceIterator.h" #include #include using namespace std; namespace astyle { enum BracketMode { NONE_MODE, ATTACH_MODE, BREAK_MODE, BDAC_MODE }; enum BracketType { NULL_TYPE = 0, DEFINITION_TYPE = 1, COMMAND_TYPE = 2, ARRAY_TYPE = 4, SINGLE_LINE_TYPE = 8}; class ASBeautifier : protected ASResource { public: ASBeautifier(); virtual ~ASBeautifier(); virtual void init(ASSourceIterator* iter); // pointer to dynamically created iterator. virtual void init(); virtual bool hasMoreLines() const; virtual string nextLine(); virtual string beautify(const string &line); void setTabIndentation(int length = 4, bool forceTabs = false); void setSpaceIndentation(int length = 4); void setMaxInStatementIndentLength(int max); void setMinConditionalIndentLength(int min); void setClassIndent(bool state); void setSwitchIndent(bool state); void setCaseIndent(bool state); void setBracketIndent(bool state); void setBlockIndent(bool state); void setNamespaceIndent(bool state); void setLabelIndent(bool state); void setCStyle(); void setJavaStyle(); void setEmptyLineFill(bool state); void setPreprocessorIndent(bool state); protected: int getNextProgramCharDistance(const string &line, int i); bool isLegalNameChar(char ch) const; bool isWhiteSpace(char ch) const; const string *findHeader(const string &line, int i, const vector &possibleHeaders, bool checkBoundry = true); string trim(const string &str); int indexOf(vector &container, const string *element); private: ASBeautifier(const ASBeautifier ©); void operator=(ASBeautifier&); // not to be implemented void initStatic(); void registerInStatementIndent(const string &line, int i, int spaceTabCount, int minIndent, bool updateParenStack); string preLineWS(int spaceTabCount, int tabCount); static vector headers; static vector nonParenHeaders; static vector preprocessorHeaders; static vector preBlockStatements; static vector assignmentOperators; static vector nonAssignmentOperators; static bool calledInitStatic; ASSourceIterator *sourceIterator; vector *waitingBeautifierStack; vector *activeBeautifierStack; vector *waitingBeautifierStackLengthStack; vector *activeBeautifierStackLengthStack; vector *headerStack; vector< vector* > *tempStacks; vector *blockParenDepthStack; vector *blockStatementStack; vector *parenStatementStack; vector *inStatementIndentStack; vector *inStatementIndentStackSizeStack; vector *parenIndentStack; vector *bracketBlockStateStack; string indentString; const string *currentHeader; const string *previousLastLineHeader; const string *immediatelyPreviousAssignmentOp; const string *probationHeader; bool isInQuote; bool isInComment; bool isInCase; bool isInQuestion; bool isInStatement; bool isInHeader; bool isCStyle; bool isInOperator; bool isInTemplate; bool isInConst; bool isInDefine; bool isInDefineDefinition; bool classIndent; bool isInClassHeader; bool isInClassHeaderTab; bool switchIndent; bool caseIndent; bool namespaceIndent; bool bracketIndent; bool blockIndent; bool labelIndent; bool preprocessorIndent; bool isInConditional; bool isMinimalConditinalIndentSet; bool shouldForceTabIndentation; int minConditionalIndent; int parenDepth; int indentLength; int blockTabCount; unsigned int leadingWhiteSpaces; int maxInStatementIndent; int templateDepth; char quoteChar; char prevNonSpaceCh; char currentNonSpaceCh; char currentNonLegalCh; char prevNonLegalCh; int prevFinalLineSpaceTabCount; int prevFinalLineTabCount; bool emptyLineFill; bool backslashEndsPrevLine; int defineTabCount; }; } #endif /* * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved. * * ASFormatter.cpp * by Tal Davidson (davidsont@bigfoot.com) * This file is a part of "Artistic Style" - an indentater and reformatter * of C, C++, C# and Java source files. * * The "Artistic Style" project, including all files needed to compile it, * is free software; you can redistribute it and/or use it and/or modify it * under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU General Public * License along with this program. * * * Patches: * 26 November 1998 - Richard Bullington - * A correction of line-breaking in headers following '}', * was created using a variation of a patch by Richard Bullington. * 08 May 2004 * applied ASFormatter450670.patch.bz2, ASFormatter.cpp.patch.bz2, * patch1_ssvb_patch.tar.gz */ #include "compiler_defines.h" #include "ASFormatter.h" #include #include #include #include #include #define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); } #define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container) ; } #define IS_A(a,b) ( ((a) & (b)) == (b)) #ifdef USES_NAMESPACE using namespace std; namespace astyle { #endif bool ASFormatter::calledInitStatic = false; vector ASFormatter::headers; vector ASFormatter::nonParenHeaders; vector ASFormatter::preprocessorHeaders; vector ASFormatter::preDefinitionHeaders; vector ASFormatter::preCommandHeaders; vector ASFormatter::operators; vector ASFormatter::assignmentOperators; /** * Constructor of ASFormatter */ ASFormatter::ASFormatter() { staticInit(); preBracketHeaderStack = NULL; bracketTypeStack = NULL; parenStack = NULL; sourceIterator = NULL; bracketFormatMode = NONE_MODE; shouldPadOperators = false; shouldPadParenthesies = false; shouldBreakOneLineBlocks = true; shouldBreakOneLineStatements = true; shouldConvertTabs = false; shouldBreakBlocks = false; shouldBreakClosingHeaderBlocks = false; shouldBreakClosingHeaderBrackets = false; shouldBreakElseIfs = false; } /** * Destructor of ASFormatter */ ASFormatter::~ASFormatter() { DELETE_CONTAINER( preBracketHeaderStack ); } /** * initialization of static data of ASFormatter. */ void ASFormatter::staticInit() { if (calledInitStatic) return; calledInitStatic = true; headers.push_back(&AS_IF); headers.push_back(&AS_ELSE); headers.push_back(&AS_DO); headers.push_back(&AS_WHILE); headers.push_back(&AS_FOR); headers.push_back(&AS_SYNCHRONIZED); headers.push_back(&AS_TRY); headers.push_back(&AS_CATCH); headers.push_back(&AS_FINALLY); headers.push_back(&AS_SWITCH); headers.push_back(&AS_TEMPLATE); 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); nonParenHeaders.push_back(&AS_ELSE); nonParenHeaders.push_back(&AS_DO); nonParenHeaders.push_back(&AS_TRY); 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); // nonParenHeaders.push_back(&AS_TEMPLATE); preDefinitionHeaders.push_back(&AS_CLASS); preDefinitionHeaders.push_back(&AS_INTERFACE); preDefinitionHeaders.push_back(&AS_NAMESPACE); preDefinitionHeaders.push_back(&AS_STRUCT); preCommandHeaders.push_back(&AS_EXTERN); preCommandHeaders.push_back(&AS_THROWS); preCommandHeaders.push_back(&AS_CONST); preprocessorHeaders.push_back(&AS_BAR_DEFINE); //// DEVEL: removed the folowing lines ////preprocessorHeaders.push_back(&AS_BAR_INCLUDE); ////preprocessorHeaders.push_back(&AS_BAR_IF); // #if or #ifdef ////preprocessorHeaders.push_back(&AS_BAR_EL); // #else or #elif ////preprocessorHeaders.push_back(&AS_BAR_ENDIF); 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); //// BUGFIX: removed the folowing lines //// operators.push_back(&AS_PAREN_PAREN); //// operators.push_back(&AS_BLPAREN_BLPAREN); 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); //BEGIN Content Patch patch1_ssvb_patch.tar.gz operators.push_back(&AS_SEMICOLON); //END Content Patch patch1_ssvb_patch.tar.gz operators.push_back(&AS_RETURN); 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_XOR_ASSIGN); assignmentOperators.push_back(&AS_OR_ASSIGN); assignmentOperators.push_back(&AS_AND_ASSIGN); assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN); assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN); assignmentOperators.push_back(&AS_ASSIGN); } /** * 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) { ASBeautifier::init(si); sourceIterator = si; INIT_CONTAINER( preBracketHeaderStack, new vector ); INIT_CONTAINER( bracketTypeStack, new vector ); bracketTypeStack->push_back(DEFINITION_TYPE); INIT_CONTAINER( parenStack, new vector ); parenStack->push_back(0); currentHeader = NULL; currentLine = string(""); formattedLine = ""; currentChar = ' '; previousCommandChar = ' '; previousNonWSChar = ' '; quoteChar = '"'; charNum = 0; previousOperator = NULL; isVirgin = true; isInLineComment = false; isInComment = false; isInPreprocessor = false; doesLineStartComment = false; isInQuote = false; isSpecialChar = false; isNonParenHeader = true; foundPreDefinitionHeader = false; foundPreCommandHeader = false; foundQuestionMark = false; isInLineBreak = false; endOfCodeReached = false; isLineReady = false; isPreviousBracketBlockRelated = true; isInPotentialCalculation = false; //foundOneLineBlock = false; shouldReparseCurrentChar = false; passedSemicolon = false; passedColon = false; isInTemplate = false; shouldBreakLineAfterComments = false; isImmediatelyPostComment = false; isImmediatelyPostLineComment = false; isImmediatelyPostEmptyBlock = false; isPrependPostBlockEmptyLineRequested = false; isAppendPostBlockEmptyLineRequested = false; prependEmptyLine = false; foundClosingHeader = false; previousReadyFormattedLineLength = 0; isImmediatelyPostHeader = false; isInHeader = false; } /** * get the next formatted line. * * @return formatted line. */ string ASFormatter::nextLine() { const string *newHeader; bool isCharImmediatelyPostComment = false; bool isPreviousCharPostComment = false; bool isCharImmediatelyPostLineComment = false; bool isInVirginLine = isVirgin; bool isCharImmediatelyPostOpenBlock = false; bool isCharImmediatelyPostCloseBlock = false; bool isCharImmediatelyPostTemplate = false; bool isCharImmediatelyPostHeader = false; if (!isFormattingEnabled()) return ASBeautifier::nextLine(); 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; isCharImmediatelyPostHeader = false; } if (isInLineComment) { appendCurrentChar(); // explicitely break a line when a line comment's end is found. if (/*bracketFormatMode == ATTACH_MODE &&*/ charNum+1 == currentLine.length()) { isInLineBreak = true; isInLineComment = false; isImmediatelyPostLineComment = true; currentChar = 0; //make sure it is a neutral char. } continue; } else if (isInComment) { if (isSequenceReached(AS_CLOSE_COMMENT)) { 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) { ////// DEVEL: if (isLegalNameChar(previousChar) && isLegalNameChar(peekNextChar())) appendCurrentChar(); continue; } /* not in MIDDLE of quote or comment or white-space of any type ... */ if (isSequenceReached(AS_OPEN_LINE_COMMENT)) { isInLineComment = true; if (shouldPadOperators) appendSpacePad(); appendSequence(AS_OPEN_LINE_COMMENT); goForward(1); continue; } else if (isSequenceReached(AS_OPEN_COMMENT)) { isInComment = true; if (shouldPadOperators) appendSpacePad(); appendSequence(AS_OPEN_COMMENT); goForward(1); continue; } else if (currentChar == '"' || currentChar == '\'') { isInQuote = true; quoteChar = currentChar; //// if (shouldPadOperators) // BUGFIX: these two lines removed. seem to be unneeded, and interfere with L" //// appendSpacePad(); // BUFFIX: TODO make sure the removal of these lines doesn't reopen old bugs... 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; if (isInPreprocessor) { 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; isCharImmediatelyPostHeader = true; // 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, ythen simply break the line if (shouldBreakElseIfs) isInLineBreak = true; else { // make sure 'else if()'s are not broken. bool isInElseIf = false; const string *upcomingHeader; upcomingHeader = findHeader(headers); if (currentHeader == &AS_ELSE && upcomingHeader == &AS_IF) isInElseIf = true; if (!isInElseIf) isInLineBreak = true; ////BUGFIX: SHOULD NOT BE breakLine() !!! } } } if (passedSemicolon) { passedSemicolon = false; if (parenStack->back() == 0) { shouldReparseCurrentChar = true; isInLineBreak = true; continue; } } if (passedColon) { passedColon = false; if (parenStack->back() == 0) { shouldReparseCurrentChar = true; isInLineBreak = true; continue; } } // Check if in template declaration, e.g. foo or foo // If so, set isInTemplate to true // if (!isInTemplate && currentChar == '<') { int templateDepth = 0; const string *oper; for (unsigned int i=charNum; i< currentLine.length(); i += (oper ? oper->length() : 1) ) { oper = ASBeautifier::findHeader(currentLine, i, operators); if (oper == &AS_LS) { templateDepth++; } else if (oper == &AS_GR) { templateDepth--; if (templateDepth == 0) { // this is a template! // isInTemplate = true; break; } } else if (oper == &AS_COMMA // comma, e.g. A || oper == &AS_BIT_AND // reference, e.g. A || oper == &AS_MULT // pointer, e.g. A || 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()++; } else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>')) { parenStack->back()--; if (isInTemplate && parenStack->back() == 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; } } // handle brackets // BracketType bracketType = NULL_TYPE; if (currentChar == '{') { bracketType = getBracketType(); foundPreDefinitionHeader = false; foundPreCommandHeader = false; bracketTypeStack->push_back(bracketType); preBracketHeaderStack->push_back(currentHeader); currentHeader = NULL; isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE); } else 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()) { bracketType = bracketTypeStack->back(); bracketTypeStack->pop_back(); isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE); } if (!preBracketHeaderStack->empty()) { currentHeader = preBracketHeaderStack->back(); preBracketHeaderStack->pop_back(); } else currentHeader = NULL; } if (!IS_A(bracketType, ARRAY_TYPE)) { if (currentChar == '{') { parenStack->push_back(0); } else if (currentChar == '}') { if (!parenStack->empty()) { parenStack->pop_back(); } } if (bracketFormatMode != NONE_MODE) { if (currentChar == '{') { if ( ( bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE && bracketTypeStack->size()>=2 && IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], COMMAND_TYPE) /*&& isInLineBreak*/) && !isCharImmediatelyPostLineComment ) { appendSpacePad(); if (!isCharImmediatelyPostComment // do not attach '{' to lines that end with /**/ comments. && previousCommandChar != '{' && previousCommandChar != '}' && previousCommandChar != ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';' appendCurrentChar(false); else appendCurrentChar(true); continue; } else if (bracketFormatMode == BREAK_MODE || bracketFormatMode == BDAC_MODE && bracketTypeStack->size()>=2 && IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], DEFINITION_TYPE)) { if ( shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE) ) breakLine(); appendCurrentChar(); continue; } } else if (currentChar == '}') { // bool origLineBreak = isInLineBreak; // 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 && !isImmediatelyPostEmptyBlock) // this '}' does not immediately follow an empty block { breakLine(); appendCurrentChar(); } else { // Content Patch ASFormatter.cpp.patch.bz2 // if (!isCharImmediatelyPostComment) if (!isCharImmediatelyPostComment && !isCharImmediatelyPostLineComment) isInLineBreak = false; appendCurrentChar(); if (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)) shouldBreakLineAfterComments = true; } if (shouldBreakBlocks) { isAppendPostBlockEmptyLineRequested =true; } continue; } } } if ( ( (previousCommandChar == '{' && isPreviousBracketBlockRelated) || (previousCommandChar == '}' && !isImmediatelyPostEmptyBlock // <-- && isPreviousBracketBlockRelated && !isPreviousCharPostComment // <-- Fixes wrongly appended newlines after '}' immediately after comments... 10/9/1999 && peekNextChar() != ' ')) && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE)) ) { isCharImmediatelyPostOpenBlock = (previousCommandChar == '{'); isCharImmediatelyPostCloseBlock = (previousCommandChar == '}'); 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) && previousNonWSChar == '}') { isInLineBreak = false; appendSpacePad(); if (shouldBreakBlocks) isAppendPostBlockEmptyLineRequested = false; } //Check if a template definition as been reached, e.g. template 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 padding is on, and a paren-header is found // then add a space pad after it. if (shouldPadOperators && !isNonParenHeader) 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) { foundPreDefinitionHeader = true; appendSequence(*newHeader); goForward(newHeader->length() - 1); if (shouldBreakBlocks) isPrependPostBlockEmptyLineRequested = true; continue; } else if ( (newHeader = findHeader(preCommandHeaders)) != NULL) { foundPreCommandHeader = true; appendSequence(*newHeader); goForward(newHeader->length() - 1); continue; } } if (previousNonWSChar == '}' || currentChar == ';') { if (shouldBreakOneLineStatements && currentChar == ';' && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE))) { passedSemicolon = true; } if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0) { isAppendPostBlockEmptyLineRequested = true; } if (currentChar != ';') currentHeader = NULL; //DEVEL: is this ok? foundQuestionMark = false; foundPreDefinitionHeader = false; foundPreCommandHeader = false; isInPotentialCalculation = 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; if (shouldPadOperators) { if ((newHeader = findHeader(operators)) != NULL) { bool shouldPad = (newHeader != &AS_COLON_COLON && newHeader != &AS_PAREN_PAREN && newHeader != &AS_BLPAREN_BLPAREN && newHeader != &AS_PLUS_PLUS && newHeader != &AS_MINUS_MINUS && newHeader != &AS_NOT && newHeader != &AS_BIT_NOT && newHeader != &AS_ARROW && newHeader != &AS_OPERATOR && !(newHeader == &AS_MINUS && isInExponent()) && !(newHeader == &AS_PLUS && isInExponent()) && previousOperator != &AS_OPERATOR && !((newHeader == &AS_MULT || newHeader == &AS_BIT_AND) && isPointerOrReference()) && !( (isInTemplate || isCharImmediatelyPostTemplate) && (newHeader == &AS_LS || newHeader == &AS_GR)) ); if (!isInPotentialCalculation) if (find(assignmentOperators.begin(), assignmentOperators.end(), newHeader) != assignmentOperators.end()) isInPotentialCalculation = true; // pad before operator if (shouldPad && !(newHeader == &AS_COLON && !foundQuestionMark) && newHeader != &AS_SEMICOLON && newHeader != &AS_COMMA) appendSpacePad(); appendSequence(*newHeader); goForward(newHeader->length() - 1); // since this block handles '()' and '[]', // the parenStack must be updated here accordingly! if (newHeader == &AS_PAREN_PAREN || newHeader == &AS_BLPAREN_BLPAREN) parenStack->back()--; currentChar = (*newHeader)[newHeader->length() - 1]; // pad after operator // but do not pad after a '-' that is a urinary-minus. if ( shouldPad && !(newHeader == &AS_MINUS && isUrinaryMinus()) ) appendSpacePad(); previousOperator = newHeader; continue; } } //BEGIN Content Patch patch1_ssvb_patch.tar.gz if (currentChar == '(' || currentChar == '[' ) isInPotentialCalculation = true; //END Content Patch patch1_ssvb_patch.tar.gz if (shouldPadParenthesies) { if (currentChar == '(' || currentChar == '[' ) { char peekedChar = peekNextChar(); isInPotentialCalculation = true; appendCurrentChar(); if (!(currentChar == '(' && peekedChar == ')') && !(currentChar == '[' && peekedChar == ']')) appendSpacePad(); continue; } else if (currentChar == ')' || currentChar == ']') { char peekedChar = peekNextChar(); if (!(previousChar == '(' && currentChar == ')') && !(previousChar == '[' && currentChar == ']')) appendSpacePad(); appendCurrentChar(); if (peekedChar != ';' && peekedChar != ',' && peekedChar != '.' && !(currentChar == ']' && peekedChar == '[')) appendSpacePad(); continue; } } appendCurrentChar(); } // return a beautified (i.e. correctly indented) line. string beautifiedLine; int readyFormattedLineLength = trim(readyFormattedLine).length(); if (prependEmptyLine && readyFormattedLineLength > 0 && previousReadyFormattedLineLength > 0) { isLineReady = true; // signal that a readyFormattedLine is still waiting beautifiedLine = beautify(""); } else { isLineReady = false; beautifiedLine = beautify(readyFormattedLine); } prependEmptyLine = false; previousReadyFormattedLineLength = readyFormattedLineLength; 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 { if (!isFormattingEnabled()) return ASBeautifier::hasMoreLines(); else return !endOfCodeReached; } /** * check if formatting options are enabled, in addition to indentation. * * @return are formatting options enabled? */ bool ASFormatter::isFormattingEnabled() const { return (bracketFormatMode != NONE_MODE || shouldPadOperators || shouldConvertTabs); } /** * 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 mode 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 mode 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 mode the padding mode. */ void ASFormatter::setOperatorPaddingMode(bool state) { shouldPadOperators = state; } /** * set parentheies padding mode. * options: * true statement parenthesies will be padded with spaces around them. * false statement parenthesies will not be padded. * * @param mode the padding mode. */ void ASFormatter::setParenthesisPaddingMode(bool state) { shouldPadParenthesies = 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; } /** * check if a specific sequence exists in the current placement of the current line * * @return whether sequence has been reached. * @param sequence the sequence to be checked */ bool ASFormatter::isSequenceReached(const string &sequence) const { return currentLine.COMPARE(charNum, sequence.length(), sequence) == 0; } /** * 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 { int peekNum = charNum + 1; int len = currentLine.length(); char ch = ' '; while (peekNum < len) { ch = currentLine[peekNum++]; if (!isWhiteSpace(ch)) return ch; } 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 { int peekNum = charNum + 1; int len = currentLine.length(); // char ch = ' '; bool foundComment = false; for (peekNum = charNum + 1; peekNum < len && isWhiteSpace(currentLine[peekNum]); ++peekNum) ; if (peekNum < len) foundComment = ( currentLine.COMPARE(peekNum, 2, AS_OPEN_COMMENT) == 0 || currentLine.COMPARE(peekNum, 2, AS_OPEN_LINE_COMMENT) == 0 ); return foundComment; } /** * 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; bool isAfterFormattedWhiteSpace = false; if (shouldPadOperators && !isInComment && !isInLineComment && !isInQuote && !doesLineStartComment && !isInPreprocessor && !isBeforeComment()) { //BEGIN Content Patch patch1_ssvb_patch.tar.gz char prevchar = ' '; char nextchar = peekNextChar(); int len = formattedLine.length(); // if (len > 0 && isWhiteSpace(formattedLine[len-1])) if (len > 0) prevchar = formattedLine[len-1]; if (isWhiteSpace(prevchar) || prevchar == '(' || prevchar == '[' || nextchar == ')' || nextchar == ']') { isAfterFormattedWhiteSpace = true; } //END Content Patch patch1_ssvb_patch.tar.gz } previousChar = currentChar; if (!isWhiteSpace(currentChar)) { previousNonWSChar = currentChar; if (!isInComment && !isInLineComment && !isInQuote && !isSequenceReached(AS_OPEN_COMMENT) && !isSequenceReached(AS_OPEN_LINE_COMMENT) ) previousCommandChar = previousNonWSChar; } unsigned int currentLineLength = currentLine.length(); if (charNum+1 < currentLineLength && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment)) { currentChar = currentLine[++charNum]; if (isAfterFormattedWhiteSpace) while (isWhiteSpace(currentChar) && charNum+1 < currentLineLength) currentChar = currentLine[++charNum]; if (shouldConvertTabs && currentChar == '\t') currentChar = ' '; return true; } // BEGIN Content patch ASFormatter450670.patch.bz2 else if (isInLineComment && (charNum+1 == currentLineLength)) { // fix BUG #450670 currentChar = ' '; return true; } // END Content patch ASFormatter450670.patch.bz2 else { if (sourceIterator->hasMoreLines()) { currentLine = sourceIterator->nextLine(); if (currentLine.length() == 0) { /*think*/ currentLine = string(" "); } // 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; trimNewLine(); currentChar = currentLine[charNum]; // check if is in preprocessor right after the line break and line trimming if (previousNonWSChar != '\\') isInPreprocessor = false; 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() { unsigned int len = currentLine.length(); charNum = 0; if (isInComment || isInPreprocessor) return; while (isWhiteSpace(currentLine[charNum]) && charNum+1 < len) ++charNum; doesLineStartComment = false; if (isSequenceReached(string("/*"))) { 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 the CURRENT character (curentChar)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 canBreakLine if true, a registered line-break */ void ASFormatter::appendCurrentChar(bool canBreakLine) { appendChar(currentChar, canBreakLine); } /** * 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, ' '); } /** * register a line break for the formatted line. */ void ASFormatter::breakLine() { isLineReady = true; isInLineBreak = false; // 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; else { bool isCommandType; 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); 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 urinary minus * this method takes for granted that the current character * is a '-'. * * @return whether the current '-' is a urinary minus. */ bool ASFormatter::isUrinaryMinus() 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(); int i = 0; char ch = ' '; char quoteChar = ' '; for (i = charNum + 1; i < currentLineLength; ++i) { 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 &headers, bool checkBoundry) { return ASBeautifier::findHeader(currentLine, charNum, headers, checkBoundry); } #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 ASFORMATTER_H #define ASFORMATTER_H #include "ASBeautifier.h" //#include "enums.h" #include "compiler_defines.h" namespace astyle { class ASFormatter : public ASBeautifier { 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 setParenthesisPaddingMode(bool mode); void setBreakOneLineBlocksMode(bool state); void setSingleStatementsMode(bool state); void setTabSpaceConversionMode(bool state); void setBreakBlocksMode(bool state); void setBreakClosingHeaderBlocksMode(bool state); void setBreakElseIfsMode(bool state); private: void ASformatter(ASFormatter ©); // not to be imlpemented void operator=(ASFormatter&); // not to be implemented void staticInit(); bool isFormattingEnabled() const; void goForward(int i); bool getNextChar(); char peekNextChar() const; bool isBeforeComment() const; void trimNewLine(); BracketType getBracketType() const; bool isPointerOrReference() const; bool isUrinaryMinus() const; bool isInExponent() const; bool isOneLineBlockReached() const; void appendChar(char ch, bool canBreakLine = true); void appendCurrentChar(bool canBreakLine = true); void appendSequence(const string &sequence, bool canBreakLine = true); void appendSpacePad(); void breakLine(); inline bool isSequenceReached(const string &sequence) const; const string *findHeader(const vector &headers, bool checkBoundry = true); static vector headers; static vector nonParenHeaders; static vector preprocessorHeaders; static vector preDefinitionHeaders; static vector preCommandHeaders; static vector operators; static vector assignmentOperators; static bool calledInitStatic; ASSourceIterator *sourceIterator; vector *preBracketHeaderStack; vector *bracketTypeStack; vector *parenStack; string readyFormattedLine; string currentLine; string formattedLine; const string *currentHeader; const string *previousOperator; char currentChar; char previousChar; char previousNonWSChar; char previousCommandChar; char quoteChar; unsigned int charNum; BracketMode bracketFormatMode; bool isVirgin; bool shouldPadOperators; bool shouldPadParenthesies; bool shouldConvertTabs; bool isInLineComment; bool isInComment; bool isInPreprocessor; bool isInTemplate; // true both in template definitions (e.g. template) and template usage (e.g. F). bool doesLineStartComment; bool isInQuote; bool isSpecialChar; bool isNonParenHeader; bool foundQuestionMark; bool foundPreDefinitionHeader; bool foundPreCommandHeader; bool isInLineBreak; bool isInClosingBracketLineBreak; bool endOfCodeReached; bool isLineReady; bool isPreviousBracketBlockRelated; bool isInPotentialCalculation; //bool foundOneLineBlock; bool shouldBreakOneLineBlocks; bool shouldReparseCurrentChar; bool shouldBreakOneLineStatements; bool shouldBreakLineAfterComments; bool shouldBreakClosingHeaderBrackets; bool shouldBreakElseIfs; bool passedSemicolon; bool passedColon; bool isImmediatelyPostComment; bool isImmediatelyPostLineComment; bool isImmediatelyPostEmptyBlock; bool shouldBreakBlocks; bool shouldBreakClosingHeaderBlocks; bool isPrependPostBlockEmptyLineRequested; bool isAppendPostBlockEmptyLineRequested; bool prependEmptyLine; bool foundClosingHeader; int previousReadyFormattedLineLength; bool isInHeader; bool isImmediatelyPostHeader; }; } #endif /* * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved. * * ASResource.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. */ #include "compiler_defines.h" #include "ASResource.h" #include #ifdef USES_NAMESPACE using namespace std; namespace astyle { #endif 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"); #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 ASRES_H #define ASRES_H #include "compiler_defines.h" #include "ASStreamIterator.h" #include #include #include namespace astyle { class ASResource { 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; }; } #endif #ifndef ASSOURCEITERATOR_H #define ASSOURCEITERATOR_H #include #include "compiler_defines.h" namespace astyle { class ASSourceIterator { public: virtual bool hasMoreLines() const = 0; virtual std::string nextLine() = 0; }; } #endif #include "compiler_defines.h" #include "ASStreamIterator.h" #include #include #include using namespace astyle; ASStreamIterator::ASStreamIterator(istream *in) { inStream = in; } ASStreamIterator::~ASStreamIterator() { delete inStream; } bool ASStreamIterator::hasMoreLines() const { if (*inStream) return true; else return false; } /* string ASStreamIterator::nextLine() { char theInChar; char peekedChar; int theBufferPosn = 0; // // treat '\n', '\r', '\n\r' and '\r\n' as an endline. // while (theBufferPosn < 2047 && inStream->get(theInChar)) // while not eof { if (theInChar != '\n' && theInChar != '\r') { buffer[theBufferPosn] = theInChar; theBufferPosn++; } else { peekedChar = inStream->peek(); if (peekedChar != theInChar && (peekedChar == '\r' || peekedChar == '\n') ) { inStream->get(theInChar); } break; } } buffer[theBufferPosn] = '\0'; return string(buffer); } */ string ASStreamIterator::nextLine() { char *srcPtr; char *filterPtr; inStream->getline(buffer, 2047); srcPtr = filterPtr = buffer; while (*srcPtr != 0) { if (*srcPtr != '\r') *filterPtr++ = *srcPtr; srcPtr++; } *filterPtr = 0; return string(buffer); } /* * 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 ASSTREAMITERATOR_H #define ASSTREAMITERATOR_H #include "ASSourceIterator.h" using namespace std; namespace astyle { class ASStreamIterator : public ASSourceIterator { public: ASStreamIterator(istream *in); virtual ~ASStreamIterator(); bool hasMoreLines() const; string nextLine(); private: istream * inStream; char buffer[2048]; }; } #endif /*************************************************************************** charcodes.cpp - description ------------------- begin : Wed Nov 24 2003 copyright : (C) 2003 by André imon 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. * * * ***************************************************************************/ // FILE SHOULD BE REMOVED FROM PROJECT #ifndef CHAR_CODES #define CHAR_CODES #ifdef _WIN32 #define AUML_LC 228 #define OUML_LC 246 #define UUML_LC 252 #define AUML_UC 196 #define OUML_UC 214 #define UUML_UC 220 #define AACUTE_LC 225 #define EACUTE_LC 233 #define OACUTE_LC 243 #define UACUTE_LC 250 #define AACUTE_UC 193 #define EACUTE_UC 201 #define OACUTE_UC 211 #define UACUTE_UC 218 #define AGRAVE_LC 224 #define EGRAVE_LC 232 #define OGRAVE_LC 242 #define UGRAVE_LC 249 #define AGRAVE_UC 192 #define EGRAVE_UC 200 #define OGRAVE_UC 210 #define UGRAVE_UC 217 #define SZLIG 223 /* DOS CONSOLE CODES #define AUML_LC 132 #define OUML_LC 148 #define UUML_LC 129 #define AUML_UC 142 #define OUML_UC 153 #define UUML_UC 154 #define AACUTE_LC 160 #define EACUTE_LC 130 #define OACUTE_LC 162 #define UACUTE_LC 163 #define AACUTE_UC 181 #define EACUTE_UC 144 #define OACUTE_UC 224 #define UACUTE_UC 233 #define AGRAVE_LC 133 #define EGRAVE_LC 138 #define OGRAVE_LC 149 #define UGRAVE_LC 151 #define AGRAVE_UC 183 #define EGRAVE_UC 212 #define OGRAVE_UC 227 #define UGRAVE_UC 235 #define SZLIG 225 */ #else #define AUML_LC 164 #define OUML_LC 182 #define UUML_LC 188 #define AUML_UC 132 #define OUML_UC 150 #define UUML_UC 156 #define AACUTE_LC 161 #define EACUTE_LC 169 #define OACUTE_LC 179 #define UACUTE_LC 186 #define AACUTE_UC 129 #define EACUTE_UC 137 #define OACUTE_UC 147 #define UACUTE_UC 154 #define AGRAVE_LC 160 #define EGRAVE_LC 168 #define OGRAVE_LC 178 #define UGRAVE_LC 185 #define AGRAVE_UC 128 #define EGRAVE_UC 136 #define OGRAVE_UC 146 #define UGRAVE_UC 153 #define SZLIG 159 #endif #endif /*************************************************************************** cmdlineoptions.cpp - description ------------------- begin : Sun Nov 25 2001 copyright : (C) 2001 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 "cmdlineoptions.h" using namespace std; /* Siehe man getopt (3) Konstruktor legt Optionen und Argumente fest */ CmdLineOptions::CmdLineOptions(int argc, char *argv[]): numberSpaces(0), wrappingStyle(highlight::WRAP_DISABLED), outputType (highlight::HTML), opt_language (false), opt_include_style (false), opt_help (false), opt_version (false), opt_verbose (false), opt_linenumbers (false), opt_style (false), opt_batch_mode (false), opt_fragment (false) , opt_attach_line_anchors (false), opt_show_themes (false), opt_show_langdefs (false), opt_printindex(false), opt_quiet(false), opt_xslfo_fop(false), opt_replacequotes(false), opt_print_progress(false), opt_fill_zeroes(false), opt_stylepath_explicit(false), opt_force_output(false), configFileRead(false), helpLang("en"), charset("ISO-8859-1") { loadConfigurationFile(); int c, option_index = 0; static struct option long_options[] = { {OPT_OUT, 1, 0, S_OPT_OUT}, {OPT_IN, 1, 0, S_OPT_IN}, {OPT_SYNTAX, 1, 0, S_OPT_SYNTAX}, {OPT_VERBOSE, 0, 0, S_OPT_VERBOSE}, {OPT_INC_STYLE, 0, 0, S_OPT_INC_STYLE}, {OPT_HELP, 0, 0, S_OPT_HELP}, {OPT_HELPINT, 1, 0, S_OPT_HELPINT}, {OPT_LINENO,0,0,S_OPT_LINENO}, {OPT_STYLE, 1,0,S_OPT_STYLE}, {OPT_STYLE_OUT, 1, 0,S_OPT_STYLE_OUT}, {OPT_STYLE_IN, 1, 0,S_OPT_STYLE_IN}, {OPT_DELTABS,1,0,S_OPT_DELTABS}, {OPT_XHTML, 0,0,S_OPT_XHTML}, {OPT_RTF, 0,0,S_OPT_RTF}, {OPT_TEX,0, 0,S_OPT_TEX}, {OPT_LATEX,0, 0,S_OPT_LATEX}, {OPT_XSLFO,0, 0,S_OPT_XSLFO}, {OPT_ANSI,0, 0,S_OPT_ANSI}, {OPT_XML,0, 0,S_OPT_XML}, {OPT_BATCHREC,1,0,S_OPT_BATCHREC}, {OPT_FRAGMENT,0,0,S_OPT_FRAGMENT}, {OPT_ANCHORS, 0,0,S_OPT_ANCHORS }, {OPT_LISTTHEMES, 0,0,S_OPT_LISTTHEMES }, {OPT_LISTLANGS, 0,0,S_OPT_LISTLANGS }, {OPT_OUTDIR,1,0,S_OPT_OUTDIR}, {OPT_VERSION,0,0,0}, {OPT_FORMATSTYLE,1,0,S_OPT_FORMATSTYLE}, {OPT_DATADIR,1,0,S_OPT_DATADIR}, {OPT_ADDDATADIR,1,0,S_OPT_ADDDATADIR}, {OPT_INDEXFILE,0,0,S_OPT_INDEXFILE}, {OPT_WRAP,0,0,S_OPT_WRAP}, {OPT_WRAPSIMPLE,0,0,S_OPT_WRAPSIMPLE}, {OPT_QUIET,0,0,S_OPT_QUIET}, {OPT_REPLACE_QUOTES,0,0,S_OPT_REPLACE_QUOTES}, {OPT_PROGRESSBAR,0,0,S_OPT_PROGRESSBAR}, {OPT_FILLZEROES,0,0,S_OPT_FILLZEROES}, {OPT_ENCODING,1,0,S_OPT_ENCODING}, //remove as soon as APAche fixes the bug in FOP (0.20.5) {OPT_FOP,0,0,S_OPT_FOP}, //deprecated {OPT_CSSOUT,1,0,0}, {OPT_CSSIN,1,0,0}, {OPT_INC_CSS,0,0,0}, {OPT_FORCE_OUTPUT,0,0,0}, {0, 0, 0, 0} }; while (1) { c = getopt_long (argc, argv,S_OPTIONS_STRING,long_options, &option_index); if (c == -1) break; switch (c) { case 0: // long options if (long_options[option_index].name==OPT_VERSION) { opt_version = true; } if (long_options[option_index].name==OPT_CSSOUT) { styleOutFilename=string(optarg); printDeprecatedWarning(OPT_CSSOUT, OPT_STYLE_OUT); } if (long_options[option_index].name==OPT_CSSIN) { styleInFilename=string(optarg); printDeprecatedWarning(OPT_CSSIN, OPT_STYLE_IN); } if (long_options[option_index].name==OPT_INC_CSS) { opt_include_style = true; printDeprecatedWarning(OPT_INC_CSS, OPT_INC_STYLE); } if (long_options[option_index].name==OPT_FORCE_OUTPUT) { opt_force_output = true; } break; case S_OPT_OUT: outFilename=string(optarg); break; case S_OPT_IN: inputFileNames.push_back(string(optarg)); break; case S_OPT_STYLE_OUT: styleOutFilename=string(optarg); opt_stylepath_explicit=true; break; case S_OPT_STYLE_IN: styleInFilename=string(optarg); break; case S_OPT_VERBOSE: opt_verbose = true; break; case S_OPT_QUIET: opt_quiet = true; break; case S_OPT_INC_STYLE: opt_include_style = true; break; case S_OPT_HELPINT: helpLang=string(optarg); case S_OPT_HELP: opt_help = true; break; case S_OPT_LINENO: opt_linenumbers = true; break; case '?': //opt_help = true; break; case S_OPT_STYLE: styleName=string(optarg); opt_style = true; break; case S_OPT_SYNTAX: language=string(optarg); opt_language = true; break; case S_OPT_DELTABS: numberSpaces = StringTools::str2int (string(optarg)); break; case S_OPT_XHTML: outputType=highlight::XHTML; break; case S_OPT_RTF: outputType=highlight::RTF; break; case S_OPT_TEX: outputType=highlight::TEX; break; case S_OPT_LATEX: outputType=highlight::LATEX; break; case S_OPT_XSLFO: outputType=highlight::XSLFO; break; case S_OPT_ANSI: outputType=highlight::ANSI; break; case S_OPT_XML: outputType=highlight::XML; break; case S_OPT_BATCHREC: opt_batch_mode = true; readDirectory(string(optarg)); break; case S_OPT_FRAGMENT: opt_fragment = true; break; case S_OPT_ANCHORS: opt_attach_line_anchors = true; break; case S_OPT_LISTTHEMES: opt_show_themes = true; break; case S_OPT_LISTLANGS: opt_show_langdefs = true; break; case S_OPT_OUTDIR: outDirectory = validateDirPath(string(optarg)); break; case S_OPT_FORMATSTYLE: indentScheme =string(optarg); break; case S_OPT_ENCODING: charset =string(optarg); break; case S_OPT_DATADIR: dataDir=validateDirPath(string(optarg)); break; case S_OPT_ADDDATADIR: additionalDataDir=validateDirPath(string(optarg)); break; case S_OPT_INDEXFILE: opt_printindex=true; break; case S_OPT_WRAPSIMPLE: wrappingStyle = highlight::WRAP_SIMPLE; break; case S_OPT_WRAP: wrappingStyle = highlight::WRAP_DEFAULT; break; case S_OPT_FOP: opt_xslfo_fop=true; break; case S_OPT_REPLACE_QUOTES: opt_replacequotes=true; break; case S_OPT_PROGRESSBAR: opt_print_progress=true; break; case S_OPT_FILLZEROES: opt_fill_zeroes=true; break; default: cerr <<"higlight: Unknown option " <-1)?delim:0) + getOutFileSuffix(); } } return outFilename; } const string &CmdLineOptions::getSingleInFilename() const { return inputFileNames[0]; } const string &CmdLineOptions::getOutDirectory() { if (!outFilename.empty() && !enableBatchMode()){ outDirectory=getDirName(outFilename); } return outDirectory; } const string CmdLineOptions::getStyleOutFilename() const { if (!styleOutFilename.empty()) return styleOutFilename; return (outputType==highlight::HTML || outputType==highlight::XHTML)? "highlight.css":"highlight.sty"; } const string &CmdLineOptions::getStyleInFilename() const { return styleInFilename; } int CmdLineOptions::getNumberSpaces() const { return numberSpaces; } bool CmdLineOptions::printVersion()const { return opt_version; } bool CmdLineOptions::printHelp()const { return opt_help; } bool CmdLineOptions::printDebugInfo()const { return opt_verbose; } bool CmdLineOptions::quietMode()const { return opt_quiet; } bool CmdLineOptions::includeStyleDef()const { return opt_include_style; } bool CmdLineOptions::formatSupportsExtStyle(){ return outputType==highlight::HTML || outputType==highlight::XHTML || outputType==highlight::LATEX || outputType==highlight::TEX; } bool CmdLineOptions::printLineNumbers()const { return opt_linenumbers; } string CmdLineOptions::getStyleName()const { return ( ( opt_style) ? styleName+".style" : "kwrite.style" ); } bool CmdLineOptions::enableBatchMode()const{ return inputFileNames.size()>1 || opt_batch_mode; } bool CmdLineOptions::fragmentOutput()const{ return opt_fragment; } string CmdLineOptions::getOutFileSuffix()const{ switch (outputType){ case highlight::XHTML: return ".xhtml"; case highlight::RTF: return ".rtf"; case highlight::TEX: case highlight::LATEX: return ".tex"; case highlight::XSLFO: return ".fo"; case highlight::XML: return ".xml"; default: return ".html"; } } string CmdLineOptions::getDirName(const string & path) { size_t dirNameLength=path.rfind(Platform::pathSeparator); return (dirNameLength==string::npos)?string():path.substr(0, dirNameLength+1); } bool CmdLineOptions::attachLineAnchors()const{ return opt_attach_line_anchors; } bool CmdLineOptions::showThemes()const{ return opt_show_themes; } bool CmdLineOptions::showLangdefs()const{ return opt_show_langdefs; } bool CmdLineOptions::outDirGiven()const{ return !outFilename.empty(); } bool CmdLineOptions::fopCompatible() const { return opt_xslfo_fop; } bool CmdLineOptions::replaceQuotes() const { return opt_replacequotes; } bool CmdLineOptions::getFlag( const string& paramVal){ return StringTools::lowerCase(paramVal)=="true"; } bool CmdLineOptions::formattingEnabled(){ return !indentScheme.empty(); } bool CmdLineOptions::dataDirGiven()const { return !dataDir.empty(); } bool CmdLineOptions::additionalDataDirGiven()const { return !additionalDataDir.empty(); } const string &CmdLineOptions::getDataDir() const { return dataDir; } const string &CmdLineOptions::getIndentScheme() const { return indentScheme; } const string &CmdLineOptions::getAdditionalDataDir()const{ return additionalDataDir; } const string &CmdLineOptions::getLanguage() const { return language; } const string&CmdLineOptions::getCharSet() const{ return charset; } bool CmdLineOptions::printIndexFile() const{ return opt_printindex && (outputType==highlight::HTML || outputType==highlight::XHTML); } bool CmdLineOptions::printProgress() const{ return opt_print_progress; } bool CmdLineOptions::fillLineNrZeroes() const{ return opt_fill_zeroes; } bool CmdLineOptions::syntaxGiven() const{ return opt_language; } bool CmdLineOptions::omitEncodingName() const{ return StringTools::lowerCase(charset)=="none"; } bool CmdLineOptions::forceOutput() const{ return opt_force_output; } const string CmdLineOptions::getHelpLang()const{ return helpLang+".help"; } highlight::WrapMode CmdLineOptions::getWrappingStyle() const { return wrappingStyle; } const vector & CmdLineOptions::getInputFileNames() const{ return inputFileNames; } void CmdLineOptions::readDirectory(const string & wildcard){ // get matching files, use recursive search bool directoryOK=Platform::getDirectoryEntries(inputFileNames, wildcard, true); if (!directoryOK) { cerr << "highlight: No files matched the pattern \"" << wildcard << "\"."<< endl; } } void CmdLineOptions::loadConfigurationFile() { #ifndef _WIN32 #ifdef CONFIG_FILE_PATH configFilePath=CONFIG_FILE_PATH; #else char* homeEnv=getenv("HOME"); if (homeEnv==NULL) return; configFilePath=string(homeEnv)+"/.highlightrc"; #endif #else configFilePath = Platform::getAppPath() + "highlight.conf"; #endif ConfigurationReader presets(configFilePath); if (presets.found()) { string paramVal; configFileRead=true; styleOutFilename = presets.getParameter(OPT_STYLE_OUT); styleInFilename = presets.getParameter(OPT_STYLE_IN); styleName = presets.getParameter(OPT_STYLE); opt_style = !styleName.empty(); language = presets.getParameter(OPT_SYNTAX); opt_language = !language.empty(); numberSpaces = StringTools::str2int(presets.getParameter(OPT_DELTABS)); indentScheme = presets.getParameter(OPT_FORMATSTYLE); paramVal = presets.getParameter(OPT_DATADIR); if (!paramVal.empty()) { dataDir=validateDirPath( paramVal); } paramVal = presets.getParameter(OPT_ADDDATADIR); if (!paramVal.empty()) { additionalDataDir=validateDirPath(paramVal); } paramVal = presets.getParameter(OPT_OUTDIR); if (!paramVal.empty()) { outDirectory=validateDirPath(paramVal); } paramVal = presets.getParameter(OPT_ENCODING); if (!paramVal.empty()) { charset=paramVal; } opt_include_style=getFlag(presets.getParameter(OPT_INC_STYLE)); opt_verbose=getFlag(presets.getParameter(OPT_VERBOSE)); opt_linenumbers=getFlag(presets.getParameter(OPT_LINENO)); opt_fragment=getFlag(presets.getParameter(OPT_FRAGMENT)); opt_attach_line_anchors=getFlag(presets.getParameter(OPT_ANCHORS)); opt_printindex=getFlag(presets.getParameter(OPT_INDEXFILE)); opt_quiet=getFlag(presets.getParameter(OPT_QUIET)); opt_xslfo_fop=getFlag(presets.getParameter(OPT_FOP)); opt_replacequotes=getFlag(presets.getParameter(OPT_REPLACE_QUOTES)); opt_print_progress=getFlag(presets.getParameter(OPT_PROGRESSBAR)); opt_fill_zeroes=getFlag(presets.getParameter(OPT_FILLZEROES)); if (getFlag(presets.getParameter(OPT_WRAP))) { wrappingStyle=highlight::WRAP_DEFAULT; } if (getFlag(presets.getParameter(OPT_WRAPSIMPLE))) { wrappingStyle=highlight::WRAP_SIMPLE; } if (getFlag(presets.getParameter(OPT_XHTML))) { outputType=highlight::XHTML; } else if (getFlag(presets.getParameter(OPT_RTF))) { outputType=highlight::RTF; } else if (getFlag(presets.getParameter(OPT_TEX))) { outputType=highlight::TEX; } else if (getFlag(presets.getParameter(OPT_LATEX))) { outputType=highlight::LATEX; } else if (getFlag(presets.getParameter(OPT_XSLFO))) { outputType=highlight::XSLFO; } else if (getFlag(presets.getParameter(OPT_ANSI))) { outputType=highlight::ANSI; } else if (getFlag(presets.getParameter(OPT_XML))) { outputType=highlight::XML; } } } string CmdLineOptions::validateDirPath(const string & path){ return (path[path.length()-1] !=Platform::pathSeparator)? path+Platform::pathSeparator : path; } highlight::OutputType CmdLineOptions::getOutputType() const { return outputType; } void CmdLineOptions::printDeprecatedWarning(const char *oldOption, const char *newOption){ cerr << "Warning: Long option \""< #include #include #include #include #include "platform_fs.h" #include "configurationreader.h" #include "datadir.h" #include "enums.h" #ifdef _WIN32 #include #endif // If your system does not know getopt_long, define USE_LOCAL_GETOPT #if defined(_WIN32) || defined(__SVR4) || defined(__sun__) // some compilers don't like redefinitions... #ifndef USE_LOCAL_GETOPT #define USE_LOCAL_GETOPT #endif #endif #ifdef USE_LOCAL_GETOPT #include "getopt.h" #else #include #endif #define OPT_VERBOSE "verbose" #define OPT_INC_STYLE "include-style" #define OPT_HELP "help" #define OPT_LINENO "linenumbers" #define OPT_XHTML "xhtml" #define OPT_RTF "rtf" #define OPT_TEX "tex" #define OPT_LATEX "latex" #define OPT_XSLFO "xsl-fo" #define OPT_FRAGMENT "fragment" #define OPT_ANCHORS "anchors" #define OPT_LISTTHEMES "list-themes" #define OPT_LISTLANGS "list-langs" #define OPT_VERSION "version" #define OPT_IN "input" #define OPT_OUT "output" #define OPT_SYNTAX "syntax" #define OPT_STYLE "style" #define OPT_STYLE_OUT "style-outfile" #define OPT_STYLE_IN "style-infile" #define OPT_DELTABS "replace-tabs" #define OPT_BATCHREC "batch-recursive" #define OPT_OUTDIR "outdir" #define OPT_FORMATSTYLE "format-style" #define OPT_DATADIR "data-dir" #define OPT_ADDDATADIR "add-data-dir" #define OPT_INDEXFILE "print-index" #define OPT_HELPINT "help-int" #define OPT_WRAP "wrap" #define OPT_WRAPSIMPLE "wrap-simple" #define OPT_QUIET "quiet" #define OPT_REPLACE_QUOTES "replace-quotes" #define OPT_FOP "fop-compatible" #define OPT_PROGRESSBAR "progress" #define OPT_FILLZEROES "zeroes" #define OPT_ANSI "ansi" #define OPT_XML "xml" #define OPT_ENCODING "encoding" #define OPT_FORCE_OUTPUT "force" #define S_OPT_ANSI 'A' #define S_OPT_OUT 'o' #define S_OPT_IN 'i' #define S_OPT_SYNTAX 'S' #define S_OPT_VERBOSE 'v' #define S_OPT_INC_STYLE 'I' #define S_OPT_HELP 'h' #define S_OPT_HELPINT 'H' #define S_OPT_LINENO 'l' #define S_OPT_STYLE 's' #define S_OPT_STYLE_OUT 'c' #define S_OPT_STYLE_IN 'e' #define S_OPT_DELTABS 't' #define S_OPT_XHTML 'X' #define S_OPT_RTF 'R' #define S_OPT_TEX 'T' #define S_OPT_LATEX 'L' #define S_OPT_XSLFO 'Y' #define S_OPT_XML 'Z' #define S_OPT_BATCHREC 'B' #define S_OPT_FRAGMENT 'f' #define S_OPT_ANCHORS 'a' #define S_OPT_LISTTHEMES 'w' #define S_OPT_LISTLANGS 'p' #define S_OPT_OUTDIR 'O' #define S_OPT_FORMATSTYLE 'F' #define S_OPT_DATADIR 'D' #define S_OPT_ADDDATADIR 'E' #define S_OPT_INDEXFILE 'C' #define S_OPT_WRAP 'W' #define S_OPT_WRAPSIMPLE 'V' #define S_OPT_QUIET 'q' #define S_OPT_FOP 'g' #define S_OPT_REPLACE_QUOTES 'r' #define S_OPT_VERSION 'Q' #define S_OPT_PROGRESSBAR 'P' #define S_OPT_FILLZEROES 'z' #define S_OPT_ENCODING 'u' // deprecated: #define OPT_CSSOUT "css-outfile" #define OPT_CSSIN "css-infile" #define OPT_INC_CSS "include-css" #define S_OPTIONS_STRING "o:i:S:B:O:s:c:e:t:u:F:D:H:E:afghlvwpqrzACILYRTZXUV::W::P" using namespace std; /**Command line options*/ class CmdLineOptions { public: /**Constructor \param argc Argument count \param argv Argument strings */ CmdLineOptions(int argc, char *argv[]); ~CmdLineOptions(); /** \return Single output file name*/ const string &getSingleOutFilename(); /** \return Single input file name*/ const string &getSingleInFilename() const; /** \return Output directory*/ const string& getOutDirectory() ; /** \return Style output file name*/ const string getStyleOutFilename() const; /** \return Style input file name*/ const string&getStyleInFilename() const; /** \return Char set*/ const string&getCharSet() const; /** \return Number of spaces to replace a tab*/ int getNumberSpaces() const; /** \return True if version information should be printed*/ bool printVersion() const; /** \return True if help information should be printed*/ bool printHelp() const; /** \return True if debug information should be printed*/ bool printDebugInfo()const; /** \return True if Style definition should be included in output*/ bool includeStyleDef() const; /** \return True if line numbers should be printed*/ bool printLineNumbers() const; /** \return colour theme name */ string getStyleName()const ; /** gibt true zurck, falls deutsche Hilfe ausgegeben werden soll */ int helpLanguage() const; /** \return True if batch mode is active*/ bool enableBatchMode() const; /** \return True if output shluld be fragmented*/ bool fragmentOutput() const; /** \return output file suffix */ string getOutFileSuffix() const; /** \return True if anchors should be attached to line numbers*/ bool attachLineAnchors() const; /** \return True if list of installed themes should be printed*/ bool showThemes() const; /** \return True if list of installed language definitions should be printed*/ bool showLangdefs() const; /** \return True if loutput directory is given*/ bool outDirGiven() const; /** \return True if refomatting is enabled*/ bool formattingEnabled(); /** \return True if a new data directory is given*/ bool dataDirGiven()const; /** \return True if an additional data directory is given*/ bool additionalDataDirGiven()const; /** \return True if index file should be printed*/ bool printIndexFile() const; /** \return True if quotes should be replaced by /dq in LaTeX*/ bool replaceQuotes() const; /** \return Data directory*/ const string &getDataDir()const; /** \return Additional data directory*/ const string &getAdditionalDataDir()const; /** \return True if language syntax is given*/ bool syntaxGiven() const; /** \return True if quiet mode is active*/ bool quietMode() const; /** \return True if XSL-FO output should be FOP compatible*/ bool fopCompatible() const; /** \return True if progress bar should be printed in batch mode */ bool printProgress() const; /** \return True if line numbers are filled with leading zeroes */ bool fillLineNrZeroes() const; /** \return name of help message file*/ const string getHelpLang() const; /** \return programming language */ const string &getLanguage()const ; /** \return Wrapping style*/ highlight::WrapMode getWrappingStyle() const; /** \return List of input file names*/ const vector & getInputFileNames() const; /** \return Name of indentation scheme file */ const string &getIndentScheme() const; /** \return Output file format */ highlight::OutputType getOutputType() const; /** \return True if chosen output format supports referenced style files */ bool formatSupportsExtStyle(); /** \return True if style output path was defined by user*/ bool styleOutPathDefined() const{ return opt_stylepath_explicit; } /** \return True if encoding nasme should be omitted in output*/ bool omitEncodingName() const; /** \return True if output should be generated if languege type is unknown*/ bool forceOutput() const; private: int numberSpaces; // number of spaces which replace a tab highlight::WrapMode wrappingStyle; // line wrapping mode highlight::OutputType outputType; // name of single output file string outFilename, // output directory outDirectory, // programming language which will be loaded language, // name of colour theme styleName, // name of external style file styleOutFilename, // name of file to be included in external style file styleInFilename, // used to define data directories at runtime dataDir, additionalDataDir; // name of indenation scheme string indentScheme; bool opt_language; bool opt_include_style; bool opt_help; bool opt_version ; bool opt_verbose; bool opt_linenumbers; bool opt_style; bool opt_batch_mode; bool opt_fragment; bool opt_attach_line_anchors; bool opt_show_themes; bool opt_show_langdefs; bool opt_asformat_output; bool opt_printindex; bool opt_quiet; bool opt_xslfo_fop; bool opt_replacequotes; bool opt_print_progress; bool opt_fill_zeroes; bool opt_stylepath_explicit; bool opt_force_output; bool configFileRead; string helpLang, charset; string configFilePath; // list of all input file names vector inputFileNames; /** load highlight configuration file */ void loadConfigurationFile(); /** \return file suffix */ string getFileSuffix( const string & fileName) const; /** \return directory name of path */ string getDirName( const string & path); /** get all entries in the directory defined by wildcard */ void readDirectory(const string & wildcard); /** \return Boolean value of paramVal */ bool getFlag(const string& paramVal); /** \return Valid path name */ string validateDirPath(const string & path); void printDeprecatedWarning(const char *oldOption, const char *newOption); }; #endif /*************************************************************************** codeparser.cpp - description ------------------- begin : Die Jul 9 2002 copyright : (C) 2002 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 "codegenerator.h" #include "htmlgenerator.h" #include "xhtmlgenerator.h" #include "rtfgenerator.h" #include "latexgenerator.h" #include "texgenerator.h" #include "xslfogenerator.h" #include "xmlgenerator.h" #ifndef __WXMSW__ #include "ansigenerator.h" #endif using namespace std; namespace highlight { CodeGenerator* CodeGenerator::generator=NULL; CodeGenerator* CodeGenerator::getInstance(OutputType type, const string& styleInfoPath, const string& styleInPath, const string& styleOutPath, const string& encoding, bool includeStyle, bool attachAnchors, bool replaceQuotes, bool fopCompatible, int numSpaces, WrapMode lineWrappingMode, bool ln, bool lnz, bool fragment, bool omitEncoding ) { if (generator==NULL){ switch (type){ case TEX: generator = new TexGenerator (styleInfoPath); break; case LATEX: generator = new LatexGenerator(styleInfoPath, replaceQuotes); break; case RTF: generator = new RtfGenerator (styleInfoPath); break; case XSLFO: generator = new XslFoGenerator(styleInfoPath, encoding, omitEncoding, fopCompatible); break; case XML: generator = new XmlGenerator(styleInfoPath,encoding, omitEncoding); break; case XHTML: generator = new XHtmlGenerator(styleInfoPath, encoding, omitEncoding, attachAnchors); break; #ifndef __WXMSW__ case ANSI: generator = new AnsiGenerator (styleInfoPath); break; #endif default: generator = new HtmlGenerator(styleInfoPath, encoding, omitEncoding, attachAnchors); } } generator->setType(type); generator->setStyleInputPath(styleInPath); generator->setStyleOutputPath(styleOutPath); generator->setIncludeStyle(includeStyle); generator->setPrintLineNumbers(ln); generator->setPrintZeroes(lnz); generator->setFragmentCode(fragment); generator->setPreformatting(lineWrappingMode, (generator->getPrintLineNumbers()) ? MAX_LINE__WIDTH - LINE_NUMBER_WIDTH : MAX_LINE__WIDTH, numSpaces ); return generator; } void CodeGenerator::deleteInstance(){ delete generator; generator=NULL; } CodeGenerator::CodeGenerator(): in(NULL), out(NULL), maskWs(false), excludeWs(false), fragmentOutput(false), showLineNumbers (false), lineNumberFillZeroes(false), lineNumber(0), includeStyleDef(false), lineIndex(0), formatter(NULL), preFormatter(NULL), formattingEnabled(false), formattingPossible(false), outputType(highlight::HTML) {} CodeGenerator::CodeGenerator(const string &colourTheme) :in(NULL), out(NULL), maskWs(false), excludeWs(false), fragmentOutput(false), showLineNumbers (false), lineNumberFillZeroes(false), lineNumber(0), includeStyleDef(false), stylePath(colourTheme), lineIndex(0), formatter(NULL), preFormatter(NULL), formattingEnabled(false), formattingPossible(false), outputType(highlight::HTML) { line.reserve(100); docStyle.load(stylePath); } CodeGenerator::~CodeGenerator() { delete preFormatter; delete formatter; } /** Getter and Setter*/ void CodeGenerator::setPrintLineNumbers(bool flag){ showLineNumbers=flag; } bool CodeGenerator::getPrintLineNumbers(){ return showLineNumbers; } void CodeGenerator::setPrintZeroes(bool flag){ lineNumberFillZeroes=flag; } bool CodeGenerator::getPrintZeroes(){ return lineNumberFillZeroes; } void CodeGenerator::setFragmentCode(bool flag){ fragmentOutput=flag; } void CodeGenerator::setIncludeStyle(bool flag){ includeStyleDef = flag; } void CodeGenerator::setStyleInputPath(const string& path){ styleInputPath = path; } void CodeGenerator::setStyleOutputPath(const string& path){ styleOutputPath = path; } const string& CodeGenerator::getStyleInputPath(){ return styleInputPath; } const string& CodeGenerator::getStyleOutputPath(){ return styleOutputPath; } bool CodeGenerator::getFragmentCode(){ return fragmentOutput; } void CodeGenerator::setStyleName(const string& s){ stylePath=s; } void CodeGenerator::setType(OutputType t){ outputType = t; } const string& CodeGenerator::getStyleName(){ return stylePath; } bool CodeGenerator::formattingDisabled(){ return !formattingEnabled; } bool CodeGenerator::formattingIsPossible(){ return formattingPossible; } void CodeGenerator::setPreformatting(WrapMode lineWrappingStyle, unsigned int lineLength, int numberSpaces ){ bool enableWrap = lineWrappingStyle!=WRAP_DISABLED; bool replaceTabs = numberSpaces > 0; if (enableWrap || replaceTabs) { preFormatter=new PreFormatter(enableWrap, replaceTabs); if (enableWrap) preFormatter->setWrappingProperties(lineLength, lineWrappingStyle==WRAP_DEFAULT); if (replaceTabs) preFormatter->setNumberSpaces(numberSpaces); } } /* WrapMode CodeGenerator::getLineWrapping(){ if (preFormatter==NULL) return WRAP_DISABLED; return (preFormatter->indentCode()?WRAP_DEFAULT:WRAP_SIMPLE); } */ LanguageDefinition &CodeGenerator::getLanguage(){ return langInfo; } void CodeGenerator::reset() { lineIndex = lineNumber = 0; line.clear(); } /** sucht vorwaerts ab Position searchPos Ziffer in s und liefert Integerwert der gefundenen Zahl zurueck. Im SymbolString stehen die den einzelnen Symbolen zugeordneten Konstanten immer HINTER diesen Symbolen*/ State CodeGenerator::getState(const string &s, unsigned int searchPos) { unsigned int i= searchPos+1, result=0; // nach Ziffer in s suchen do { ++i; } while ((ihasMoreLines(); if (!eof) { newLine = formatter->nextLine(); } } else // reformatting not enabled { eof = ! getline( *in, newLine); } return eof; } unsigned char CodeGenerator::getInputChar() { bool eol = lineIndex == line.length(); if (eol) { bool eof=false; if (preFormatter!=NULL){ if (!preFormatter->hasMoreLines()) { eof=readNewLine(line); preFormatter->setLine(line); } line = preFormatter->getNextLine(); } else { eof=readNewLine(line); } lineIndex=0; ++lineNumber; line=StringTools::trimRight(line); return (eof)?'\0':'\n'; } return line[lineIndex++]; } State CodeGenerator::getCurrentState (bool lastStateWasNumber) { unsigned char c; if (token.length()==0) { c=getInputChar(); } else { lineIndex-= (token.length()-1); c=token[0]; } if (c=='\n'){ return _EOL; // End of line } if (c=='\0') { return _EOF; // End of file } if (isspace(c)) { token= c; return _WS; } // numbers have to be searched before using the symbolstring, // as numbers are part of this string if (isdigit(c) // recognize floats like .5 || (c=='.' && isdigit(line[lineIndex])) // test if '-' belongs to a term like "1-2" || ((c == '-') && (!lastStateWasNumber) && isdigit(StringTools::getNextNonWs(line, lineIndex))) ) { token = getNumber(); return NUMBER; } unsigned int symbolLength; size_t symbolPos; bool found=false; string symbols=langInfo.getSymbolString(); symbolPos = symbols.find(c); // search symbols (comment delimiters, directives etc.) // before keywords, because alphabetic chars may be part of symbols, too while ((symbolPos!= string::npos) && (!found)) { symbolLength=symbols.find(' ', symbolPos)-symbolPos; token = symbols.substr(symbolPos, symbolLength); // TODO Ruby =ende, =end bugfix (whitespace after symbol needs to be checked) // Abfrage nach Leerzeichen in SymbolString verhindert falsches // Erkennen von Symbolteilen: if (lineIndex && token == line.substr(lineIndex-1, symbolLength) && isspace(symbols[symbolPos-1]) ) { found = true; lineIndex += (symbolLength-1); } else { symbolPos = symbols.find_first_not_of(' ',symbols.find(' ',symbolPos)); } } // dirty workaround stuff in here if (found) { State foundState = getState(symbols, symbolPos); // get the current keyword class id to apply the corresponding formatting style if (foundState==KEYWORD_BEGIN || foundState==TAG_BEGIN ) { currentKeywordClass=langInfo.getDelimPrefixClassID(token); } // Full line quotes must start in coloumn 1 (Fortran 77) if (langInfo.isFullLineComment() && foundState==SL_COMMENT){ if (lineIndex==1) { return SL_COMMENT; } } // VHDL Workaround: distinguish string delimiters and event markers // (same eymbol: ') else if (langInfo.isVHDL() && foundState==STRING && currentState!=STRING && lineIndex > 1 &&(isdigit(line[lineIndex-2]) || isalpha(line[lineIndex-2]))){ c=line[lineIndex-1]; // do not return, continue search... } else { return foundState; } } // Alphanumerisches Token parsen und als Keyword oder Type erkennen if (StringTools::isAlpha(c) || langInfo.isPrefix(c) || isAllowedChar(c)) { if (langInfo.isPrefix(c)){ token = c; ++lineIndex; token += getIdentifier(); } else { token = getIdentifier(); } string reservedWord=(langInfo.isIgnoreCase()) ? StringTools::lowerCase(token):token; currentKeywordClass=langInfo.isKeyword(reservedWord); return (currentKeywordClass) ? KEYWORD : STANDARD; } // Character not referring to any state token = c; return STANDARD; } string CodeGenerator::maskString(const string & s) { ostringstream ss; for (unsigned int i=0;i< s.length();i++){ ss << maskCharacter(s[i]); } return ss.str(); } void CodeGenerator::printMaskedToken(bool flushWhiteSpace) { if(flushWhiteSpace) flushWs(); *out << maskString(token); token.clear(); } bool CodeGenerator::isAllowedChar(char c) { return ( langInfo.getAllowedChars().find(c)!= string::npos); } bool CodeGenerator::styleFound(){ return docStyle.found(); } bool CodeGenerator::printIndexFile(const vector &fileList, const string &outPath){ return true; } bool CodeGenerator::initIndentationScheme(const string &schemePath){ if (formatter!=NULL){ return true; } ConfigurationReader indentScheme(schemePath); if (indentScheme.found()){ if (formatter==NULL) { formatter=new astyle::ASFormatter(); string brackets=indentScheme.getParameter("brackets"); if (!brackets.empty()){ // Break brackets from pre-block code (i.e. ANSI C/C++ style). if (brackets=="break"){ formatter->setBracketFormatMode(astyle::BREAK_MODE); } //Attach brackets to pre-block code (i.e. Java/K&R style). else if (brackets=="attach"){ formatter->setBracketFormatMode(astyle::ATTACH_MODE); } // Break definition-block brackets and attach command-block brackets. else if (brackets=="linux"){ formatter->setBracketFormatMode(astyle::BDAC_MODE); } // Break brackets before closing headers (e.g. 'else', 'catch', ..). // Should be appended to --brackets=attach or --brackets=linux. else if (brackets=="break-closing-headers"){ formatter->setBreakClosingHeaderBracketsMode(true); } } string pad=indentScheme.getParameter("pad"); if (!pad.empty()){ //Insert space paddings around parenthesies only. if (pad=="paren"){ formatter->setParenthesisPaddingMode(true); } // Insert space paddings around operators only. else if (pad=="oper"){ formatter->setOperatorPaddingMode(true); } //Insert space paddings around operators AND parenthesies. else if (pad=="all"){ formatter->setOperatorPaddingMode(true); formatter->setParenthesisPaddingMode(true); } } string oneLine=indentScheme.getParameter("one-line"); if (!oneLine.empty()){ // Don't break one-line blocks. if (oneLine=="keep-blocks"){ formatter->setBreakOneLineBlocksMode(false); } // Don't break complex statements and multiple statements residing in a // single line. else if (oneLine=="keep-statements"){ formatter->setSingleStatementsMode(false); } } // Insert empty lines around unrelated blocks, labels, classes, ... string breakBlocks=indentScheme.getParameter("break-blocks"); if (!breakBlocks.empty()){ if (breakBlocks=="all"){ //Like --break-blocks, except also insert empty lines around closing //headers (e.g. 'else', 'catch', ...). formatter->setBreakClosingHeaderBlocksMode(true); } formatter->setBreakBlocksMode(true); } string trueVal="true"; // Other options... //Indent using # spaces per indent. Not specifying # will result in a //default of 4 spaces per indent. string indentSpaces=indentScheme.getParameter("indent-spaces"); // Indent a minimal # spaces in a continuous conditional belonging to a //conditional header. string minConditionalIndent=indentScheme.getParameter("min-conditional-indent"); // Indent a maximal # spaces in a continuous statement, relatively to the // previous line. string maxInStatementIndent=indentScheme.getParameter("max-instatement-indent"); // Add extra indentation to '{' and '}' block brackets. string indentBrackets=indentScheme.getParameter("indent-brackets"); // Add extra indentation entire blocks (including brackets). string indentBlocks=indentScheme.getParameter("indent-blocks"); // Indent the contents of namespace blocks. string indentNamespaces=indentScheme.getParameter("indent-namespaces"); // Indent 'class' blocks, so that the inner 'public:','protected:' and // 'private: headers are indented inrelation to the class block. string indentClasses=indentScheme.getParameter("indent-classes"); // Indent 'switch' blocks, so that the inner 'case XXX:' headers are // indented in relation to the switch block. string indentSwitches=indentScheme.getParameter("indent-switches"); // Indent 'case XXX:' lines, so that they are flush with their bodies.. string indentCases=indentScheme.getParameter("indent-cases"); // Indent labels so that they appear one indent less than the current // indentation level, rather than being flushed completely to the left // (which is the default). string indentLabels=indentScheme.getParameter("indent-labels"); // Indent multi-line #define statements string indentPreprocessor=indentScheme.getParameter("indent-preprocessor"); // Break 'else if()' statements into two different lines. string breakElseIfs = indentScheme.getParameter("break-elseifs"); string javaStyle = indentScheme.getParameter("java-style"); // default values in ASBeautifier are false, it is ok to set them false // if parameter does not exist in scheme file formatter->setBracketIndent(indentBrackets==trueVal); formatter->setBlockIndent(indentBlocks==trueVal); formatter->setNamespaceIndent(indentNamespaces==trueVal); formatter->setClassIndent(indentClasses==trueVal); formatter->setSwitchIndent(indentSwitches==trueVal); formatter->setCaseIndent(indentCases==trueVal); formatter->setLabelIndent(indentLabels==trueVal); formatter->setPreprocessorIndent(indentPreprocessor==trueVal); formatter->setBreakElseIfsMode(breakElseIfs==trueVal); if (javaStyle==trueVal){ formatter->setJavaStyle(); } if (!indentSpaces.empty()){ formatter->setSpaceIndentation(StringTools::str2int(indentSpaces)); } if (!minConditionalIndent.empty()){ formatter->setMinConditionalIndentLength( StringTools::str2int(minConditionalIndent)); } if (!maxInStatementIndent.empty()){ formatter->setMinConditionalIndentLength( StringTools::str2int(maxInStatementIndent)); } } formattingEnabled=(formatter != NULL); return true; } else { return false; } } LoadResult CodeGenerator::initLanguage(const string& langDefPath){ bool reloadNecessary= langInfo.needsReload(langDefPath); if (reloadNecessary){ bool failure = !langInfo.load(langDefPath); if (failure) { return LOAD_FAILED; } formattingPossible=langInfo.enableReformatting(); if (styleTagOpen.size()>NUMBER_BUILTIN_STYLES){ // remove dynamic keyword tag delimiters of the old language definition vector::iterator keyStyleOpenBegin = styleTagOpen.begin() + NUMBER_BUILTIN_STYLES; vector::iterator keyStyleCloseBegin = styleTagClose.begin()+ NUMBER_BUILTIN_STYLES; styleTagOpen.erase(keyStyleOpenBegin, styleTagOpen.end()); styleTagClose.erase(keyStyleCloseBegin, styleTagClose.end()); } // add new keyword delimiters for (unsigned int i=0;i< langInfo.getKeywordClasses().size(); i++){ styleTagOpen.push_back(getMatchingOpenTag(i)); styleTagClose.push_back(getMatchingCloseTag(i)); } } return (reloadNecessary) ? LOAD_NEW : LOAD_NONE; } ParseError CodeGenerator::printOutput (const string & inFileName, const string &outFileName) { if (!docStyle.found()) { return BAD_STYLE; } reset(); ParseError error=PARSE_OK; in = (inFileName.empty()? &cin :new ifstream (inFileName.c_str())); if (!in->fail()) { out = (outFileName.empty()? &cout :new ofstream (outFileName.c_str())); if ( out->fail()) { error=BAD_OUTPUT; } } if ( in->fail()){ error=BAD_INPUT; } if (error==PARSE_OK) { if (formatter != NULL){ formatter->init(new astyle::ASStreamIterator(in)); } if (! fragmentOutput){ *out << getHeader(inFileName); } printBody(); if (! fragmentOutput){ *out << getFooter(); } } if (!outFileName.empty()){ delete out; out=NULL; } if (!inFileName.empty()) { delete in; in=NULL; } return error; } unsigned int CodeGenerator::getStyleID(State s, unsigned int kwClassID){ if (s==KEYWORD && kwClassID){ return NUMBER_BUILTIN_STYLES + kwClassID-1; } return (unsigned int) s ; } void CodeGenerator::closeTag(State s){ *out << styleTagClose[(unsigned int)s]; flushWs(); currentState=_UNKNOWN; } void CodeGenerator::openTag(State s){ *out << styleTagOpen[(unsigned int)s]; currentState=s; } void CodeGenerator::closeKWTag(unsigned int kwClassID){ *out << styleTagClose[getStyleID(KEYWORD, kwClassID)]; flushWs(); currentState=_UNKNOWN; } void CodeGenerator::openKWTag(unsigned int kwClassID){ *out << styleTagOpen[getStyleID(KEYWORD, kwClassID)]; currentState=KEYWORD; } /////////////////////////////////////////////////////////////////////////////// void CodeGenerator::processRootState() { if (langInfo.highlightingDisabled()){ string line; while (getline(*in, line)){ *out << maskString(line) << getNewLine(); } *out << flush; return; } State state=STANDARD; bool eof=false, firstLine=true; // avoid newline before printing the first output line openTag(STANDARD); do { // determine next state state= getCurrentState(state==NUMBER); // handle current state switch(state) { case KEYWORD: case KEYWORD_BEGIN: closeTag(STANDARD); eof=processKeywordState(state); openTag(STANDARD); break; case NUMBER: closeTag(STANDARD); eof=processNumberState(); openTag(STANDARD); break; case ML_COMMENT_BEGIN: closeTag(STANDARD); eof=processMultiLineCommentState(); openTag(STANDARD); break; case SL_COMMENT: closeTag(STANDARD); eof=processSingleLineCommentState(); openTag(STANDARD); break; case STRING: closeTag(STANDARD); eof=processStringState(STANDARD); openTag(STANDARD); break; case DIRECTIVE_LINE: closeTag(STANDARD); eof=processDirectiveState(); openTag(STANDARD); break; case TAG_BEGIN: closeTag(STANDARD); eof=processTagState(); openTag(STANDARD); break; case ESC_CHAR: if (langInfo.allowExtEscSeq()){ closeTag(STANDARD); eof=processEscapeCharState(); openTag(STANDARD); } else { printMaskedToken(); } break; case SYMBOL: closeTag(STANDARD); eof=processSymbolState(); openTag(STANDARD); break; case _EOL: insertLineNumber(!firstLine); firstLine=false; break; case _EOF: eof=true; break; case _WS: processWsState(); break; default: printMaskedToken(); break; } } while (!eof); closeTag(STANDARD); *out << getNewLine(); *out << flush; } bool CodeGenerator::processKeywordState(State myState){ State newState=STANDARD; unsigned int myClassID=currentKeywordClass; bool eof=false, exitState=false; openKWTag(myClassID); do { printMaskedToken(newState!=_WS); newState= getCurrentState(); switch(newState) { case _WS: processWsState(); break; case _EOL: insertLineNumber(); exitState=true; break; case _EOF: eof = true; break; case KEYWORD_END: if (myState==KEYWORD_BEGIN){ printMaskedToken(); } exitState=true; break; default: exitState= myState!=KEYWORD_BEGIN &&((myClassID!=currentKeywordClass)||(myState!=newState)); break; } } while ((!exitState) && (!eof)); closeKWTag(myClassID); currentKeywordClass=0; return eof; } bool CodeGenerator::processNumberState(){ State newState=STANDARD; bool eof=false, exitState=false; openTag(NUMBER); do { printMaskedToken(newState!=_WS); newState= getCurrentState(true); switch(newState) { case _WS: processWsState(); break; case _EOL: insertLineNumber(); exitState=true; break; case _EOF: eof = true; break; default: exitState=newState!=NUMBER; break; } } while ((!exitState) && (!eof)); closeTag(NUMBER); return eof; } bool CodeGenerator::processMultiLineCommentState() { int commentCount=1; State newState=STANDARD; bool eof=false, exitState=false; openTag(ML_COMMENT_BEGIN); do { printMaskedToken(newState!=_WS); newState= getCurrentState(); switch(newState) { case _WS: processWsState(); break; case _EOL: wsBuffer += styleTagClose[ML_COMMENT_BEGIN]; insertLineNumber(); wsBuffer += styleTagOpen[ML_COMMENT_BEGIN]; break; case _EOF: eof = true; break; case ML_COMMENT_BEGIN: if (langInfo.allowNestedMLComments()) { ++commentCount; } break; case ML_COMMENT_END: commentCount--; if (!commentCount){ printMaskedToken(); exitState=true; } break; default: break; } } while ((!exitState) && (!eof)); closeTag(ML_COMMENT_BEGIN); return eof; } bool CodeGenerator::processSingleLineCommentState() { //if ( checkSpecialCmd()) return false; State newState=STANDARD; bool eof=false, exitState=false; openTag(SL_COMMENT); do { printMaskedToken(newState!=_WS); newState= getCurrentState(); switch(newState) { case _WS: processWsState(); break; case _EOL: printMaskedToken(); insertLineNumber(); exitState=true; break; case _EOF: eof = true; break; default: break; } } while ((!exitState) && (!eof)); closeTag(SL_COMMENT); return eof; } bool CodeGenerator::processDirectiveState() { State newState=STANDARD; bool eof=false, exitState=false; openTag(DIRECTIVE_LINE); do { printMaskedToken(newState!=_WS); newState= getCurrentState(); switch(newState) { case _WS: processWsState(); break; case DIRECTIVE_LINE_END: printMaskedToken(); exitState=true; break; case _EOL: printMaskedToken(); exitState=(terminatingChar!=langInfo.getContinuationChar()); if (!exitState) wsBuffer += styleTagClose[DIRECTIVE_LINE]; insertLineNumber(); if (!exitState) wsBuffer += styleTagOpen[DIRECTIVE_LINE]; break; case ML_COMMENT_BEGIN: closeTag(DIRECTIVE_LINE); eof= processMultiLineCommentState(); openTag(DIRECTIVE_LINE); break; case SL_COMMENT: closeTag(DIRECTIVE_LINE); eof= processSingleLineCommentState(); openTag(DIRECTIVE_LINE); exitState=true; break; case STRING: closeTag(DIRECTIVE_LINE); eof=processStringState(DIRECTIVE_LINE); openTag(DIRECTIVE_LINE); break; case _EOF: eof = true; break; default: break; } } while ((!exitState) && (!eof)); closeTag(DIRECTIVE_LINE); return eof; } bool CodeGenerator::processStringState(State oldState) { State newState=STANDARD; bool eof=false, exitState=false; bool returnedFromOtherState=false; // Test if character before string open delimiter token equals to the // raw string prefix (Example: r" ", r""" """ in Python) bool isRawString= line[lineIndex-token.length()-1]==langInfo.getRawStringPrefix(); string openStringDelimiter=token; State myState= (oldState==DIRECTIVE_LINE) ? DIRECTIVE_STRING : STRING; openTag(myState); do { // true if last token was an escape char if (!returnedFromOtherState) { printMaskedToken(newState!=_WS); } returnedFromOtherState=false; newState= getCurrentState(); switch(newState) { case _WS: processWsState(); break; case _EOL: wsBuffer += styleTagClose[myState]; insertLineNumber(); wsBuffer += styleTagOpen[myState]; //exitState=true; break; case ML_COMMENT_END: printMaskedToken(); break; case STRING: exitState= openStringDelimiter==token; printMaskedToken(); break; case ESC_CHAR: if (!isRawString){ closeTag(myState); eof=processEscapeCharState(); openTag(myState); returnedFromOtherState=true; } break; case _EOF: eof = true; break; default: printMaskedToken(); break; } } while ((!exitState) && (!eof)); closeTag(myState); return eof; } bool CodeGenerator::processTagState() { State newState=STANDARD; bool eof=false, exitState=false, returnedFromOtherState=false; unsigned int myKeywordClass=currentKeywordClass; openTag(KEYWORD); do { if (!returnedFromOtherState) { printMaskedToken(newState!=_WS); } returnedFromOtherState = false; newState= getCurrentState(); switch(newState) { case _WS: processWsState(); break; case _EOL: insertLineNumber(); exitState=true; break; case TAG_END: printMaskedToken(); exitState=true; break; case STRING: closeTag(KEYWORD); eof=processStringState(KEYWORD); currentKeywordClass=myKeywordClass; openTag(KEYWORD); returnedFromOtherState = true; break; case ESC_CHAR: closeTag(KEYWORD); eof=processEscapeCharState(); currentKeywordClass=myKeywordClass; openTag(KEYWORD); returnedFromOtherState = true; break; case NUMBER: closeTag(KEYWORD); eof=processNumberState(); currentKeywordClass=myKeywordClass; openTag(KEYWORD); returnedFromOtherState = true; break; case _EOF: eof = true; break; default: printMaskedToken(); break; } } while ((!exitState) && (!eof)); closeTag(KEYWORD); currentKeywordClass=0; return eof; } bool CodeGenerator::processSymbolState(){ State newState=STANDARD; bool eof=false, exitState=false; openTag(SYMBOL); do { printMaskedToken(newState!=_WS); newState= getCurrentState(true); switch(newState) { case _WS: processWsState(); break; case _EOL: insertLineNumber(); exitState=true; break; case _EOF: eof = true; break; default: exitState=newState!=SYMBOL; break; } } while ((!exitState) && (!eof)); closeTag(SYMBOL); return eof; } bool CodeGenerator::processEscapeCharState() { State newState=STANDARD; bool eof=false, exitState=false; openTag(ESC_CHAR); do { printMaskedToken(newState!=_WS); skipEscapeSequence(); newState= getCurrentState(); switch(newState) { case _EOL: insertLineNumber(); exitState=true; break; case _WS: processWsState(); --lineIndex; break; case _EOF: eof = true; break; default: exitState=newState!=ESC_CHAR; break; } } while ((!exitState) && (!eof)); closeTag(ESC_CHAR); return eof; } void CodeGenerator::skipEscapeSequence(){ if (lineIndex1) { unsigned int styleID=getStyleID(currentState, currentKeywordClass); if (excludeWs && styleID!=_UNKNOWN) { *out << styleTagClose[styleID]; } *out << maskWsBegin; for (int i=0; i #include #include #include #include #include "languagedefinition.h" #include "documentstyle.h" #include "ASFormatter.h" #include "preformatter.h" #include "enums.h" #define NUMBER_BUILTIN_STYLES 10 #define LINE_NUMBER_WIDTH 5 #define MAX_LINE__WIDTH 80 #define OUTPUT_FLAG_LN 1 #define OUTPUT_FLAG_LNZ 2 #define OUTPUT_FLAG_FRAG 4 /** The highlight namespace contains all classes and data structures needed for parsing input data. */ namespace highlight { /** \brief Base class for parsing. Works similar to a Turing machine. The virtual class provides source code parsing functioality, based on information stored in language definitions.
Deriving classes have to define the output format.
Codegenerator is a singleton class. * @author Andre Simon */ class CodeGenerator { public: virtual ~CodeGenerator(); /** Get appropriate Codegenerator instance \param type Output file type (HTML, XHTML, RTF, LATEX, TEX, XSLFO, ANSI) \param styleInfoPath Path to formatting style information \param styleInPath Path to style definition input file (to be included in styleOutPath) \param styleOutPath Path to style definition output file (CSS path for HTML output) \param encoding Output file encoding name \param includeStyle Switch to include style information in output file (only XHTML, HTML) \param attachAnchors Switch to attach anchors to line numbers (only XHTML, HTML) \param replaceQuotes Switch to replace quotes by \dq{} (only LATEX) \param fopCompatible Switch to generate FO for Apache FOP (only XSLFO) \param omitEncoding Switch to omit encoding info in output document \param ln Set true if line numbers should be printed \param lnz Set true if leading space of line numbers should be filled with 0's \param fragment Set true if document header and footer should be omitted \param numSpaces Number of spaces which replace a tab \param lineWrappingMode Line wrapping mode */ static CodeGenerator* getInstance(OutputType type, const string& styleInfoPath, const string& styleInPath, const string& styleOutPath, const string& encoding, bool includeStyle, bool attachAnchors, bool replaceQuotes, bool fopCompatible, int numSpaces, WrapMode lineWrappingMode, bool ln, bool lnz, bool fragment, bool omitEncoding ); /** Deletes the singleton CodeGenerator instance. Call this method if getInstance was already called, or if you want to free the momory after usage.*/ static void deleteInstance(); /** Generates output \param inFileName Path of input file (if empty use stdin) \param outFileName Path of input file (if empty use stdout) \return ParseError */ ParseError printOutput(const string &inFileName, const string &outFileName); /** \return True if document style was found */ bool styleFound(); /** \return True if reformatting of current input is disabled */ bool formattingDisabled(); /** \return True if reformatting of current input is possible */ bool formattingIsPossible(); /** \param langDefPath Absolute path to language definition \return Failure: LOAD_FAILED; Reload necessary: LOAD_NEW, no reload necessary: LOAD_NONE */ LoadResult initLanguage(const string& langDefPath); /** \return Language definition*/ LanguageDefinition &getLanguage(); /** tell parser to output line numbers \param flag true if line numbers should be printed */ void setPrintLineNumbers(bool flag); /** \return line number flag */ bool getPrintLineNumbers(); /** tell parser to output line numbers filled with zeroes \param flag true if zeroes should be printed */ void setPrintZeroes(bool flag); /** \return print zeroes flag */ bool getPrintZeroes(); /** tell parser to omit document header and footer \param flag true if output should be fragmented */ void setFragmentCode(bool flag); /** \return fragment flag */ bool getFragmentCode(); /** tell parser the style name \param s path to style definition */ void setStyleName(const string& s); /** \return style path */ const string& getStyleName(); /** tell parser the wrapping mode \param lineWrappingStyle wrapping style \param lineLength max line length \param numberSpaces number of spaces which replace a tab */ void setPreformatting(WrapMode lineWrappingStyle, unsigned int lineLength,int numberSpaces); /** \return wrapping style */ WrapMode getLineWrapping(); /** tell parser the include style definition in output \param flag true if style should be included */ void setIncludeStyle(bool flag); /** Print style definitions to external file \param outFile Path of external style definition */ bool printExternalStyle(const string &outFile); /** Print index file with all input file names \param fileList List of output file names \param outPath Output path */ virtual bool printIndexFile(const vector & fileList, const string &outPath); /** initialize source code indentation \param indentSchemePath Path of indentation scheme \return true id successfull */ bool initIndentationScheme(const string&indentSchemePath); /** Set style input path \param s path to style input file */ void setStyleInputPath(const string& path); /** Set style output path \param s path to style output file */ void setStyleOutputPath(const string& path); /** Set output type \param s output type */ void setType(OutputType t); /** \return style input file path */ const string& getStyleInputPath(); /** \return style output file path */ const string& getStyleOutputPath(); protected: CodeGenerator(); //! CodeGenerator Constructor /** \param colourTheme Name of coloring style being used */ CodeGenerator(const string &colourTheme); /** \param c Character to be masked \return Escape sequence of output format */ virtual string maskCharacter(unsigned char c) = 0; /** \param s string \return Copy of s with all escaped characters */ string maskString(const string &s ) ; /** \param s Symbol string \param searchPos Position where search starts \return Found state (integer value) */ State getState(const string &s, unsigned int searchPos); /** \return Next identifier in current line of code */ string getIdentifier(); /** \return Next number in current line of code */ string getNumber(); /** Insert line number at the beginning of current output line */ virtual void insertLineNumber(bool insertNewLine=true); /** Prints document footer*/ virtual string getFooter() = 0; /** Prints document body*/ virtual void printBody() = 0; /** prints document header \param title Title of the document */ virtual string getHeader(const string &title) = 0; /** Get current line number \return line number */ unsigned int getLineNumber(); /** Tag Delimiters for every colour style*/ vector styleTagOpen, styleTagClose; /** Description of document colour style*/ DocumentStyle docStyle; /** Language definition*/ LanguageDefinition langInfo; /** Tag for inserting line feeds*/ string newLineTag; /** String that represents a white space in output */ string spacer; /** file input*/ istream *in; /** file output*/ ostream *out; /** Tags which enclose white space indentation blocks */ string maskWsBegin, maskWsEnd; /** Style comment delimiters */ string styleCommentOpen, styleCommentClose; /** Test if maskWsBegin and maskWsEnd should be applied */ bool maskWs; /** Test if whitespace sould always be separated from enclosing tokens */ bool excludeWs; /** Test if header and footer should be omitted */ bool fragmentOutput; /** Test if line numbers should be printed */ bool showLineNumbers; /** Test if leading spyce of line number should be filled with zeroes*/ bool lineNumberFillZeroes; /** Current line of input file*/ string line; /** Current line number */ unsigned int lineNumber; // Zeigt den aktuellen Zustand an // wird nicht in getCurrentState gesetzt, da nur Zustände interessant // sind, die als Index auf die styleCloseTags und styleOpenTags verwendet // werden können /** Current state*/ State currentState; /** keyword class id, used to apply the corresponding keyword style*/ unsigned int currentKeywordClass; /** Processes origin state */ void processRootState(); /** return line break sequence */ virtual string getNewLine(); /** \param s current state \return Index of style tag corresponding to the states */ unsigned int getStyleID(State s, unsigned int kwClassID = 0); /** \return line index */ unsigned int getLineIndex(); /** print all remaining white space*/ void flushWs(); /** \return Content of user defined input style */ string readUserStyleDef(); /** \return Style definition of the chosen output format */ virtual string getStyleDefinition() {return "";}; /** contains white space, which will be printed after a closing tag */ string wsBuffer; /** Flag to test if style definition should be included in output document */ bool includeStyleDef; private: CodeGenerator(const CodeGenerator&){} CodeGenerator& operator=(CodeGenerator&){ return *this;} static CodeGenerator* generator; /** return matching open and close tags of the given state */ virtual string getMatchingOpenTag(unsigned int) = 0; virtual string getMatchingCloseTag(unsigned int) = 0; /** open a new tag, set current state to s*/ void openTag(State s); /** close opened tag, clear current state */ void closeTag(State s); void closeTag(unsigned int styleID); void openTag(unsigned int styleID); // path to style definition file string stylePath; // contains current position in line unsigned int lineIndex; /**last character of the last line*/ unsigned char terminatingChar; /** Class for reformatting */ astyle::ASFormatter *formatter; /** Class for line wrapping and tab replacement*/ PreFormatter *preFormatter; /** Flag to test if formatting is enabled with current input document*/ bool formattingEnabled; /** Flag to test if formatting is possible with current input document*/ bool formattingPossible; /** contains the current token*/ string token; string styleInputPath, styleOutputPath; /** Resets parser to origin state, call this after every file conversion */ void reset(); /** read new line from in stream */ bool readNewLine(string &newLine); /** return next character from in stream */ unsigned char getInputChar(); OutputType outputType; /** return new state */ State getCurrentState ( bool lastStateWasNumber=false); /** Methods that represent a parsing state */ bool processKeywordState(State myState) ; bool processNumberState() ; bool processMultiLineCommentState(); bool processSingleLineCommentState(); bool processStringState(State oldState); bool processEscapeCharState(); bool processDirectiveState(); bool processTagState(); bool processSymbolState(); void processWsState(); /** gibt true zurck, falls c ein erlaubter Character innerhalb von Keyword oder Typbezeichner ist */ bool isAllowedChar(char c) ; /** returns true if curret token is the first in line and no whitespace */ bool isFirstNonWsChar() ; /** print escaped token and clears it */ void printMaskedToken(bool flushWhiteSpace=true); /** print escape sequence */ void skipEscapeSequence(); void closeKWTag(unsigned int styleID); void openKWTag(unsigned int styleID); /** look for special commands in comments, take action in derived class \return true if command was found */ bool checkSpecialCmd(); }; } #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. */ /* * 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 /*************************************************************************** configurationreader.cpp - description ------------------- begin : Son Nov 10 2002 copyright : (C) 2002 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 "configurationreader.h" using namespace std; ConfigurationReader::ConfigurationReader(const string & configuration_path) { ifstream in (configuration_path.c_str()); fileFound=in; if (fileFound) { string line; line.reserve(500); unsigned int lineBegin; size_t delimPos; string paramName, paramValue; while (getline(in, line)) { lineBegin=line.find_first_not_of("\t "); if ((line.size()>2) && (lineBegin!=string::npos) && (line.at(lineBegin)!='#')) { //comment? if (line[lineBegin]=='$') { // neuer Parametername? delimPos=line.find("=",lineBegin)-1; if (delimPos!=string::npos) { paramName=StringTools::trimRight( StringTools::lowerCase(line.substr(lineBegin+1, delimPos))); parameterNames.push_back(paramName); paramValue=line.substr(delimPos+2, line.length()); } } else { // line belongs to last parameter paramValue=line; } if (parameterMap[paramName].empty()) { parameterMap[paramName] = paramValue; } else { parameterMap[paramName]+= (" "+paramValue); } } //if ((lineBegin!=string::npos) && (line.at(lineBegin)!='#')) } //while in.close(); } //if (in) } ConfigurationReader::~ConfigurationReader() { } bool ConfigurationReader::found() { return fileFound; } string &ConfigurationReader::getParameter(const string & paramName) { return parameterMap[paramName] ; } const char* ConfigurationReader::getCParameter(const string & paramName) { return parameterMap[paramName].c_str() ; } vector &ConfigurationReader::getParameterNames() { return parameterNames; } /*************************************************************************** configurationreader.h - description ------------------- begin : Son Nov 10 2002 copyright : (C) 2002 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. * * * ***************************************************************************/ #ifndef CONFIGURATIONREADER_H #define CONFIGURATIONREADER_H #include #include #include #include #include #include #include "stringtools.h" using namespace std; /** Maps parameter keys to values*/ typedef map ParameterMap; /** \brief Class to handle ASCII config files Configuration file format:
$ParamName=ParamValue
ParamValue may be splittet over multiple lines
ParamName is not case sensitive
Comments start with # as the first character of a line **/ class ConfigurationReader { public: /** Constructor \param configuration_path Path to configuration file */ ConfigurationReader(const string & configuration_path); ~ConfigurationReader(); /** \param paramName Name of parameter \return Value of parameter */ string &getParameter(const string & paramName); /** \param paramName Name of parameter \return Value of parameter */ const char* getCParameter(const string & paramName); /** \return True if config file exists */ bool found(); /** \return List of parameter names */ vector &getParameterNames(); private: ParameterMap parameterMap; bool fileFound; vector parameterNames; }; #endif /*************************************************************************** dataDir.cpp - description ------------------- begin : Sam M� 1 2003 copyright : (C) 2003 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 "datadir.h" using namespace std; bool DataDir::searchDataDir(const string &userDefinedDir){ #ifndef _WIN32 bool found = false; //falls kein Datenverzeichnis angegeben, startIndex auf 1 setzen int searchStartIndex=(userDefinedDir.empty()); string possibleDirs[] ={ userDefinedDir, #ifdef HL_DATA_DIR HL_DATA_DIR, #endif "/usr/share/highlight/" }; for (int i=searchStartIndex;i< #ifdef HL_DATA_DIR 3 #else 2 #endif ;i++) { if (fileExists(possibleDirs[i])) { dataDir=possibleDirs[i]; found = true; } if (found) { break; } else { if (!searchStartIndex) cerr << "highlight: directory " << userDefinedDir << " specified by data-dir option not found.\n" << " Searching another standard directory.\n"; } } return found; #else dataDir=userDefinedDir; return true; #endif } DataDir::DataDir() { } void DataDir::setAdditionalDataDir(const string& dir){ additionalDataDir=dir; } const string &DataDir::getDir() { return dataDir; } const string DataDir::getLangDefDir() { return dataDir+"langDefs"+Platform::pathSeparator; } const string DataDir::getThemeDir() { return dataDir+"themes"+Platform::pathSeparator; } const string DataDir::getIndentSchemesDir() { return dataDir+"indentSchemes"+Platform::pathSeparator; } const string DataDir::getAdditionalLangDefDir() { return additionalDataDir+"langDefs"+Platform::pathSeparator; } const string DataDir::getAdditionalThemeDir() { return additionalDataDir+"themes"+Platform::pathSeparator; } const string DataDir::getAdditionalIndentSchemesDir() { return additionalDataDir+"indentSchemes"+Platform::pathSeparator; } const string DataDir::getHelpMsgDir() { return dataDir+"helpmsg"+Platform::pathSeparator; } const string DataDir::searchForLangDef(const string & langDef){ if (!additionalDataDir.empty()){ string path=getAdditionalLangDefDir()+langDef; if (fileExists(path)){ return path; } } return getLangDefDir()+langDef; } const string DataDir::searchForTheme(const string & theme){ if (!additionalDataDir.empty()){ string path=getAdditionalThemeDir()+theme; if (fileExists(path)){ return path; } } return getThemeDir()+theme; } const string DataDir::searchForIndentScheme(const string & scheme){ if (!additionalDataDir.empty()){ string path=getAdditionalIndentSchemesDir()+scheme; if (fileExists(path)){ return path; } } return getIndentSchemesDir()+scheme; } bool DataDir::fileExists(const string&f){ ifstream file(f.c_str()); bool exists=!file.fail(); file.close(); return exists; } /*************************************************************************** datadir.h - description ------------------- begin : Sam M� 1 2003 copyright : (C) 2003 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 DATADIR_H #define DATADIR_H #include #include #include //#include "stringtools.h" #include "platform_fs.h" using namespace std; /** \brief Manages access to installation directories. Apart from the standard installation directory, one can define additional search paths. **/ class DataDir { string dataDir; string additionalDataDir; bool fileExists(const string&f); public: DataDir(); /** search for a valid installation directory \param userDefinedDir Directory defined by user \return True if directory was found */ bool searchDataDir(const string &userDefinedDir); /** add another installation directory, which is added to search path \param dir Directory defined by user */ void setAdditionalDataDir(const string& dir); /** \return Data installation directory */ const string & getDir() ; /** \return Location of languafe definitions */ const string getLangDefDir() ; /** \return Location of themes */ const string getThemeDir() ; /** \return Location of indentation schemes */ const string getIndentSchemesDir(); /** \return User defined location of indentation schemes */ const string getAdditionalIndentSchemesDir(); /** \return User defined location of languafe definitions */ const string getAdditionalLangDefDir() ; /** \return User defined location of themes */ const string getAdditionalThemeDir() ; /** \return Location of help files */ const string getHelpMsgDir() ; /** \param langDef Name of language definition \return Absolute path of definiton found in a data directory */ const string searchForLangDef(const string & langDef); /** \param theme Name of colour theme file \return Absolute path of theme found in a data directory */ const string searchForTheme(const string & theme); /** \param scheme Name of indent scheme file \return Absolute path of theme found in a data directory */ const string searchForIndentScheme(const string & scheme); }; #endif /*************************************************************************** documentstyle.cpp - description ------------------- begin : Son Nov 10 2002 copyright : (C) 2002 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. * * * ***************************************************************************/ #include "documentstyle.h" namespace highlight { DocumentStyle::DocumentStyle(const string &styleDefinitionFile) { fileFound=load(styleDefinitionFile); } DocumentStyle::DocumentStyle():fileFound(false) {} bool DocumentStyle::load(const string &styleDefinitionPath) { ConfigurationReader styleConfig(styleDefinitionPath); if (styleConfig.found()){ fontsize = styleConfig.getParameter("fontsize"); bgColour.setRGBValues(styleConfig.getParameter("bgcolour")); defaultElem.set(styleConfig.getParameter("defaultcolour")); comment.set(styleConfig.getParameter("comment")); directive.set(styleConfig.getParameter("directive")); str.set(styleConfig.getParameter("string")); escapeChar.set(styleConfig.getParameter("escapechar")); number.set(styleConfig.getParameter("number")); dstr.set(styleConfig.getParameter("string_directive")); line.set(styleConfig.getParameter("line")); string tmpstr; // TODO: Remove this check as soon as all themes have a brackets attribute tmpstr=styleConfig.getParameter("symbol"); if (tmpstr.empty()) { tmpstr=styleConfig.getParameter("defaultcolour"); } symbol.set(tmpstr); // TODO: Remove this check as soon as all themes have a sl-comment attribute tmpstr=styleConfig.getParameter("sl-comment"); if (tmpstr.empty()) { tmpstr=styleConfig.getParameter("comment"); } slcomment.set(tmpstr); string paramVal; vector paramNames=styleConfig.getParameterNames(); //collect keyword classes, save corresponding style definition for (unsigned int i=0;i DocumentStyle::getClassNames(){ vector kwClassNames; for(KSIterator iter = keywordStyles.begin(); iter != keywordStyles.end(); iter++){ kwClassNames.push_back( (*iter).first); } return kwClassNames; } KeywordStyles& DocumentStyle::getKeywordStyles(){ return keywordStyles; } } /*************************************************************************** documentstyle.h - description ------------------- begin : Son Nov 10 2002 copyright : (C) 2002 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 DOCUMENTSTYLE_H #define DOCUMENTSTYLE_H #include #include #include "configurationreader.h" #include "elementstyle.h" #include "stylecolour.h" using namespace std; namespace highlight { /** maps keyword class names and the corresponding formatting information*/ typedef map KeywordStyles; /** iterator for keyword styles*/ typedef KeywordStyles::iterator KSIterator; /** \brief Contains information about document formatting properties. * @author Andre Simon */ class DocumentStyle { private: ElementStyle comment, slcomment, str, dstr, escapeChar, number, directive, line, symbol; ElementStyle defaultElem; StyleColour bgColour; string fontsize; bool fileFound; KeywordStyles keywordStyles; public: /** Constructor \param styleDefinitionPath Style definition path */ DocumentStyle(const string & styleDefinitionPath); DocumentStyle(); ~DocumentStyle(); /** load sytle definition \param styleDefinitionFile Style definition path \return True if successfull */ bool load(const string & styleDefinitionFile); /** \return class names defined in the theme file */ vector getClassNames(); /** \return keyword styles */ KeywordStyles& getKeywordStyles(); /** \return Font size */ string &getFontSize() ; /** \return Background colour*/ StyleColour& getBgColour(); /** \return Style of default (unrecognized) strings */ ElementStyle & getDefaultStyle() ; /** \return Comment style*/ ElementStyle & getCommentStyle() ; /** \return Single line comment style*/ ElementStyle& getSingleLineCommentStyle() ; /** \return Keyword style*/ ElementStyle & getKeywordStyle() ; /** \return String style*/ ElementStyle & getStringStyle() ; /** \return Directive line string style*/ ElementStyle & getDirectiveStringStyle() ; /** \return Escape character style*/ ElementStyle & getEscapeCharStyle() ; /** \return Number style*/ ElementStyle & getNumberStyle() ; /** \return Directive style*/ ElementStyle & getDirectiveStyle() ; /** \return Type style*/ ElementStyle & getTypeStyle() ; /** \return Line number style*/ ElementStyle & getLineStyle() ; /** \return Bracket style*/ ElementStyle & getSymbolStyle() ; /** \param className Name of keyword class \return keyword style of the given className */ ElementStyle & getKeywordStyle(const string &className); /** \return True if language definition was found */ bool found() const ; }; } #endif /*************************************************************************** elementstyle.cpp - description ------------------- begin : Son Nov 10 2002 copyright : (C) 2002 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 "elementstyle.h" namespace highlight { ElementStyle::ElementStyle(StyleColour col, bool b, bool i, bool u) : colour(col) , bold(b), italic(i), underline(u) {} ElementStyle:: ElementStyle(const string & elementStyleString) : bold(false), italic(false), underline(false) { set(elementStyleString); } ElementStyle::ElementStyle() : bold(false), italic(false), underline(false) {} void ElementStyle::set(const string & elementStyleString){ istringstream valueStream(elementStyleString.c_str()); string r, g, b, attr; valueStream >> r; valueStream >> g; valueStream >> b; colour.setRedValue(r); colour.setGreenValue(g); colour.setBlueValue(b); while ( valueStream >> attr) { if (attr=="italic") { italic = true; } else if (attr=="bold") { bold = true; } else if (attr=="underline") { underline = true; } } } ElementStyle::~ElementStyle() {} bool ElementStyle::isItalic() const { return italic; } bool ElementStyle::isBold() const { return bold; } bool ElementStyle::isUnderline() const { return underline; } StyleColour ElementStyle::getColour() const { return colour; } } /*************************************************************************** elementstyle.h - description ------------------- begin : Son Nov 10 2002 copyright : (C) 2002 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 ELEMENTSTYLE_H #define ELEMENTSTYLE_H #include #include "stylecolour.h" using namespace std; namespace highlight { /** \brief The class stores the basic text formatting properties. * @author Andre Simon */ class ElementStyle { public: /** Constructor \param col Style colour \param b Bold flag \param i Italic flag \param u Underline flag */ ElementStyle(StyleColour col, bool b, bool i, bool u); /** Constuctor \param elementStyleString String with fotmatting information */ ElementStyle(const string & elementStyleString); ElementStyle(); ~ElementStyle(); /** initialize object \param elementStyleString String which contains formatting attributes */ void set(const string & elementStyleString); /** \return True if italic */ bool isItalic() const; /** \return True if bold */ bool isBold() const; /** \return True if underline */ bool isUnderline() const; /** \return Element colour */ StyleColour getColour() const; private: StyleColour colour; bool bold, italic, underline; }; } #endif // // C++ Interface: enums // // Description: // // // Author: Andre Simon , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef ENUMS_H #define ENUMS_H namespace highlight { /** states which may occour during input file parsing*/ enum State { STANDARD=0, STRING, NUMBER, SL_COMMENT, ML_COMMENT_BEGIN, ESC_CHAR, DIRECTIVE_LINE, DIRECTIVE_STRING, LINENUMBER, SYMBOL, // Konstanten ab hier duefen nicht mehr als Array-Indizes benutzt werden!! KEYWORD, ML_COMMENT_END, DIRECTIVE_LINE_END, TAG_BEGIN, TAG_END, KEYWORD_BEGIN, KEYWORD_END, _UNKNOWN=100, _EOL, _EOF, _WS } ; /** Parser return values*/ enum ParseError{ PARSE_OK, BAD_INPUT=1, BAD_OUTPUT=2, BAD_STYLE=4 }; /** line wrapping modes*/ enum WrapMode { WRAP_DISABLED, WRAP_SIMPLE, WRAP_DEFAULT }; /** language definition loading results*/ enum LoadResult{ LOAD_FAILED, LOAD_NEW, LOAD_NONE }; /** output formats */ enum OutputType { HTML, XHTML, TEX, LATEX, RTF, XSLFO, XML, ANSI }; } #endif /* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 Free Software Foundation, Inc. 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, 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef __STDC__ # ifndef const # define const # endif #endif /* This tells Alpha OSF/1 not to define a getopt prototype in . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #include #include //#include "tailor.h" /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined (_LIBC) || !defined (__GNU_LIBRARY__) /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #endif /* GNU C library. */ /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a long-named option. Because this is not POSIX.2 compliant, it is being phased out. */ /* #define GETOPT_COMPAT */ /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = 0; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* XXX 1003.2 says this must be 1 before any call. */ int optind = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ #define BAD_OPTION '\0' int optopt = BAD_OPTION; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return EOF with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #define my_strlen strlen #else /* Avoid depending on library functions or files whose names are inconsistent. */ #if __STDC__ || defined(PROTO) #ifndef _WIN32 // Solaris compilation fix extern "C" { char *getenv(const char *name); int strncmp(const char *s1, const char *s2, int n); } // extern char *getenv(const char *name); // extern int strncmp(const char *s1, const char *s2, int n); #endif extern int strcmp (const char *s1, const char *s2); static int my_strlen(const char *s); static char *my_index (const char *str, int chr); #else #ifndef _WIN32 extern char *getenv (); #endif #endif static int my_strlen (const char *str) { int n = 0; while (*str++) n++; return n; } static char * my_index ( const char *str, int chr) { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } #endif /* GNU C library. */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. To perform the swap, we first reverse the order of all elements. So all options now come before all non options, but they are in the wrong order. So we put back the options and non options in original order by reversing them again. For example: original input: a b c -x -y reverse all: -y -x c b a reverse options: -x -y c b a reverse non options: -x -y a b c */ #if __STDC__ || defined(PROTO) static void exchange (char **argv); #endif static void exchange (char **argv) { char *temp, **first, **last; /* Reverse all the elements [first_nonopt, optind) */ first = &argv[first_nonopt]; last = &argv[optind-1]; while (first < last) { temp = *first; *first = *last; *last = temp; first++; last--; } /* Put back the options in order */ first = &argv[first_nonopt]; first_nonopt += (optind - last_nonopt); last = &argv[first_nonopt - 1]; while (first < last) { temp = *first; *first = *last; *last = temp; first++; last--; } /* Put back the non options in order */ first = &argv[first_nonopt]; last_nonopt = optind; last = &argv[last_nonopt-1]; while (first < last) { temp = *first; *first = *last; *last = temp; first++; last--; } } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns `EOF'. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return BAD_OPTION after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return BAD_OPTION. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal ( int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only) { int option_index; optarg = 0; /* Initialize the internal data when the first call is made. Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ if (optind == 0) { first_nonopt = last_nonopt = optind = 1; nextchar = NULL; /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } #ifndef _WIN32 else if (getenv ("POSIXLY_CORRECT") != NULL) ordering = REQUIRE_ORDER; #endif else ordering = PERMUTE; } if (nextchar == NULL || *nextchar == '\0') { if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Now skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && (argv[optind][0] != '-' || argv[optind][1] == '\0') #ifdef GETOPT_COMPAT && (longopts == NULL || argv[optind][0] != '+' || argv[optind][1] == '\0') #endif /* GETOPT_COMPAT */ ) optind++; last_nonopt = optind; } /* Special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return EOF; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if ((argv[optind][0] != '-' || argv[optind][1] == '\0') #ifdef GETOPT_COMPAT && (longopts == NULL || argv[optind][0] != '+' || argv[optind][1] == '\0') #endif /* GETOPT_COMPAT */ ) { if (ordering == REQUIRE_ORDER) return EOF; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Start decoding its characters. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } if (longopts != NULL && ((argv[optind][0] == '-' && (argv[optind][1] == '-' || long_only)) #ifdef GETOPT_COMPAT || argv[optind][0] == '+' #endif /* GETOPT_COMPAT */ )) { const struct option *p; char *s = nextchar; int exact = 0; int ambig = 0; const struct option *pfound = NULL; int indfound = 0; while (*s && *s != '=') s++; /* Test all options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, s - nextchar)) { if (s - nextchar == my_strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[optind]); nextchar += my_strlen (nextchar); optind++; return BAD_OPTION; } if (pfound != NULL) { option_index = indfound; optind++; if (*s) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = s + 1; else { if (opterr) { if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[optind - 1][0], pfound->name); } nextchar += my_strlen (nextchar); return BAD_OPTION; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, "%s: option `%s' requires an argument\n", argv[0], argv[optind - 1]); nextchar += my_strlen (nextchar); return optstring[0] == ':' ? ':' : BAD_OPTION; } } nextchar += my_strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' #ifdef GETOPT_COMPAT || argv[optind][0] == '+' #endif /* GETOPT_COMPAT */ || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar); else /* +option or -option */ fprintf (stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; return BAD_OPTION; } } /* Look at and handle the next option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { #if 0 if (c < 040 || c >= 0177) fprintf (stderr, "%s: unrecognized option, character code 0%o\n", argv[0], c); else fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); #else /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); #endif } optopt = c; return BAD_OPTION; } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = 0; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { #if 0 fprintf (stderr, "%s: option `-%c' requires an argument\n", argv[0], c); #else /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], c); #endif } optopt = c; if (optstring[0] == ':') c = ':'; else c = BAD_OPTION; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt ( int argc, char *const *argv, const char *optstring) { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } int getopt_long ( int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } #endif /* _LIBC or not __GNU_LIBRARY__. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == EOF) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case BAD_OPTION: break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ /* Declarations for getopt. Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library 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. The GNU C Library 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 the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _GETOPT_H #ifndef __need_getopt # define _GETOPT_H 1 #endif /* If __GNU_LIBRARY__ is not already defined, either we are being used standalone, or this is the first header included in the source file. If we are being used with glibc, we need to include , but that does not exist if we are standalone. So: if __GNU_LIBRARY__ is not defined, include , which will pull in for us if it's from glibc. (Why ctype.h? It's guaranteed to exist and it doesn't flood the namespace with stuff the way some other headers do.) */ #if !defined __GNU_LIBRARY__ # include #endif #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; #ifndef __need_getopt /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { # if (defined __STDC__ && __STDC__) || defined __cplusplus const char *name; # else char *name; # endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ # define no_argument 0 # define required_argument 1 # define optional_argument 2 #endif /* need getopt */ /* Get definitions and prototypes for functions to process the arguments in ARGV (ARGC of them, minus the program name) for options given in OPTS. Return the option character from OPTS just read. Return -1 when there are no more options. For unrecognized options, or options missing arguments, `optopt' is set to the option letter, and '?' is returned. The OPTS string is a list of characters which are recognized option letters, optionally followed by colons, specifying that that letter takes an argument, to be placed in `optarg'. If a letter in OPTS is followed by two colons, its argument is optional. This behavior is specific to the GNU `getopt'. The argument `--' causes premature termination of argument scanning, explicitly telling `getopt' that there are no more options. If OPTS begins with `--', then non-option arguments are treated as arguments to the option '\0'. This behavior is specific to the GNU `getopt'. */ #if (defined __STDC__ && __STDC__) || defined __cplusplus # ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); # else /* not __GNU_LIBRARY__ */ // Solaris compilation fix //extern int getopt (); # endif /* __GNU_LIBRARY__ */ # ifndef __need_getopt extern int getopt_long (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind); extern int getopt_long_only (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind, int __long_only); # endif #else /* not __STDC__ */ extern int getopt (); # ifndef __need_getopt extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); # endif #endif /* __STDC__ */ #ifdef __cplusplus } #endif /* Make sure we later can get all the definitions and declarations. */ #undef __need_getopt #endif /* getopt.h */ /*************************************************************************** help.cpp - description ------------------- begin : Die Apr 23 2002 copyright : (C) 2002 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 "help.h" namespace Help { /** gibt Hilfetext auf Konsole aus */ void printHelp(const std::string & helpFilePath) { std::ifstream helpFile(helpFilePath.c_str()); std::string line; if (helpFile){ while (getline(helpFile, line)) std::cout << line << "\n"; helpFile.close(); } else { std::cerr <<"highlight: Could not read "<< helpFilePath << "\n"; } } } /*************************************************************************** help.h - description ------------------- begin : Die Apr 23 2002 copyright : (C) 2002 by Andé 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 HELP_H #define HELP_H #include #include #include /**\ brief COntains methods for printing help messages *@author Andre Simon */ namespace Help { /** print help message to stdout */ void printHelp(const std::string &); } #endif /*************************************************************************** htmlcode.cpp - description ------------------- begin : Wed Nov 28 2001 copyright : (C) 2001 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 "htmlgenerator.h" using namespace std; namespace highlight { HtmlGenerator::HtmlGenerator(void) {} string HtmlGenerator::formatStyleAttributes(const string & elemName, const ElementStyle & elem) { ostringstream s; s << "."<"; } HtmlGenerator::HtmlGenerator ( const string &cssStyle, const string &enc, bool omitEnc, bool withAnchors) : CodeGenerator( cssStyle), brTag("
"), hrTag("
"), idAttr("name"), fileSuffix(".html"), encoding(enc), omitEncoding(omitEnc), HTML_FOOTER( "\n\n\n\n"), attachAnchors(withAnchors) { styleTagOpen.push_back(""); styleTagOpen.push_back(getOpenTag("str")); styleTagOpen.push_back(getOpenTag("num")); styleTagOpen.push_back(getOpenTag("slc")); styleTagOpen.push_back(getOpenTag("com")); styleTagOpen.push_back(getOpenTag("esc")); styleTagOpen.push_back(getOpenTag("dir")); styleTagOpen.push_back(getOpenTag("dstr")); styleTagOpen.push_back(getOpenTag("line")); styleTagOpen.push_back(getOpenTag("sym")); styleTagClose.push_back(""); for (int i=1;i"); } /*assert (styleTagOpen.size()==styleTagClose.size()); assert (styleTagOpen.size()==NUMBER_BUILTIN_STYLES); */ newLineTag = "\n"; spacer = " "; styleCommentOpen="/*"; styleCommentClose="*/"; } string HtmlGenerator::getStyleDefinition() { if (styleDefinitionCache.empty()){ ostringstream os; os << "body.hl\t{ background-color:#" << (docStyle.getBgColour().getHexRedValue()) << (docStyle.getBgColour().getHexGreenValue()) << (docStyle.getBgColour().getHexBlueValue()) << "; }\n"; os << "pre.hl\t{ color:#" << (docStyle.getDefaultStyle().getColour().getHexRedValue()) << (docStyle.getDefaultStyle().getColour().getHexGreenValue()) << (docStyle.getDefaultStyle().getColour().getHexBlueValue() ) << "; background-color:#" << (docStyle.getBgColour().getHexRedValue()) << (docStyle.getBgColour().getHexGreenValue()) << (docStyle.getBgColour().getHexBlueValue()) << "; font-size:" << docStyle.getFontSize() << "pt; font-family:Courier;}\n"; os << formatStyleAttributes("num", docStyle.getNumberStyle()) << formatStyleAttributes("esc", docStyle.getEscapeCharStyle()) << formatStyleAttributes("str", docStyle.getStringStyle()) << formatStyleAttributes("dstr", docStyle.getDirectiveStringStyle()) << formatStyleAttributes("slc", docStyle.getSingleLineCommentStyle()) << formatStyleAttributes("com", docStyle.getCommentStyle()) << formatStyleAttributes("dir", docStyle.getDirectiveStyle()) << formatStyleAttributes("sym", docStyle.getSymbolStyle()) << formatStyleAttributes("line", docStyle.getLineStyle()); KeywordStyles styles = docStyle.getKeywordStyles(); for (KSIterator it=styles.begin(); it!=styles.end(); it++){ os << formatStyleAttributes(it->first, *(it->second)); } styleDefinitionCache=os.str(); } return styleDefinitionCache; } string HtmlGenerator::getHeader(const string &title) { ostringstream os; os << getHeaderStart((title.empty())?"Source file":title ); if (langInfo.getSyntaxHighlight()) { if (includeStyleDef) //CSS-Definition in HTML- einfuegen { os << "" << endl; } else //Referenz auf CSS-Datei einfuegen { os << "\n"; } } os << "\n\n
";
  return os.str();
}

string HtmlGenerator::getFooter()
{
  return "
" + HTML_FOOTER; } void HtmlGenerator::printBody() { processRootState(); } string HtmlGenerator::maskCharacter(unsigned char c) { switch (c) { case '<' : return "<"; break; case '>' : return ">"; break; case '&' : return "&"; break; case '\"' : return """; break; case '@' : return "@"; break; default : string m; return m += c; } } void HtmlGenerator::insertLineNumber (bool insertNewLine) { if (insertNewLine){ //*out << getNewLine(); wsBuffer += getNewLine(); } if (showLineNumbers) { ostringstream numberPrefix; if (attachAnchors) { numberPrefix << ""; } ostringstream os; if (lineNumberFillZeroes) os.fill('0'); os <"; } wsBuffer += numberPrefix.str(); } } string HtmlGenerator::getHeaderStart(const string &title){ ostringstream header; header<< "" << "\n\n\n"; if (!omitEncoding){ header << "\n"; } header << "" << title <<"\n"; return header.str(); } bool HtmlGenerator::printIndexFile(const vector &fileList, const string &outPath ){ string suffix = fileSuffix; string outFilePath = outPath + "index" + suffix; ofstream indexfile(outFilePath.c_str()); if (!indexfile.fail()){ string inFileName; string inFilePath, newInFilePath; indexfile << getHeaderStart("Source Index" ); indexfile << "\n\n

Source Index

\n" << hrTag << "\n
    \n"; string::size_type pos; for (unsigned int i=0; i < fileList.size(); i++){ pos=(fileList[i]).find_last_of(Platform::pathSeparator); if (pos!=string::npos){ newInFilePath = (fileList[i]).substr(0, pos+1); } else { newInFilePath=Platform::pathSeparator; } if (newInFilePath!=inFilePath){ indexfile << "
\n

"; indexfile << newInFilePath; indexfile << "

\n
\n" << hrTag << brTag << "Generated by highlight " << HIGHLIGHT_VERSION << ", " << HIGHLIGHT_URL << ""; indexfile << HTML_FOOTER; } else { return false; } return true; } string HtmlGenerator::getMatchingOpenTag(unsigned int styleID){ return getOpenTag(langInfo.getKeywordClasses()[styleID]); } string HtmlGenerator::getMatchingCloseTag(unsigned int styleID){ return ""; } } /*************************************************************************** htmlgenerator.h - description ------------------- begin : Wed Nov 28 2001 copyright : (C) 2001 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 HTMLGENERATOR_H #define HTMLGENERATOR_H #include #include #include #include #include "codegenerator.h" #include "version.h" #include "stylecolour.h" #include "elementstyle.h" #include "platform_fs.h" namespace highlight { /** \brief This class generates HTML. 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 HtmlGenerator : public highlight::CodeGenerator { public: /** Constructor \param colourTheme Name of Colour theme to use \param enc encoding name \param omitEnc switch to omit encoding information \param withAnchors Test if HTML anchors should be attached to line numbers */ HtmlGenerator(const string &colourTheme, const string &enc, bool omitEnc=false, bool withAnchors = false); HtmlGenerator(); /** Destructor*/ virtual ~HtmlGenerator() {}; /** insert line number in the beginning of the new line */ virtual void insertLineNumber(bool insertNewLine=true); /** Print document header \param title Title of the document */ string getHeader(const string &title); /** Print document body*/ void printBody(); /** Print document footer*/ string getFooter(); /** Print style definitions to external file \param outFile Path of external style definition */ bool printExternalStyle(const string &outFile); /** Print index file with all input file names \param fileList List of output file names \param outPath Output path */ bool printIndexFile(const vector & fileList, const string &outPath); protected: /** some strings which are similar in HTML and XHTML*/ string brTag, hrTag, idAttr, fileSuffix; /** Output encoding name */ string encoding; /** switch to omit encoding name in file header */ bool omitEncoding; /** HTML footer */ string HTML_FOOTER; /** caches style definition */ string styleDefinitionCache; /** \return CSS definition */ string getStyleDefinition(); /** \return Content of user defined style file */ string readUserStyleDef(); /** \param title Dociment title \return Start of file header */ virtual string getHeaderStart(const string &title); private: /** \param styleName Style name \return Opening tag of the given style */ string getOpenTag(const string& styleName); /** \return escaped character*/ virtual string maskCharacter(unsigned char ); /** test if anchors should be appied to line numbers*/ bool attachAnchors; /**\return text formatting attributes in HTML format */ string formatStyleAttributes(const string & elemName, const ElementStyle & elem); /** \param styleID Style ID \return Opening tag of the given style */ string getMatchingOpenTag(unsigned int styleID); /** \param styleID Style ID \return Closing tag of the given style */ string getMatchingCloseTag(unsigned int styleID); }; } #endif /*************************************************************************** languagedefinition.cpp - description ------------------- begin : Wed Nov 28 2001 copyright : (C) 2001 by Andre imon 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 "languagedefinition.h" using namespace std; namespace highlight { LanguageDefinition::LanguageDefinition(): ignoreCase(false), disableHighlighting(false), allowExtEscape(false), vhdl_mode(false), java_mode(false), allowNestedComments(true), fullLineComment(false), reformatCode(false) {} int LanguageDefinition::isKeyword(const string &s) { if (s.length()) { if (keywords.count(s)){ return keywords[s]; } else if (prefixes.count(s[0])){ return prefixes[s[0]]; } } return 0; } bool LanguageDefinition::isPrefix(unsigned char c) { return ( prefixes.count(c)); } void LanguageDefinition::addSimpleSymbol(stringstream& symbolStream, State state, const string& paramValues ) { istringstream valueStream(paramValues); bool valExists=false; string value; while (valueStream >> value) { symbolStream << " " << value; valExists = true; } if (valExists) { symbolStream << " " << state; } } void LanguageDefinition::addDelimiterSymbol(stringstream& symbolStream, State stateBegin, State stateEnd, const string& paramValues, unsigned int classID) { istringstream valueStream(paramValues); string delimPrefix, delimSuffix; while (valueStream>>delimPrefix){ valueStream >> delimSuffix; symbolStream << " "<> symbol; return symbol; } void LanguageDefinition::addKeywords(const string &kwList, int classID){ istringstream valueStream(kwList); string keyword; while (valueStream >> keyword){ keywords.insert(make_pair(keyword, classID)); } } unsigned int LanguageDefinition::generateNewKWClass(const string& newClassName){ unsigned int newClassID=0; bool found=false; while (newClassID paramNames=langDef.getParameterNames(); for (unsigned int i=0;i> token ) { allowedChars += token; } symbolString = symbolStrStream.str(); string fileToInclude=langDef.getParameter("include"); if (!fileToInclude.empty()){ string::size_type Pos = langDefPath.find_last_of(Platform::pathSeparator); string includeLangDefPath = langDefPath.substr(0, Pos+1) + fileToInclude; load(includeLangDefPath, false); } return true; } else { currentPath.clear(); return false; } } void LanguageDefinition::reset() { keywords.clear(); keywordClasses.clear(); delimiterPrefixes.clear();; prefixes.clear(); allowedChars.clear(); ignoreCase= false; java_mode= vhdl_mode= false; allowNestedComments= reformatCode = false; rawStringPrefix = continuationChar = '\0'; disableHighlighting=false; fullLineComment=false; } bool LanguageDefinition::isVHDL() { return vhdl_mode; } bool LanguageDefinition::isJava() { return java_mode; } bool LanguageDefinition::allowNestedMLComments(){ return allowNestedComments; } bool LanguageDefinition::highlightingDisabled(){ return disableHighlighting; } bool LanguageDefinition::isFullLineComment(){ return fullLineComment; } bool LanguageDefinition::needsReload(const string &langDefPath){ return currentPath!=langDefPath; } bool LanguageDefinition::enableReformatting(){ return reformatCode; } const KeywordMap& LanguageDefinition::getKeywords() const{ return keywords; } string &LanguageDefinition::getSymbolString() { return symbolString; } unsigned char LanguageDefinition::getRawStringPrefix(){ return rawStringPrefix; } unsigned char LanguageDefinition::getContinuationChar(){ return continuationChar; } string &LanguageDefinition::getAllowedChars() { return allowedChars; } bool LanguageDefinition::getSyntaxHighlight() { return !disableHighlighting; } bool LanguageDefinition::isIgnoreCase() { return ignoreCase; } const vector&LanguageDefinition::getKeywordClasses() const{ return keywordClasses; } bool LanguageDefinition::allowExtEscSeq() { return allowExtEscape; } } /*************************************************************************** languagedefinition.h - description ------------------- begin : Wed Nov 28 2001 copyright : (C) 2001 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 LANGUAGEDEFINITION_H #define LANGUAGEDEFINITION_H #include #include #include #include #include #include #include "configurationreader.h" //#include "stringtools.h" #include "platform_fs.h" #include "enums.h" namespace highlight { /** maps keywords and the corresponding class IDs*/ typedef map KeywordMap; /** maps keyword prefixes and the corresponding class IDs*/ typedef map PrefixMap; /**\brief Contains specific data of the programming language being processed. The load() method will only read a new language definition if the given file path is not equal to the path of the current language definition. * @author Andre Simon */ class LanguageDefinition { public: LanguageDefinition(); /**\return Symbol string, containg all known symbols with the referencing state ids*/ string &getSymbolString(); /** \return Prefix of raw strings */ unsigned char getRawStringPrefix(); /** \return Continuation Character */ unsigned char getContinuationChar(); /** \return List of characters allowed within identifiers */ string &getAllowedChars(); /** \return true if syntax highlighting is enabled*/ bool getSyntaxHighlight(); /** \return True if language is case sensitive */ bool isIgnoreCase(); /** \param s String \return class id of keyword, 0 if s is not a keyword */ int isKeyword(const string &s); /** \return true if c is member of prefix list*/ bool isPrefix(unsigned char c); /** Load new language definition \param langDefPath Path of language definition \param clear Test if former data should be deleted \return True if successfull */ bool load(const string& langDefPath, bool clear=true); /** \return True if programming language is VHDL */ bool isVHDL(); /** \return True if programming language is Java */ bool isJava(); /** \return True if multi line comments may be nested */ bool allowNestedMLComments(); /** \return True if highlighting is disabled */ bool highlightingDisabled(); /** \return True if single line comments must start at coloumn 1 */ bool isFullLineComment(); /** \return True the next load() call will load a new language definition \param langDefPath Path to language definition */ bool needsReload(const string &langDefPath); /** \return True if current language may be reformatted (c, c++, c#, java) */ bool enableReformatting(); /** \return True if escape sequences are allowed outsde of strings */ bool allowExtEscSeq(); /** \return Class ID of given keyword delimiter prefix \param prefix Keyword delimiter prefix */ unsigned int getDelimPrefixClassID(const string& prefix); /** \return keywords*/ const KeywordMap& getKeywords() const; /** \return keyword classes*/ const vector& getKeywordClasses() const; private: // string containing symbols and their IDs of the programming language string symbolString; // string with special characters that may occour in keywords string allowedChars; // path to laoed language definition string currentPath; KeywordMap keywords; vector keywordClasses; KeywordMap delimiterPrefixes; PrefixMap prefixes; // keywords are not case sensitive if set bool ignoreCase, disableHighlighting, allowExtEscape, // switch to enable VHDL workarounds vhdl_mode, // switch to enable Java workarounds java_mode, // allow nested multi line comment blocks allowNestedComments, // single line comments have to start in coloumn 1 if set fullLineComment, // code formatting is enabled if set reformatCode; // Character, die eine Variable bzw. ein Keyword kennzeichnen unsigned char rawStringPrefix, continuationChar; /** setzt Membervariablen auf Defaultwerte */ void reset(); // add a symbol sequencs to the symbolStream void addSimpleSymbol(stringstream& symbolStream, State state, const string& paramValues ); // add a delimiter symbol sequencs to the symbolStream void addDelimiterSymbol(stringstream& symbolStream, State stateBegin, State stateEnd, const string& paramValues, unsigned int classID=0); bool getFlag( string& paramValue); unsigned char getSymbol(const string& paramValue); // generate a unique class ID if the class name unsigned int generateNewKWClass(const string& newClassName); // add keywords to the given class void addKeywords(const string &kwList, int classID); }; } #endif /*************************************************************************** LatexCode.cpp - description ------------------- begin : Mit Jul 24 2002 copyright : (C) 2002 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 "latexgenerator.h" namespace highlight { LatexGenerator::LatexGenerator(const string &colourTheme, bool replQuotes) : CodeGenerator(colourTheme), replaceQuotes(replQuotes) { styleTagOpen.push_back( "\\hlstd{"); styleTagOpen.push_back( "\\hlstr{"); styleTagOpen.push_back( "\\hlnum{"); styleTagOpen.push_back( "\\hlslc{"); styleTagOpen.push_back( "\\hlcom{"); styleTagOpen.push_back( "\\hlesc{"); styleTagOpen.push_back( "\\hldir{"); styleTagOpen.push_back( "\\hldstr{"); styleTagOpen.push_back( "\\hlline{"); styleTagOpen.push_back( "\\hlsym{"); for (int i=0;i' : return "$>$"; break; case '{': case '}': case '&': case '$': case '#': case '%': { string m; m ="\\"; m += c; return m; } break; case '\"': return (fragmentOutput && replaceQuotes)?"\\dq{}":"\""; break; case '_': return "\\textunderscore "; break; case '^': return "\\textasciicircum "; break; case '\\': return "$\\backslash$"; break; case '~': return "$\\sim$"; break; case '|': return "\\textbar "; break; // avoid latex compilation failure if [ or * follows a line break (\\) case '*': case '[': case ']': // avoid "merging" of consecutive '-' chars when included in bold font ( \bf ) case '-': { string m; m= "{"; m+= c; m+= "}"; return m; } break; case ' ': return spacer; break; case AUML_LC: return "\\\"a"; break; case OUML_LC: return "\\\"o"; break; case UUML_LC: return "\\\"u"; break; case AUML_UC: return "\\\"A"; break; case OUML_UC: return "\\\"O"; break; case UUML_UC: return "\\\"U"; break; case AACUTE_LC: return "\\'a"; break; case EACUTE_LC: return "\\'e"; break; case OACUTE_LC: return "\\'o"; break; case UACUTE_LC: return "\\'u"; break; case AGRAVE_LC: return "\\`a"; break; case EGRAVE_LC: return "\\`e"; break; case OGRAVE_LC: return "\\`o"; break; case UGRAVE_LC: return "\\`u"; break; case AACUTE_UC: return "\\'A"; break; case EACUTE_UC: return "\\'E"; break; case OACUTE_UC: return "\\'O"; break; case UACUTE_UC: return "\\'U"; break; case AGRAVE_UC: return "\\`A"; break; case EGRAVE_UC: return "\\`E"; break; case UGRAVE_UC: return "\\`O"; break; case OGRAVE_UC: return "\\`U"; break; case SZLIG: return "\\ss "; break; /* #ifndef _WIN32 // skip first byte of multibyte chracters case 195: return string(""); break; #endif*/ default : { string m; return m+=c; } } } string LatexGenerator::getMatchingOpenTag(unsigned int styleID){ return "\\hl"+langInfo.getKeywordClasses()[styleID]+"{"; } string LatexGenerator::getMatchingCloseTag(unsigned int styleID){ return "}"; } string LatexGenerator::getStyleDefinition() { if (styleDefinitionCache.empty()){ ostringstream os; os << formatStyleAttributes("std", docStyle.getDefaultStyle()); os << formatStyleAttributes("num", docStyle.getNumberStyle()); os << formatStyleAttributes("esc", docStyle.getEscapeCharStyle()); os << formatStyleAttributes("str", docStyle.getStringStyle()); os << formatStyleAttributes("dstr", docStyle.getDirectiveStringStyle()); os << formatStyleAttributes("slc", docStyle.getSingleLineCommentStyle()); os << formatStyleAttributes("com", docStyle.getCommentStyle()); os << formatStyleAttributes("dir", docStyle.getDirectiveStyle()); os << formatStyleAttributes("sym", docStyle.getSymbolStyle()); os << formatStyleAttributes("line", docStyle.getLineStyle()); KeywordStyles styles = docStyle.getKeywordStyles(); for (KSIterator it=styles.begin(); it!=styles.end(); it++){ os << formatStyleAttributes(it->first, *(it->second)); } os << "\\definecolor{bgcolor}{rgb}{" << docStyle.getBgColour().getLatexRedValue() << "," << docStyle.getBgColour().getLatexGreenValue() << "," << docStyle.getBgColour().getLatexBlueValue() << "}\n"; os << "\\oddsidemargin -3mm\n\\textwidth 165,2truemm\n" << "\\topmargin 0truept\n\\headheight 0truept\n" << "\\headsep 0truept\n\\textheight 230truemm\n"; styleDefinitionCache=os.str(); } return styleDefinitionCache; } } /*************************************************************************** latexgenerator.h - description ------------------- begin : Mit Jul 24 2002 copyright : (C) 2002 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. * * * ***************************************************************************/ #ifndef LATEXGENERATOR_H #define LATEXGENERATOR_H #include #include #include #include "codegenerator.h" #include "version.h" #include "charcodes.h" namespace highlight { /** \brief This class generates LaTeX. 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 LatexGenerator : public highlight::CodeGenerator { public: /** Constructor \param colourTheme Name of Colour theme to use \param replQuotes Test if quotes shold be replaced by \ dq */ LatexGenerator(const string &colourTheme, bool replQuotes=false); LatexGenerator(); ~LatexGenerator(); /** 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: string styleDefinitionCache; string longLineTag; /** \return escaped character*/ virtual string maskCharacter(unsigned char ); /**\return text formatting attributes in LaTeX format */ string formatStyleAttributes(const string & elemName, const ElementStyle & elem); /** test if double quotes should be replaced by \dq{} */ bool replaceQuotes; string getNewLine(); string getStyleDefinition(); string getMatchingOpenTag(unsigned int styleID); string getMatchingCloseTag(unsigned int styleID); }; } #endif /*************************************************************************** main.cpp - description ------------------- begin : Die Apr 23 22:16:35 CEST 2002 copyright : (C) 2002-2004 by André Simon email : andre.simon1@gmx.de Highlight is a universal source code to HTML converter. Syntax highlighting is formatted by Cascading Style Sheets. It's possible to easily enhance highlight's parsing database. ***************************************************************************/ /*************************************************************************** * * * 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 "main.h" using namespace std; void HighlightApp::printVersionInfo() { cout << "\n highlight version " << HIGHLIGHT_VERSION << "\n Copyright (C) 2002-2005 Andre Simon " << "\n\n Artistic Style Classes (1.15.3)" << "\n Copyright (C) 1998-2002 Tal Davidson " << "\n\n Dirstream Classes (0.4)" << "\n Copyright (C) 2002-2004 Benjamin Kaufmann " << "\n\n This software is released under the terms of the GNU General " << "Public License." << "\n For more information about these matters, see the file named " << "COPYING.\n\n"; #ifdef USE_LOCAL_GETOPT cout << " (Built with USE_LOCAL_GETOPT flag set.)\n"; #endif #ifdef HL_DATA_DIR cout << " (HL_DATA_DIR: \"" < filePaths; string wildcard=(showThemes)? "*.style":"*.lang"; unsigned int suffixLength=wildcard.length()-1; string searchDir = ((showThemes) ? dataDir.getThemeDir(): dataDir.getLangDefDir()) + wildcard; bool directoryOK = Platform::getDirectoryEntries(filePaths, searchDir, true); if (!directoryOK) { cerr << "highlight: Could not access directory " << searchDir << ", aborted.\n"; return false; } cout << "\n Installed " << ((showThemes)? "themes":"language definitions ") << "(located in " << ((showThemes)?dataDir.getThemeDir():dataDir.getLangDefDir()) << ") :\n" << endl; sort(filePaths.begin(), filePaths.end()); string temp; for (unsigned int i=0;i< filePaths.size(); i++){ if (showThemes) temp = (filePaths[i]).substr(dataDir.getThemeDir().length()); else temp = (filePaths[i]).substr(dataDir.getLangDefDir().length()); cout << " "<second << " <- \"" << it->first <<"\"\n"; } cerr <<"\n"; } string HighlightApp::getFileSuffix(const string &fileName) { size_t ptPos=fileName.rfind("."); return (ptPos == string::npos) ? "" : fileName.substr(ptPos+1, fileName.length()); } bool HighlightApp::loadMapConfig(const string& name, StringMap* map){ string extPath=dataDir.getDir() + name + ".conf"; ConfigurationReader config(extPath); if (config.found() ) { stringstream values; string paramName, paramVal; for (unsigned int i=0;i> paramVal) { map->insert(make_pair( paramVal, paramName)); } values.clear(); } return true; } else { cerr << "highlight: Configuration file "<< extPath << " not found.\n"; return false; } } int HighlightApp::getNumDigits(int i){ int res=0; while (i){ i/=10; ++res; } return res; } void HighlightApp::printProgressBar(int total, int count){ if (!total) return; int p=100*count / total; int numProgressItems=p/10; cout << "\r["; for (int i=0;i<10;i++){ cout <<((i & fileList, const string &action){ cerr << "highlight: Could not " << action << " file" << ((numberErrorFiles>1)?"s":"")<<":\n"; copy (fileList.begin(), fileList.end(), ostream_iterator(cerr, "\n")); if (fileList.size() < numberErrorFiles) { cerr << "... [" << (numberErrorFiles - fileList.size() ) << " of " << numberErrorFiles << " failures not shown, use --" << OPT_VERBOSE << " switch to print all paths]\n"; } } string HighlightApp::analyzeShebang(const string& file){ if (scriptShebangs.empty()) loadMapConfig("scriptre", &scriptShebangs); ifstream inFile(file.c_str()); string firstLine; getline (inFile, firstLine); return scriptShebangs[StringTools::trimRight(firstLine)]; } string HighlightApp::guessFileType(const string& suffix, const string &inputFile) { if (extensions.empty()) loadMapConfig("extensions", &extensions); string fileType = (extensions.count(suffix)) ? extensions[suffix] : suffix ; if (!fileType.empty()) return fileType; return analyzeShebang(inputFile); } int HighlightApp::run(int argc, char**argv){ //get command line options CmdLineOptions options(argc, argv); // set data directory path, where /langDefs and /themes reside string highlightRootDir = Platform::getAppPath(); // determine highlight data directory if (! dataDir.searchDataDir((options.dataDirGiven())? options.getDataDir(): highlightRootDir)){ printBadInstallationInfo(); return EXIT_FAILURE; } if (options.additionalDataDirGiven()){ dataDir.setAdditionalDataDir(options.getAdditionalDataDir()); } if (options.printVersion()) { printVersionInfo(); return EXIT_SUCCESS; } if (options.printHelp()) { Help::printHelp(dataDir.getHelpMsgDir() + options.getHelpLang()); return EXIT_SUCCESS; } if (options.showThemes() || options.showLangdefs()) { return listInstalledFiles(options.showThemes())?EXIT_SUCCESS:EXIT_FAILURE; } // list of input files const vector inFileList=options.getInputFileNames(); string stylePath=dataDir.searchForTheme(options.getStyleName()); highlight::CodeGenerator *generator = highlight::CodeGenerator::getInstance(options.getOutputType(), stylePath, options.getStyleInFilename(), options.getStyleOutFilename(), options.getCharSet(), options.includeStyleDef(), options.attachLineAnchors(), options.replaceQuotes(), options.fopCompatible(), options.getNumberSpaces(), options.getWrappingStyle(), options.printLineNumbers(), options.fillLineNrZeroes(), options.fragmentOutput(), options.omitEncodingName() ); assert (generator!=NULL); bool styleFileWanted = !options.fragmentOutput() || options.styleOutPathDefined(); if (!generator->styleFound() ) { cerr << "highlight: Could not find style " << stylePath << ".\n"; highlight::CodeGenerator::deleteInstance(); return EXIT_FAILURE; } if (!options.getIndentScheme().empty()){ string indentSchemePath = dataDir.searchForIndentScheme(options.getIndentScheme()+".indent"); if (!generator->initIndentationScheme(indentSchemePath)){ cerr << "highlight: Could not find indentation scheme " << indentSchemePath << ".\n"; highlight::CodeGenerator::deleteInstance(); return EXIT_FAILURE; } } string outDirectory = options.getOutDirectory(); if (!outDirectory.empty() && !options.quietMode() && !dirstr::directory_exists(outDirectory) ){ cerr << "highlight: Output directory \"" << outDirectory << "\" does not exist.\n"; return EXIT_FAILURE; } bool initError=false, IOError=false; if ( !options.includeStyleDef() && (styleFileWanted) && options.formatSupportsExtStyle()) { string cssOutFile=outDirectory + options.getStyleOutFilename(); bool success=generator->printExternalStyle (cssOutFile); if (!success){ cerr << "highlight: Could not write " << cssOutFile <<".\n"; IOError = true; } } if (options.printIndexFile()){ bool success=generator -> printIndexFile(inFileList, outDirectory); if (!success){ cerr << "highlight: Could not write index file.\n"; IOError = true; } } unsigned int fileCount=inFileList.size(), fileCountWidth=getNumDigits(fileCount), i=0, numBadFormatting=0, numBadInput=0, numBadOutput=0; vector badFormattedFiles, badInputFiles, badOutputFiles; string outFilePath; string suffix, lastSuffix; if (options.syntaxGiven()) { // user defined language definition, valid for all files suffix = guessFileType(options.getLanguage()); } while (i < fileCount && !initError) { if (!options.syntaxGiven()) { // determine file type for each file suffix = guessFileType(getFileSuffix(inFileList[i]), inFileList[i]); } if (suffix.empty()) { if (!options.enableBatchMode() && !styleFileWanted) cerr << "highlight: Undefined language definition. Use --" << OPT_SYNTAX << " option.\n"; if (!options.forceOutput()){ initError = true; break; } } if (suffix != lastSuffix) { string langDefPath=dataDir.searchForLangDef(suffix+".lang"); highlight::LoadResult loadRes= generator->initLanguage(langDefPath); if (loadRes==highlight::LOAD_FAILED){ cerr << "highlight: Unknown source file extension \"" << suffix << "\".\n"; if (!options.forceOutput()){ initError = true; break; } } if (options.printDebugInfo() && loadRes==highlight::LOAD_NEW){ printDebugInfo(generator->getLanguage(), langDefPath); } lastSuffix = suffix; } if (options.enableBatchMode()){ string::size_type pos=(inFileList[i]).find_last_of(Platform::pathSeparator); outFilePath = outDirectory; outFilePath += inFileList[i].substr(pos+1); outFilePath += options.getOutFileSuffix(); if (!options.quietMode()) { if (options.printProgress()){ printProgressBar(fileCount, i+1); } else { printCurrentAction(outFilePath, fileCount, i+1, fileCountWidth); } } } else { outFilePath = options.getSingleOutFilename(); } highlight::ParseError error = generator->printOutput(inFileList[i], outFilePath); if (error==highlight::BAD_INPUT){ if (numBadInput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo()) { badInputFiles.push_back(inFileList[i]); } } else if (error==highlight::BAD_OUTPUT){ if (numBadOutput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo()) { badOutputFiles.push_back(outFilePath); } } if (options.formattingEnabled() && !generator->formattingIsPossible()){ if (numBadFormatting++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo()) { badFormattedFiles.push_back(outFilePath); } } ++i; } if (numBadInput){ printIOErrorReport(numBadInput, badInputFiles, "read input"); IOError = true; } if (numBadOutput){ printIOErrorReport(numBadOutput, badOutputFiles, "write output"); IOError = true; } if (numBadFormatting){ printIOErrorReport(numBadFormatting, badFormattedFiles, "reformat"); } highlight::CodeGenerator::deleteInstance(); return (initError || IOError) ? EXIT_FAILURE : EXIT_SUCCESS; } int main(int argc, char **argv) { HighlightApp app; return app.run(argc, argv); } // // C++ Interface: main // // Description: // // // Author: Andre Simon , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef HIGHLIGHT_APP #define HIGHLIGHT_APP #include #include #include #include #include #include #include #include "./dirstream0.4/dirstream.h" #include "cmdlineoptions.h" #include "configurationreader.h" #include "codegenerator.h" #include "help.h" #include "datadir.h" #include "version.h" #include "platform_fs.h" #define IO_ERROR_REPORT_LENGTH 5 #define SHEBANG_CNT 12 typedef map StringMap; /** Main application class @author Andre Simon */ class HighlightApp { public: HighlightApp(){}; ~HighlightApp(){}; /** Start application \param argc Number of command line arguments \param argv values of command line arguments \return EXIT_SUCCESS or EXIT_FAILURE */ int run(int argc, char **argv); private: DataDir dataDir; StringMap extensions; StringMap scriptShebangs; /** print version info*/ void printVersionInfo(); /** print error message*/ void printBadInstallationInfo(); /** print input and output errors */ void printIOErrorReport(unsigned int numberErrorFiles, vector & fileList, const string &action); /** print installed files \param showThemes Print installed themes if true, language definitions otherwise */ bool listInstalledFiles(bool showThemes); void printDebugInfo(highlight::LanguageDefinition &lang, const string &langDefPath); string getFileSuffix(const string &fileName); string guessFileType(const string &suffix, const string &inputFile=""); int getNumDigits(int i); void printProgressBar(int total, int count); void printCurrentAction(const string&outfilePath, int total, int count, int countWidth); bool readInputFilePaths(vector &fileList, string wildcard, bool recursiveSearch); string analyzeShebang(const string& file); bool loadMapConfig(const string& name, StringMap* map); }; #endif // // C++ Implementation: platform_fs // // Description: // // // Author: André Simon , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "platform_fs.h" #include "./dirstream0.4/dirstream.h" #include using namespace std; namespace Platform { #ifdef _WIN32 #include const char pathSeparator = '\\'; //const std::string pathSeparatorStr = "\\"; std::string getAppPath() { char pathAndName[MAX_PATH], path[MAX_PATH], drive[3]; GetModuleFileName(NULL, pathAndName, MAX_PATH); _splitpath(pathAndName, drive, path, 0, 0); return std::string(drive)+path; } #else const char pathSeparator = '/'; // const std::string pathSeparatorStr = "/"; std::string getAppPath() { return ""; } #endif bool getDirectoryEntries(vector &fileList, string wildcard, bool recursiveSearch) { if (!wildcard.empty()) { string directory_path; string::size_type Pos = wildcard.find_last_of(pathSeparator); if (Pos == string::npos) { directory_path = "."; } else { directory_path = wildcard.substr(0, Pos + 1); wildcard = wildcard.substr(Pos + 1); } dirstr::dirstream str( directory_path.c_str(), #ifdef USE_FN_MATCH dirstr::pred_f(FnMatcher(wildcard.c_str(), 0)), #else dirstr::pattern_f(wildcard.c_str()), #endif (recursiveSearch)?dirstr::recursive_yes:dirstr::recursive_no); for(string entry; str >> entry;) { fileList.push_back(dirstr::full_path(entry)); //std::cout << "Entry " <, (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef PLATFORM_FS__H__INCLUDED #define PLATFORM_FS__H__INCLUDED #include #include #include #ifdef USE_FN_MATCH #include #endif namespace Platform { extern const char pathSeparator; //extern const std::string pathSeparatorStr; std::string getAppPath(); /** \param fileList Vector where found entries will be stored \param wildcard Directory path and wildcard \param recursiveSearch Test if directory should be searched recursively */ bool getDirectoryEntries(std::vector &fileList, std::string wildcard, bool recursiveSearch=false); #ifdef USE_FN_MATCH struct FnMatcher { FnMatcher(const char* pattern, int flags) : pattern_(pattern) , flags_(flags) {} bool operator()(const std::string& e) const { // std::cout << "pattern: "< maxLineLength){ // erster Durchlauf... // wenn möglich an öffnender Klammer oder Geichheitszeichen ausrichten if (indentAfterOpenBraces){ wsPrefixLength=line.find_first_of(INDENT_MARKERS); } // sonst die Einrückung der Originalzeile beibehalten if (wsPrefixLength==string::npos || wsPrefixLength-index>maxLineLength){ wsPrefixLength=line.find_first_not_of(WS_CHARS); } else { // wsPrefix in allen neu umgebrochenen Zeilen durch Spaces ersetzen redefineWsPrefix=true; // Position hinter öffnende Klammer springen wsPrefixLength=line.find_first_not_of(WS_CHARS,wsPrefixLength+1); } if (wsPrefixLength!=string::npos){ index = wsPrefixLength; // Falls Anzahl der Whitespaces am beginn der ersten zeile größer // als Max. Zeilenlänge, Whitespaces verwerfen if (wsPrefixLength>maxLineLength){ wsPrefixLength=0; return string(); } else{ wsPrefix=line.substr(0, wsPrefixLength); } } // Zeile enthaelt nur Whitespace; verwerfen else { hasMore= false; return string(); } } else { if (redefineWsPrefix){ wsPrefix.clear(); wsPrefix.append(wsPrefixLength, ' '); } redefineWsPrefix=false; } string resultString; // Position, ab der rckwaerts nach Umbruchmglichkeit gesucht wird unsigned int searchEndPos = maxLineLength - wsPrefixLength; // letztes Teilstueck der Zeile ausgeben; Parsen beenden if (line.length()-index < searchEndPos) { hasMore=false; resultString=(index>0) ? wsPrefix + line.substr(index) : line.substr(index); return resultString; } // Umbrechposition suchen size_t lbPos = line.find_last_of(LB_CHARS, index+searchEndPos); if (lbPos <= index || lbPos == string::npos) { // nichts gefunden, hart umbrechen lbPos = index + searchEndPos; } // Einrückung der Originalzeile erhalten resultString+=wsPrefix; // Neue Zeile erzeugen resultString += line.substr(index, lbPos-index+1); // Whitespace am neuen Zeilenbeginn ignorieren, ausser beim ersten Durchlauf //unsigned int newIndex=StringTools::getNextNonWsPos(line,lbPos+1); size_t newIndex=line.find_first_not_of(WS_CHARS, lbPos+1); index=(newIndex!=string::npos)?newIndex:line.length(); hasMore=index!=line.length(); // unnoetigen Leerstring vermeiden return resultString; } void PreFormatter::setWrappingProperties(unsigned int maxLineLength, bool indentAfterOpenBraces){ this->maxLineLength = maxLineLength; this->indentAfterOpenBraces = indentAfterOpenBraces; } void PreFormatter::setNumberSpaces(unsigned int num){ numberSpaces = num; } } /*************************************************************************** PreFormatter.cpp - description ------------------- begin : Mo Jan 03 2005 copyright : (C) 2005 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. * * * ***************************************************************************/ #ifndef PreFormatter_H #define PreFormatter_H #define LB_CHARS " \t[](){}-+<>.:,;" #define WS_CHARS " \n\r\t" #define INDENT_MARKERS "{(=" #include #include #include "stringtools.h" namespace highlight { /** \brief Class which provides intelligent line wrapping. * @author Andre Simon */ class PreFormatter{ public: /** Constructor */ PreFormatter(bool wrap, bool replTabs); PreFormatter(); ~PreFormatter(); /** \return True if current line can be wrapped again */ bool hasMoreLines(); /** Sets new line to be wrapped \param newline New line */ void setLine(const std::string newline); /** The method will indent function calls and statements \return Next line */ std::string getNextLine(); /** \return True if lines following open braces should be indented */ bool indentCode(); /** \param maxlength max. length of output lines \param indentAfterOpenBraces set true if lines should be indented after braces */ void setWrappingProperties(unsigned int maxlength=80, bool indentAfterOpenBraces=true); /** \param num number of spaces which replace a tab */ void setNumberSpaces(unsigned int num); /** \return true if preformatting is enabled */ bool isEnabled(){ return wrapLines || replaceTabs; } private: unsigned int maxLineLength; std::string line, wsPrefix; unsigned int index; unsigned int numberSpaces; size_t wsPrefixLength; bool hasMore, indentAfterOpenBraces; bool redefineWsPrefix; bool wrapLines, replaceTabs; }; } #endif /*************************************************************************** rtfcode.cpp - description ------------------- begin : Die Jul 9 2002 copyright : (C) 2002 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 "rtfgenerator.h" using namespace std; namespace highlight { string RtfGenerator::formatStyleAttributes( const ElementStyle & col) { stringstream s; s << "\\red"<< col.getColour().getRTFRedValue() << "\\green"< keywordClasses = langInfo.getKeywordClasses(); for (unsigned int i=0;i #include #include #include #include "codegenerator.h" #include "charcodes.h" #include "version.h" namespace highlight { /** \brief This class generates RTF. 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 RtfGenerator : public highlight::CodeGenerator { public: /** Constructor \param colourTheme Name of Colour theme to use */ RtfGenerator( const string &colourTheme); RtfGenerator(); ~RtfGenerator(); /** 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 ); /**\return text formatting attributes in RTF format */ string formatStyleAttributes( const ElementStyle & col); /** gibt RTF-"Tags" zurueck (Farbindex+bold+kursiv)*/ string getOpenTag(int styleNumber,const ElementStyle &); string getCloseTag(const ElementStyle &); string getMatchingOpenTag(unsigned int styleID); string getMatchingCloseTag(unsigned int styleID); }; } #endif /*************************************************************************** stringtools.cpp - description ------------------- begin : Mon Dec 10 2001 copyright : (C) 2001 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 "stringtools.h" #include #include #include using namespace std; namespace StringTools { // Make a lowercase copy of s: // (C) Bruce Eckel, Thinking in C++ Vol 2 string lowerCase(const string& s) { char* buf = new char[s.length()]; s.copy(buf, s.length()); for(unsigned int i = 0; i < s.length(); i++) buf[i] = tolower(buf[i]); string r(buf, s.length()); delete buf; return r; } int str2int(string s) { istringstream os(s); int intVal; os >> intVal; return intVal; } bool isAlpha(unsigned char c) { return (isalpha(c) || c == '_'); } string trimRight(const string &value) { string::size_type where = value.find_last_not_of(" \t\r"); if (where == string::npos) // string has nothing but space return string(); if (where == (value.length() - 1)) // string has no trailing space, don't copy its contents return value; return value.substr(0, where + 1); } unsigned char getNextNonWs(const string &line, int index) { unsigned char c; do { c=line[index++]; } while (isspace(c)); return c; } string getParantheseVal(const string &s){ string::size_type openPos=s.find('('); string::size_type closePos=s.rfind(')'); if (openPos ==string::npos || closePos==string::npos){ return string(); } return s.substr(openPos+1, closePos-openPos-1); } } /*************************************************************************** stringtools.h - description ------------------- begin : Mon Dec 10 2001 copyright : (C) 2001 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. * * * ***************************************************************************/ #ifndef STRINGTOOLS_H #define STRINGTOOLS_H #include using namespace std; /**\brief Contains methods for string manipulation *@author Andre Simon */ namespace StringTools { /** \param s String \returns lowercase string */ string lowerCase(const string &s); /** \param s String \returns Integer value */ int str2int(string s); /** \return true if c is alpa or underscore */ bool isAlpha(unsigned char c); /** \param value String \return string trimmed on the left side */ string trimRight(const string &value); /** \return next character in line starting from index, which is no whitespace*/ unsigned char getNextNonWs(const string &line, int index=0); /** \param s String, containing a opening and a closing paranthesis \return value between "(", ")" */ string getParantheseVal(const string &s); } #endif /*************************************************************************** stylecolour.cpp - description ------------------- begin : Die Nov 5 2002 copyright : (C) 2002 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 "stylecolour.h" using std::string; namespace highlight { StyleColour::StyleColour(const string & r_hex, const string & g_hex, const string & b_hex) : r(r_hex), g(g_hex), b(b_hex) {} StyleColour::StyleColour() : r("00"), g("00"), b("00") {} //Parst PArameter aus style-Datei StyleColour::StyleColour(const string & styleColourString) { setRGBValues(styleColourString); } void StyleColour::setRGBValues(const string & styleColourString){ //Stringstream zum Einlesen der Tokens: istringstream valueStream(styleColourString.c_str()); valueStream >> r; valueStream >> g; valueStream >> b; } void StyleColour::setRedValue(const string & r_hex) { r = r_hex; } void StyleColour::setGreenValue(const string & g_hex) { g = g_hex; } void StyleColour::setBlueValue(const string & b_hex) { b = b_hex; } string& StyleColour::getHexRedValue() { return r; } string& StyleColour::getHexGreenValue() { return g; } string& StyleColour::getHexBlueValue() { return b; } string StyleColour::getRTFRedValue() { return int2str(hex2dec(r)); } string StyleColour::getRTFGreenValue() { return int2str(hex2dec(g)); } string StyleColour::getRTFBlueValue() { return int2str(hex2dec(b)); } string StyleColour::getLatexRedValue() { return float2str((float)hex2dec(r)/255); } string StyleColour::getLatexGreenValue() { return float2str((float)hex2dec(g)/255); } string StyleColour::getLatexBlueValue() { return float2str((float)hex2dec(b)/255); } // Konvertieren von RGB nach CYM string StyleColour::getTexRedValue() { return float2str(1-(float)hex2dec(r)/255); } string StyleColour::getTexGreenValue() { return float2str(1-(float)hex2dec(g)/255); } string StyleColour::getTexBlueValue() { return float2str(1-(float)hex2dec(b)/255); } string StyleColour::int2str(const int num) { std::ostringstream outStream; outStream << num; return outStream.str(); } string StyleColour::float2str(const double num) { std::ostringstream outStream; outStream << ( floor ( num * 100 + .5 ) / 100); return outStream.str(); } int StyleColour::hex2dec(const string &hexVal) { if (hexVal.length() != 2) return 0; unsigned int decVal=0, koeff=16; for (int i=0; i<2;i++ ) { if ((hexVal[i] >= '0')&& (hexVal[i]<= '9' )) { decVal += (koeff * (hexVal[i]-'0')); } if ((hexVal[i] >= 'a')&& (hexVal[i]<= 'f' )) { decVal +=( koeff * (hexVal[i]-87)); } if ((hexVal[i] >= 'A')&& (hexVal[i]<= 'F' )) { decVal += (koeff * (hexVal[i]-55)); } koeff=1; } return decVal; } } /*************************************************************************** stylecolour.h - description ------------------- begin : Die Nov 5 2002 copyright : (C) 2002 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 STYLECOLOUR_H #define STYLECOLOUR_H #include #include #include #include #include using namespace std; namespace highlight { /**\brief Stores colours and returns red, green and blue values in different formats * @author Andre Simon */ class StyleColour { public: /** Constructor \param r_hex Red value in hex notation \param g_hex Blue value in hex notation \param b_hex Green value in hex notation */ StyleColour(const string & r_hex, const string & g_hex, const string & b_hex); /** Constructor \param styleColourString String with rgb values */ StyleColour(const string & styleColourString); StyleColour(); ~StyleColour(){}; /** Sets red, green and blue values \param styleColourString String containing colour attributes */ void setRGBValues(const string & styleColourString); /** Sets red value \param r_hex New red value */ void setRedValue(const string & r_hex); /** Sets green value \param g_hex New green value */ void setGreenValue(const string & g_hex); /** Sets blue value \param b_hex New blue value */ void setBlueValue(const string & b_hex); /** \return Red value in hex format */ string& getHexRedValue(); /** \return Green value in hex format */ string& getHexGreenValue(); /** \return Blue value in hex format */ string& getHexBlueValue(); /** \return Red value in latex format */ string getLatexRedValue(); /** \return Green value in latex format */ string getLatexGreenValue(); /** \return Blue value in latex format */ string getLatexBlueValue(); /** \return Red value in tex format */ string getTexRedValue(); /** \return Green value in tex format */ string getTexGreenValue(); /** \return Blue value in tex format */ string getTexBlueValue(); /** \return Red value in RTF format */ string getRTFRedValue(); /** \return Green value in RTF format */ string getRTFGreenValue(); /** \return Blue value in RTF format */ string getRTFBlueValue(); private: string r, g, b; string int2str(int); string float2str(double); int hex2dec(const string &hexVal); }; } #endif /*************************************************************************** TexGenerator.cpp - description ------------------- begin : Mit Jul 24 2002 copyright : (C) 2002 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 "texgenerator.h" namespace highlight { TexGenerator::TexGenerator(const string &colourTheme): CodeGenerator( colourTheme) { styleTagOpen.push_back( "{\\hlstd "); styleTagOpen.push_back( "{\\hlstr "); styleTagOpen.push_back( "{\\hlnum "); styleTagOpen.push_back( "{\\hlslc "); styleTagOpen.push_back( "{\\hlcom "); styleTagOpen.push_back( "{\\hlesc "); styleTagOpen.push_back( "{\\hldir "); styleTagOpen.push_back( "{\\hldstr "); styleTagOpen.push_back( "{\\hlline "); styleTagOpen.push_back( "{\\hlsym "); for (int i=0;i': case '=': { string m; m = "$\\mathord{"; m += c; m += "}$"; return m; } break; case AUML_LC: return "\\\"a"; break; case OUML_LC: return "\\\"o"; break; case UUML_LC: return "\\\"u"; break; case AUML_UC: return "\\\"A"; break; case OUML_UC: return "\\\"O"; break; case UUML_UC: return "\\\"U"; break; case AACUTE_LC: return "\\'a"; break; case EACUTE_LC: return "\\'e"; break; case OACUTE_LC: return "\\'o"; break; case UACUTE_LC: return "\\'u"; break; case AGRAVE_LC: return "\\`a"; break; case EGRAVE_LC: return "\\`e"; break; case OGRAVE_LC: return "\\`o"; break; case UGRAVE_LC: return "\\`u"; break; case AACUTE_UC: return "\\'A"; break; case EACUTE_UC: return "\\'E"; break; case OACUTE_UC: return "\\'O"; break; case UACUTE_UC: return "\\'U"; break; case AGRAVE_UC: return "\\`A"; break; case EGRAVE_UC: return "\\`E"; break; case UGRAVE_UC: return "\\`O"; break; case OGRAVE_UC: return "\\`U"; break; case SZLIG: return "\\ss "; break; /* #ifndef _WIN32 // skip first byte of multibyte chracters case 195: return string(""); break; #endif*/ default : string m; return m += c; } } string TexGenerator::getMatchingOpenTag(unsigned int styleID){ return "{\\hl"+langInfo.getKeywordClasses()[styleID]+" "; } string TexGenerator::getMatchingCloseTag(unsigned int styleID){ return "}"; } string TexGenerator::getStyleDefinition() { if (styleDefinitionCache.empty()){ ostringstream os; os << formatStyleAttributes("std", docStyle.getDefaultStyle()); os << formatStyleAttributes("num", docStyle.getNumberStyle()); os << formatStyleAttributes("esc", docStyle.getEscapeCharStyle()); os << formatStyleAttributes("str", docStyle.getStringStyle()); os << formatStyleAttributes("dstr", docStyle.getDirectiveStringStyle()); os << formatStyleAttributes("slc", docStyle.getSingleLineCommentStyle()); os << formatStyleAttributes("com", docStyle.getCommentStyle()); os << formatStyleAttributes("dir", docStyle.getDirectiveStyle()); os << formatStyleAttributes("line", docStyle.getLineStyle()); os << formatStyleAttributes("sym", docStyle.getSymbolStyle()); KeywordStyles styles = docStyle.getKeywordStyles(); for (KSIterator it=styles.begin(); it!=styles.end(); it++){ os << formatStyleAttributes(it->first, *(it->second)); } os << "% The special option is not supported by all dvi drivers\n" << "\\special{background rgb " << docStyle.getBgColour().getLatexRedValue() << " " << docStyle.getBgColour().getLatexGreenValue() << " " << docStyle.getBgColour().getLatexBlueValue() << "}"; os << "\n\\nopagenumbers\n" << "\\input colordvi\n"; styleDefinitionCache=os.str(); } return styleDefinitionCache; } } /*************************************************************************** texcode.h - description ------------------- begin : Mit Jul 24 2002 copyright : (C) 2002 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. * * * ***************************************************************************/ #ifndef TEXGENERATOR_H #define TEXGENERATOR_H #include #include #include #include "charcodes.h" #include "version.h" #include "codegenerator.h" namespace highlight { /** \brief This class generates TeX. 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 TexGenerator : public highlight::CodeGenerator { public: /** Constructor \param colourTheme Name of Colour theme to use */ TexGenerator(const string &colourTheme); TexGenerator(); ~TexGenerator(); /** 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: string styleDefinitionCache; string getStyleDefinition(); /** \return escaped character*/ virtual string maskCharacter(unsigned char ); /**\return text formatting attributes in RTF format */ string formatStyleAttributes(const string & elemName, const ElementStyle & elem); string getMatchingOpenTag(unsigned int styleID); string getMatchingCloseTag(unsigned int styleID); }; } #endif /*************************************************************************** version.h - description ------------------- begin : Mon March 3 2003 copyright : (C) 2003 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. * * * ***************************************************************************/ #ifndef VERSION_H #define VERSION_H #define HIGHLIGHT_VERSION "2.2-10" #define HIGHLIGHT_URL "http://www.andre-simon.de/" #define HIGHLIGHT_EMAIL "andre.simon1@gmx.de" #endif /*************************************************************************** htmlcode.cpp - description ------------------- begin : Wed Nov 28 2001 copyright : (C) 2001 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 "xhtmlgenerator.h" using namespace std; namespace highlight { XHtmlGenerator::XHtmlGenerator(void) {} XHtmlGenerator::XHtmlGenerator ( const string &cssStyle, const string &enc, bool omitEnc, bool withAnchors) : HtmlGenerator(cssStyle, enc, omitEnc, withAnchors) { fileSuffix=".xhtml"; brTag="
"; hrTag="
"; idAttr="id"; HTML_FOOTER= "\n\n\n\n"; } string XHtmlGenerator::getHeaderStart(const string &title){ ostringstream header; header << "\n\n" << "\n" << "\n" << title << "\n"; return header.str(); } string XHtmlGenerator::getHeader(const string &title) { ostringstream osPart1; osPart1 << getHeaderStart((title.empty())?"Source file":title ); if (langInfo.getSyntaxHighlight()) { if (includeStyleDef) //CSS-Definition in HTML- einfuegen { osPart1 << "\n"; } else //Referenz auf CSS-Datei einfuegen { osPart1 << "\n"; } } osPart1 << "\n\n
";

  return osPart1.str();
}

}
/***************************************************************************
                         xhtmlgenerator.h  -  description
                             -------------------
    begin                : Mo Jun 21 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 XHTMLGENERATOR_H
#define XHTMLGENERATOR_H

#include "htmlgenerator.h"

namespace highlight {

/**
   \brief This class generates XHTML.

   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 XHtmlGenerator : public highlight::HtmlGenerator
  {
  public:

    /** Constructor
     \param colourTheme Name of Colour theme to use
     \param enc encoding name
     \param omitEnc switch to omit encoding information
     \param withAnchors Test if HTML anchors should be attached to line numbers
    */
    XHtmlGenerator(const string &colourTheme,
                   const string &enc,
                   bool omitEnc=false,
                   bool withAnchors = false);

    XHtmlGenerator();

    /** Destructor*/
    virtual ~XHtmlGenerator() {};

  private:

    /** prints document header
       \param  title Title of the document
    */
    string getHeader(const string &title);

    string getHeaderStart(const string &title);

  };

}

#endif
/***************************************************************************
                          xmlcode.cpp  -  description
                             -------------------
    begin                : Do 20.01.2005
    copyright            : (C) 2005 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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "xmlgenerator.h"

using namespace std;
namespace highlight {

    XmlGenerator::XmlGenerator(const string &colourTheme,const string &enc, bool omitEnc)
    : CodeGenerator(colourTheme),
    encoding(enc), omitEncoding(omitEnc)
{
    styleTagOpen.push_back(getOpenTag("def"));
    styleTagOpen.push_back(getOpenTag("str"));
    styleTagOpen.push_back(getOpenTag("num"));
    styleTagOpen.push_back(getOpenTag("slc"));
    styleTagOpen.push_back(getOpenTag("com"));
    styleTagOpen.push_back(getOpenTag("esc"));
    styleTagOpen.push_back(getOpenTag("dir"));
    styleTagOpen.push_back(getOpenTag("dstr"));
    styleTagOpen.push_back(getOpenTag("line"));
    styleTagOpen.push_back(getOpenTag("sym"));

    styleTagClose.push_back(getCloseTag("def"));
    styleTagClose.push_back(getCloseTag("str"));
    styleTagClose.push_back(getCloseTag("num"));
    styleTagClose.push_back(getCloseTag("slc"));
    styleTagClose.push_back(getCloseTag("com"));
    styleTagClose.push_back(getCloseTag("esc"));
    styleTagClose.push_back(getCloseTag("dir"));
    styleTagClose.push_back(getCloseTag("dstr"));
    styleTagClose.push_back(getCloseTag("line"));
    styleTagClose.push_back(getCloseTag("sym"));

    spacer = " ";
    newLineTag = "
\n"; } string XmlGenerator::getStyleDefinition() { if (styleDefinitionCache.empty()) { ostringstream os; os << "\n\n"; styleDefinitionCache=os.str(); } return styleDefinitionCache; } string XmlGenerator::formatStyleAttributes(const string & elemName, const ElementStyle & elem) { ostringstream s; s << "\t\n" ; return s.str(); } XmlGenerator::XmlGenerator() {} XmlGenerator::~XmlGenerator() {} string XmlGenerator::getOpenTag(const string& styleName ){ return "<"+styleName+">"; } string XmlGenerator::getCloseTag(const string& styleName ){ return ""; } string XmlGenerator::getHeader(const string & title) { ostringstream header; header << "\n" << getStyleDefinition(); return header.str(); } void XmlGenerator::printBody() { *out << "\n"; processRootState(); *out << "\n"; } string XmlGenerator::getFooter() { ostringstream os; os <<"\n"; os<< "\n"; return os.str(); } string XmlGenerator::maskCharacter(unsigned char c) { switch (c) { case '<' : return "<"; break; case '>' : return ">"; break; case '&' : return "&"; break; case '\"' : return """; break; // skip first byte of multibyte chracters /* #ifndef _WIN32 case 195: return string(""); break; #endif*/ default: string m; m += c; return m; } } /*string XmlGenerator::getNewLine(){ string nlStr; if (currentState!=_UNKNOWN){ nlStr+=styleTagClose[getStyleID(currentState, currentKeywordClass)]; } nlStr += newLineTag; if (currentState!=_UNKNOWN){ nlStr+=styleTagOpen[getStyleID(currentState, currentKeywordClass)]; } return nlStr; } */ string XmlGenerator::getMatchingOpenTag(unsigned int styleID){ return getOpenTag(langInfo.getKeywordClasses()[styleID]); } string XmlGenerator::getMatchingCloseTag(unsigned int styleID){ return getCloseTag(langInfo.getKeywordClasses()[styleID]); } } /*************************************************************************** xmlcode.h - description ------------------- begin : Do 20.01.2005 copyright : (C) 2005 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 XMLGENERATOR_H #define XMLGENERATOR_H #include #include #include #include "codegenerator.h" #include "version.h" namespace highlight { /** \brief This class generates XML. 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 XmlGenerator : public highlight::CodeGenerator { public: /** Constructor \param colourTheme Name of Colour theme to use \param enc encoding name \param omitEnc switch to omit encoding information */ XmlGenerator( const string &colourTheme,const string &enc, bool omitEnc=false); XmlGenerator(); ~XmlGenerator(); /** 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: string styleDefinitionCache, encoding; bool omitEncoding; string getStyleDefinition(); string formatStyleAttributes(const string &, const ElementStyle &); /** \return escaped character*/ virtual string maskCharacter(unsigned char ); // string getNewLine(); string getOpenTag(const string& ); string getCloseTag(const string& ); string getMatchingOpenTag(unsigned int styleID); string getMatchingCloseTag(unsigned int styleID); }; } #endif /*************************************************************************** xslfocode.cpp - description ------------------- begin : Do 11.12.2003 copyright : (C) 2003 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 "xslfogenerator.h" using namespace std; namespace highlight { XslFoGenerator::XslFoGenerator(const string &colourTheme, const string &enc, bool omitEnc, bool fopCompatible) : CodeGenerator(colourTheme), encoding(enc), fopOutput(fopCompatible), omitEncoding(omitEnc) { styleTagOpen.push_back( getOpenTag(docStyle.getDefaultStyle())); styleTagOpen.push_back( getOpenTag(docStyle.getStringStyle())); styleTagOpen.push_back( getOpenTag(docStyle.getNumberStyle())); styleTagOpen.push_back( getOpenTag(docStyle.getSingleLineCommentStyle())); styleTagOpen.push_back( getOpenTag(docStyle.getCommentStyle())); styleTagOpen.push_back( getOpenTag(docStyle.getEscapeCharStyle())); styleTagOpen.push_back( getOpenTag(docStyle.getDirectiveStyle())); styleTagOpen.push_back( getOpenTag(docStyle.getDirectiveStringStyle())); styleTagOpen.push_back( getOpenTag(docStyle.getLineStyle())); styleTagOpen.push_back( getOpenTag(docStyle.getSymbolStyle())); snl << " "; for (int i=0;i"); } if (fopOutput) newLineTag ="\n"; else newLineTag ="\n"+ snl.str(); spacer = " "; } XslFoGenerator::XslFoGenerator() {} XslFoGenerator::~XslFoGenerator() {} string XslFoGenerator::getOpenTag(const ElementStyle &elem) { ostringstream s; s << ""; return s.str(); } string XslFoGenerator::getHeader(const string & title) { ostringstream os; os << "\n\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n" << "\n\n" << "\n" << " \n"; if (fopOutput) os << snl.str()<< ""; else os << snl.str(); return os.str(); } /** gibt RTF-Text aus */ void XslFoGenerator::printBody() { processRootState(); } string XslFoGenerator::getFooter() { ostringstream os; if (fopOutput) os <<"\n"; os <<"\n\n \n\n"<\n"; return os.str(); } /** Gibt RTF-Code der Sonderzeichen zurueck */ string XslFoGenerator::maskCharacter(unsigned char c) { switch (c) { case '<' : return "<"; break; case '>' : return ">"; break; case '&' : return "&"; break; case '\"' : return """; break; // skip first byte of multibyte chracters /*#ifndef _WIN32 case 195: return string(""); break; #endif*/ default: string m; m += c; return m; } } /*string XslFoGenerator::getNewLine(){ string nlStr; if (currentState!=_UNKNOWN){ nlStr+=styleTagClose[getStyleID(currentState, currentKeywordClass)]; } nlStr += newLineTag; if (currentState!=_UNKNOWN){ nlStr+=styleTagOpen[getStyleID(currentState, currentKeywordClass)]; } return nlStr; }*/ string XslFoGenerator::getMatchingOpenTag(unsigned int styleID){ return getOpenTag(docStyle.getKeywordStyle(langInfo.getKeywordClasses()[styleID])); } string XslFoGenerator::getMatchingCloseTag(unsigned int styleID){ return ""; } } /*************************************************************************** xslfocode.h - description ------------------- begin : Do 11.12.2003 copyright : (C) 2003 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 XSLFOGENERATOR_H #define XSLFOGENERATOR_H #include #include #include #include #include "codegenerator.h" #include "version.h" namespace highlight { /** \brief This class generates XSL-FO. 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 XslFoGenerator : public highlight::CodeGenerator { public: /** Constructor \param colourTheme Name of Colour theme to use \param enc encoding name \param omitEnc switch to omit encoding information \param fopCompatible Test if output should be compatible with Apache FOP 0.20.5 */ XslFoGenerator( const string &colourTheme, const string &enc, bool omitEnc=false, bool fopCompatible=false); XslFoGenerator(); ~XslFoGenerator(); /** 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: ostringstream snl; string styleDefinition, encoding; bool fopOutput, omitEncoding; /** \return escaped character*/ virtual string maskCharacter(unsigned char ); string getOpenTag(const ElementStyle &); // string getNewLine(); string getMatchingOpenTag(unsigned int styleID); string getMatchingCloseTag(unsigned int styleID); }; } #endif