summaryrefslogtreecommitdiff
path: root/bench/example.cpp
diff options
context:
space:
mode:
authormurphy <murphy@rubychan.de>2005-10-29 14:49:23 +0000
committermurphy <murphy@rubychan.de>2005-10-29 14:49:23 +0000
commit382685e66f662d8bfb760099ec5e394f15db0d3c (patch)
tree56c395136b35fa36a0589ecb04984b7d3a7b0eff /bench/example.cpp
parent84199b89843d0eca9a85b66dbeae9fd10fdc7d63 (diff)
downloadcoderay-382685e66f662d8bfb760099ec5e394f15db0d3c.tar.gz
Added the good old benchmark suite to the repository.
Diffstat (limited to 'bench/example.cpp')
-rw-r--r--bench/example.cpp13544
1 files changed, 13544 insertions, 0 deletions
diff --git a/bench/example.cpp b/bench/example.cpp
new file mode 100644
index 0000000..ba9cf72
--- /dev/null
+++ b/bench/example.cpp
@@ -0,0 +1,13544 @@
+/***************************************************************************
+ ansigenerator.cpp - description
+ -------------------
+ begin : Jul 5 2004
+ copyright : (C) 2004 by André Simon
+ email : andre.simon1@gmx.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "ansigenerator.h"
+
+using namespace std;
+
+namespace highlight {
+
+
+string AnsiGenerator::getOpenTag(const string&font,
+ const string&fgCol, const string&bgCol) {
+ ostringstream s;
+ s << "\033["<<font;
+ if (!fgCol.empty())
+ s<<";"<<fgCol;
+ if (!bgCol.empty())
+ s<<";"<<bgCol;
+ s << "m";
+ return s.str();
+}
+
+
+AnsiGenerator::AnsiGenerator(const string &colourTheme)
+ : CodeGenerator(colourTheme) {
+ styleTagOpen.push_back("");
+ styleTagOpen.push_back(getOpenTag("00", "31")); //str
+ styleTagOpen.push_back(getOpenTag("00", "34"));//number
+ styleTagOpen.push_back(getOpenTag("00", "34"));//sl comment
+ styleTagOpen.push_back(getOpenTag("00", "34"));//ml comment
+ styleTagOpen.push_back(getOpenTag("00", "35"));//escapeChar
+ styleTagOpen.push_back(getOpenTag("00", "35"));//directive
+ styleTagOpen.push_back(getOpenTag("01", "31"));//directive string
+ styleTagOpen.push_back(getOpenTag("00", "30"));//linenum
+ styleTagOpen.push_back(getOpenTag("01", "00"));//symbol
+
+ styleTagClose.push_back("");
+ for (int i=1;i<NUMBER_BUILTIN_STYLES; i++) {
+ styleTagClose.push_back("\033[m");
+ }
+ newLineTag = "\n";
+ spacer = " ";
+}
+
+AnsiGenerator::AnsiGenerator() {}
+AnsiGenerator::~AnsiGenerator() {}
+
+string AnsiGenerator::getHeader(const string & title) {
+ return string();
+}
+
+void AnsiGenerator::printBody() {
+ processRootState();
+}
+
+string AnsiGenerator::getFooter() {
+ return string();
+}
+
+string AnsiGenerator::maskCharacter(unsigned char c) {
+ string m;
+ m+=c;
+ return m;
+}
+
+string AnsiGenerator::getMatchingOpenTag(unsigned int styleID) {
+ return (styleID)?getOpenTag("01", "32", ""):getOpenTag("00", "33");
+}
+
+string AnsiGenerator::getMatchingCloseTag(unsigned int styleID) {
+ return "\033[m";
+}
+
+}
+/***************************************************************************
+ ansicode.h - description
+ -------------------
+ begin : Jul 5 2004
+ copyright : (C) 2004 by Andre Simon
+ email : andre.simon1@gmx.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef ANSIGENERATOR_H
+#define ANSIGENERATOR_H
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <sstream>
+
+#include "codegenerator.h"
+#include "charcodes.h"
+#include "version.h"
+
+namespace highlight {
+
+/**
+ \brief This class generates ANSI escape sequences.
+
+ It contains information about the resulting document structure (document
+ header and footer), the colour system, white space handling and text
+ formatting attributes.
+
+* @author Andre Simon
+*/
+
+class AnsiGenerator : public highlight::CodeGenerator
+ {
+ public:
+
+ /** Constructor
+ \param colourTheme Name of Colour theme to use
+ */
+ AnsiGenerator( const string &colourTheme);
+ AnsiGenerator();
+ ~AnsiGenerator();
+
+ /** prints document header
+ \param title Title of the document
+ */
+ string getHeader(const string & title);
+
+ /** Prints document footer*/
+ string getFooter();
+
+ /** Prints document body*/
+ void printBody();
+
+ private:
+
+ /** \return escaped character*/
+ virtual string maskCharacter(unsigned char );
+
+
+ /** gibt ANSI-"Tags" zurueck (Farbindex+bold+kursiv)*/
+ string getOpenTag(const string&font,
+ const string&fgCol, const string&bgCol="");
+
+
+
+ string getMatchingOpenTag(unsigned int styleID);
+ string getMatchingCloseTag(unsigned int styleID);
+ };
+
+}
+#endif
+/*
+ * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
+ *
+ * ASBeautifier.cpp
+ * by Tal Davidson (davidsont@bigfoot.com)
+ * This file is a part of "Artistic Style" - an indentater and reformatter
+ * of C, C, C# and Java source files.
+ *
+ * The "Artistic Style" project, including all files needed to compile it,
+ * is free software; you can redistribute it and/or use it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program.
+ *
+ * Patches:
+ * 18 March 1999 - Brian Rampel -
+ * Fixed inverse insertion of spaces vs. tabs when in -t mode.
+ * 08 may 2004
+ * applied ASBeautifier.cpp.BITFIELD.patch.bz2
+ */
+
+#include "compiler_defines.h"
+#include "ASBeautifier.h"
+
+#include <vector>
+#include <string>
+#include <cctype>
+#include <algorithm>
+#include <iostream>
+
+
+#define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); }
+#define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container) ; }
+
+#ifdef USES_NAMESPACE
+using namespace std;
+#endif
+
+
+
+
+#ifdef USES_NAMESPACE
+namespace astyle
+ {
+#endif
+
+ bool ASBeautifier::calledInitStatic = false;
+
+ vector<const string*> ASBeautifier::headers;
+ vector<const string*> ASBeautifier::nonParenHeaders;
+ vector<const string*> ASBeautifier::preBlockStatements;
+ vector<const string*> ASBeautifier::assignmentOperators;
+ vector<const string*> ASBeautifier::nonAssignmentOperators;
+
+ /*
+ * initialize the static vars
+ */
+ void ASBeautifier::initStatic()
+ {
+ if (calledInitStatic)
+ return;
+
+ calledInitStatic = true;
+
+ headers.push_back(&AS_IF);
+ headers.push_back(&AS_ELSE);
+ headers.push_back(&AS_FOR);
+ headers.push_back(&AS_WHILE);
+ headers.push_back(&AS_DO);
+ headers.push_back(&AS_TRY);
+ headers.push_back(&AS_CATCH);
+ headers.push_back(&AS_FINALLY);
+ headers.push_back(&AS_SYNCHRONIZED);
+ headers.push_back(&AS_SWITCH);
+ headers.push_back(&AS_CASE);
+ headers.push_back(&AS_DEFAULT);
+ headers.push_back(&AS_FOREACH);
+ headers.push_back(&AS_LOCK);
+ headers.push_back(&AS_UNSAFE);
+ headers.push_back(&AS_FIXED);
+ headers.push_back(&AS_GET);
+ headers.push_back(&AS_SET);
+ headers.push_back(&AS_ADD);
+ headers.push_back(&AS_REMOVE);
+ //headers.push_back(&AS_PUBLIC);
+ //headers.push_back(&AS_PRIVATE);
+ //headers.push_back(&AS_PROTECTED);
+
+ //headers.push_back(&AS_OPERATOR);
+ headers.push_back(&AS_TEMPLATE);
+ headers.push_back(&AS_CONST);
+ /**/
+ headers.push_back(&AS_STATIC);
+ headers.push_back(&AS_EXTERN);
+
+ nonParenHeaders.push_back(&AS_ELSE);
+ nonParenHeaders.push_back(&AS_DO);
+ nonParenHeaders.push_back(&AS_TRY);
+ nonParenHeaders.push_back(&AS_FINALLY);
+ nonParenHeaders.push_back(&AS_STATIC);
+ nonParenHeaders.push_back(&AS_CONST);
+ nonParenHeaders.push_back(&AS_EXTERN);
+ nonParenHeaders.push_back(&AS_CASE);
+ nonParenHeaders.push_back(&AS_DEFAULT);
+ nonParenHeaders.push_back(&AS_UNSAFE);
+ nonParenHeaders.push_back(&AS_GET);
+ nonParenHeaders.push_back(&AS_SET);
+ nonParenHeaders.push_back(&AS_ADD);
+ nonParenHeaders.push_back(&AS_REMOVE);
+
+
+
+ nonParenHeaders.push_back(&AS_PUBLIC);
+ nonParenHeaders.push_back(&AS_PRIVATE);
+ nonParenHeaders.push_back(&AS_PROTECTED);
+ nonParenHeaders.push_back(&AS_TEMPLATE);
+ nonParenHeaders.push_back(&AS_CONST);
+ /// nonParenHeaders.push_back(&AS_ASM);
+
+ preBlockStatements.push_back(&AS_CLASS);
+ preBlockStatements.push_back(&AS_STRUCT);
+ preBlockStatements.push_back(&AS_UNION);
+ preBlockStatements.push_back(&AS_INTERFACE);
+ preBlockStatements.push_back(&AS_NAMESPACE);
+ preBlockStatements.push_back(&AS_THROWS);
+ preBlockStatements.push_back(&AS_EXTERN);
+
+ assignmentOperators.push_back(&AS_ASSIGN);
+ assignmentOperators.push_back(&AS_PLUS_ASSIGN);
+ assignmentOperators.push_back(&AS_MINUS_ASSIGN);
+ assignmentOperators.push_back(&AS_MULT_ASSIGN);
+ assignmentOperators.push_back(&AS_DIV_ASSIGN);
+ assignmentOperators.push_back(&AS_MOD_ASSIGN);
+ assignmentOperators.push_back(&AS_OR_ASSIGN);
+ assignmentOperators.push_back(&AS_AND_ASSIGN);
+ assignmentOperators.push_back(&AS_XOR_ASSIGN);
+ assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
+ assignmentOperators.push_back(&AS_GR_GR_ASSIGN);
+ assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
+ assignmentOperators.push_back(&AS_LS_LS_ASSIGN);
+
+ assignmentOperators.push_back(&AS_RETURN);
+
+ nonAssignmentOperators.push_back(&AS_EQUAL);
+ nonAssignmentOperators.push_back(&AS_PLUS_PLUS);
+ nonAssignmentOperators.push_back(&AS_MINUS_MINUS);
+ nonAssignmentOperators.push_back(&AS_NOT_EQUAL);
+ nonAssignmentOperators.push_back(&AS_GR_EQUAL);
+ nonAssignmentOperators.push_back(&AS_GR_GR_GR);
+ nonAssignmentOperators.push_back(&AS_GR_GR);
+ nonAssignmentOperators.push_back(&AS_LS_EQUAL);
+ nonAssignmentOperators.push_back(&AS_LS_LS_LS);
+ nonAssignmentOperators.push_back(&AS_LS_LS);
+ nonAssignmentOperators.push_back(&AS_ARROW);
+ nonAssignmentOperators.push_back(&AS_AND);
+ nonAssignmentOperators.push_back(&AS_OR);
+ }
+
+ /**
+ * ASBeautifier's constructor
+ */
+ ASBeautifier::ASBeautifier()
+ {
+ initStatic();
+
+ waitingBeautifierStack = NULL;
+ activeBeautifierStack = NULL;
+ waitingBeautifierStackLengthStack = NULL;
+ activeBeautifierStackLengthStack = NULL;
+
+ headerStack = NULL;
+ tempStacks = NULL;
+ blockParenDepthStack = NULL;
+ blockStatementStack = NULL;
+ parenStatementStack = NULL;
+ bracketBlockStateStack = NULL;
+ inStatementIndentStack = NULL;
+ inStatementIndentStackSizeStack = NULL;
+ parenIndentStack = NULL;
+ sourceIterator = NULL;
+
+ isMinimalConditinalIndentSet = false;
+ shouldForceTabIndentation = false;
+
+ setSpaceIndentation(4);
+ setMaxInStatementIndentLength(40);
+ setClassIndent(false);
+ setSwitchIndent(false);
+ setCaseIndent(false);
+ setBlockIndent(false);
+ setBracketIndent(false);
+ setNamespaceIndent(false);
+ setLabelIndent(false);
+ setEmptyLineFill(false);
+ setCStyle();
+ setPreprocessorIndent(false);
+ }
+
+ ASBeautifier::ASBeautifier(const ASBeautifier &other)
+ {
+ waitingBeautifierStack = NULL;
+ activeBeautifierStack = NULL;
+ waitingBeautifierStackLengthStack = NULL;
+ activeBeautifierStackLengthStack = NULL;
+
+ headerStack = new vector<const string*>;
+ *headerStack = *other.headerStack;
+
+ tempStacks = new vector< vector<const string*>* >;
+ vector< vector<const string*>* >::iterator iter;
+ for (iter = other.tempStacks->begin();
+ iter != other.tempStacks->end();
+ ++iter)
+ {
+ vector<const string*> *newVec = new vector<const string*>;
+ *newVec = **iter;
+ tempStacks->push_back(newVec);
+ }
+ blockParenDepthStack = new vector<int>;
+ *blockParenDepthStack = *other.blockParenDepthStack;
+
+ blockStatementStack = new vector<bool>;
+ *blockStatementStack = *other.blockStatementStack;
+
+ parenStatementStack = new vector<bool>;
+ *parenStatementStack = *other.parenStatementStack;
+
+ bracketBlockStateStack = new vector<bool>;
+ *bracketBlockStateStack = *other.bracketBlockStateStack;
+
+ inStatementIndentStack = new vector<int>;
+ *inStatementIndentStack = *other.inStatementIndentStack;
+
+ inStatementIndentStackSizeStack = new vector<int>;
+ *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack;
+
+ parenIndentStack = new vector<int>;
+ *parenIndentStack = *other.parenIndentStack;
+
+ sourceIterator = other.sourceIterator;
+
+ indentString = other.indentString;
+ currentHeader = other.currentHeader;
+ previousLastLineHeader = other.previousLastLineHeader;
+ immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp;
+ isInQuote = other.isInQuote;
+ isInComment = other.isInComment;
+ isInCase = other.isInCase;
+ isInQuestion = other.isInQuestion;
+ isInStatement =other. isInStatement;
+ isInHeader = other.isInHeader;
+ isCStyle = other.isCStyle;
+ isInOperator = other.isInOperator;
+ isInTemplate = other.isInTemplate;
+ isInConst = other.isInConst;
+ classIndent = other.classIndent;
+ isInClassHeader = other.isInClassHeader;
+ isInClassHeaderTab = other.isInClassHeaderTab;
+ switchIndent = other.switchIndent;
+ caseIndent = other.caseIndent;
+ namespaceIndent = other.namespaceIndent;
+ bracketIndent = other.bracketIndent;
+ blockIndent = other.blockIndent;
+ labelIndent = other.labelIndent;
+ preprocessorIndent = other.preprocessorIndent;
+ parenDepth = other.parenDepth;
+ indentLength = other.indentLength;
+ blockTabCount = other.blockTabCount;
+ leadingWhiteSpaces = other.leadingWhiteSpaces;
+ maxInStatementIndent = other.maxInStatementIndent;
+ templateDepth = other.templateDepth;
+ quoteChar = other.quoteChar;
+ prevNonSpaceCh = other.prevNonSpaceCh;
+ currentNonSpaceCh = other.currentNonSpaceCh;
+ currentNonLegalCh = other.currentNonLegalCh;
+ prevNonLegalCh = other.prevNonLegalCh;
+ isInConditional = other.isInConditional;
+ minConditionalIndent = other.minConditionalIndent;
+ prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount;
+ prevFinalLineTabCount = other.prevFinalLineTabCount;
+ emptyLineFill = other.emptyLineFill;
+ probationHeader = other.probationHeader;
+ isInDefine = other.isInDefine;
+ isInDefineDefinition = other.isInDefineDefinition;
+ backslashEndsPrevLine = other.backslashEndsPrevLine;
+ defineTabCount = other.defineTabCount;
+ }
+
+ /**
+ * ASBeautifier's destructor
+ */
+ ASBeautifier::~ASBeautifier()
+ {
+ DELETE_CONTAINER( headerStack );
+ DELETE_CONTAINER( tempStacks );
+ DELETE_CONTAINER( blockParenDepthStack );
+ DELETE_CONTAINER( blockStatementStack );
+ DELETE_CONTAINER( parenStatementStack );
+ DELETE_CONTAINER( bracketBlockStateStack );
+ DELETE_CONTAINER( inStatementIndentStack );
+ DELETE_CONTAINER( inStatementIndentStackSizeStack );
+ DELETE_CONTAINER( parenIndentStack );
+
+ // DELETE_CONTAINER( sourceIterator );
+ }
+
+ /**
+ * initialize the ASBeautifier.
+ *
+ * init() should be called every time a ABeautifier object is to start
+ * beautifying a NEW source file.
+ * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
+ * that will be used to iterate through the source code. This object will be
+ * deleted during the ASBeautifier's destruction, and thus should not be
+ * deleted elsewhere.
+ *
+ * @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
+ */
+ void ASBeautifier::init(ASSourceIterator *iter)
+
+ {
+ sourceIterator = iter;
+ init();
+ }
+
+ /**
+ * initialize the ASBeautifier.
+ */
+ void ASBeautifier::init()
+ {
+ INIT_CONTAINER( waitingBeautifierStack, new vector<ASBeautifier*> );
+ INIT_CONTAINER( activeBeautifierStack, new vector<ASBeautifier*> );
+
+ INIT_CONTAINER( waitingBeautifierStackLengthStack, new vector<int> );
+ INIT_CONTAINER( activeBeautifierStackLengthStack, new vector<int> );
+
+ INIT_CONTAINER( headerStack, new vector<const string*> );
+ INIT_CONTAINER( tempStacks, new vector< vector<const string*>* > );
+ tempStacks->push_back(new vector<const string*>);
+
+ INIT_CONTAINER( blockParenDepthStack, new vector<int> );
+ INIT_CONTAINER( blockStatementStack, new vector<bool> );
+ INIT_CONTAINER( parenStatementStack, new vector<bool> );
+
+ INIT_CONTAINER( bracketBlockStateStack, new vector<bool> );
+ bracketBlockStateStack->push_back(true);
+
+ INIT_CONTAINER( inStatementIndentStack, new vector<int> );
+ INIT_CONTAINER( inStatementIndentStackSizeStack, new vector<int> );
+ inStatementIndentStackSizeStack->push_back(0);
+ INIT_CONTAINER( parenIndentStack, new vector<int> );
+
+ immediatelyPreviousAssignmentOp = NULL;
+ previousLastLineHeader = NULL;
+
+ isInQuote = false;
+ isInComment = false;
+ isInStatement = false;
+ isInCase = false;
+ isInQuestion = false;
+ isInClassHeader = false;
+ isInClassHeaderTab = false;
+ isInHeader = false;
+ isInOperator = false;
+ isInTemplate = false;
+ isInConst = false;
+ isInConditional = false;
+ templateDepth = 0;
+ parenDepth=0;
+ blockTabCount = 0;
+ leadingWhiteSpaces = 0;
+ prevNonSpaceCh = '{';
+ currentNonSpaceCh = '{';
+ prevNonLegalCh = '{';
+ currentNonLegalCh = '{';
+ prevFinalLineSpaceTabCount = 0;
+ prevFinalLineTabCount = 0;
+ probationHeader = NULL;
+ backslashEndsPrevLine = false;
+ isInDefine = false;
+ isInDefineDefinition = false;
+ defineTabCount = 0;
+ }
+
+ /**
+ * set indentation style to ANSI C/C++.
+ */
+ void ASBeautifier::setCStyle()
+ {
+ isCStyle = true;
+ }
+
+ /**
+ * set indentation style to Java / K&R.
+ */
+ void ASBeautifier::setJavaStyle()
+ {
+ isCStyle = false;
+ }
+
+ /**
+ * indent using one tab per indentation
+ */
+ void ASBeautifier::setTabIndentation(int length, bool forceTabs)
+ {
+ indentString = "\t";
+ indentLength = length;
+ shouldForceTabIndentation = forceTabs;
+
+ if (!isMinimalConditinalIndentSet)
+ minConditionalIndent = indentLength * 2;
+ }
+
+ /**
+
+ * indent using a number of spaces per indentation.
+ *
+ * @param length number of spaces per indent.
+ */
+ void ASBeautifier::setSpaceIndentation(int length)
+ {
+ indentString=string(length, ' ');
+ indentLength = length;
+
+ if (!isMinimalConditinalIndentSet)
+ minConditionalIndent = indentLength * 2;
+ }
+
+ /**
+ * set the maximum indentation between two lines in a multi-line statement.
+ *
+ * @param max maximum indentation length.
+ */
+ void ASBeautifier::setMaxInStatementIndentLength(int max)
+ {
+ maxInStatementIndent = max;
+ }
+
+ /**
+ * set the minimum indentation between two lines in a multi-line condition.
+ *
+ * @param min minimal indentation length.
+ */
+ void ASBeautifier::setMinConditionalIndentLength(int min)
+ {
+ minConditionalIndent = min;
+ isMinimalConditinalIndentSet = true;
+ }
+
+ /**
+ * set the state of the bracket indentation option. If true, brackets will
+ * be indented one additional indent.
+ *
+ * @param state state of option.
+ */
+ void ASBeautifier::setBracketIndent(bool state)
+ {
+ bracketIndent = state;
+ }
+
+ /**
+ * set the state of the block indentation option. If true, entire blocks
+ * will be indented one additional indent, similar to the GNU indent style.
+ *
+ * @param state state of option.
+ */
+ void ASBeautifier::setBlockIndent(bool state)
+ {
+ if (state)
+ setBracketIndent(false); // so that we don't have both bracket and block indent
+ blockIndent = state;
+ }
+
+ /**
+ * set the state of the class indentation option. If true, C++ class
+ * definitions will be indented one additional indent.
+ *
+ * @param state state of option.
+ */
+ void ASBeautifier::setClassIndent(bool state)
+ {
+ classIndent = state;
+ }
+
+ /**
+ * set the state of the switch indentation option. If true, blocks of 'switch'
+ * statements will be indented one additional indent.
+ *
+ * @param state state of option.
+ */
+ void ASBeautifier::setSwitchIndent(bool state)
+ {
+ switchIndent = state;
+ }
+
+ /**
+ * set the state of the case indentation option. If true, lines of 'case'
+ * statements will be indented one additional indent.
+ *
+ * @param state state of option.
+ */
+ void ASBeautifier::setCaseIndent(bool state)
+ {
+ caseIndent = state;
+ }
+ /**
+ * set the state of the namespace indentation option.
+ * If true, blocks of 'namespace' statements will be indented one
+ * additional indent. Otherwise, NO indentation will be added.
+ *
+ * @param state state of option.
+ */
+ void ASBeautifier::setNamespaceIndent(bool state)
+ {
+ namespaceIndent = state;
+ }
+
+ /**
+ * set the state of the label indentation option.
+ * If true, labels will be indented one indent LESS than the
+ * current indentation level.
+ * If false, labels will be flushed to the left with NO
+ * indent at all.
+ *
+ * @param state state of option.
+ */
+ void ASBeautifier::setLabelIndent(bool state)
+ {
+ labelIndent = state;
+ }
+
+ /**
+ * set the state of the preprocessor indentation option.
+ * If true, multiline #define statements will be indented.
+ *
+ * @param state state of option.
+ */
+ void ASBeautifier::setPreprocessorIndent(bool state)
+ {
+ preprocessorIndent = state;
+ }
+
+ /**
+ * set the state of the empty line fill option.
+ * If true, empty lines will be filled with the whitespace.
+ * of their previous lines.
+ * If false, these lines will remain empty.
+ *
+ * @param state state of option.
+ */
+ void ASBeautifier::setEmptyLineFill(bool state)
+ {
+ emptyLineFill = state;
+ }
+
+ /**
+ * check if there are any indented lines ready to be read by nextLine()
+ *
+ * @return are there any indented lines ready?
+ */
+ bool ASBeautifier::hasMoreLines() const
+ {
+ return sourceIterator->hasMoreLines();
+ }
+
+ /**
+ * get the next indented line.
+ *
+ * @return indented line.
+ */
+ string ASBeautifier::nextLine()
+ {
+ return beautify(sourceIterator->nextLine());
+ }
+
+ /**
+ * beautify a line of source code.
+ * every line of source code in a source code file should be sent
+ * one after the other to the beautify method.
+ *
+ * @return the indented line.
+ * @param originalLine the original unindented line.
+ */
+ string ASBeautifier::beautify(const string &originalLine)
+ {
+ string line;
+ bool isInLineComment = false;
+ bool lineStartsInComment = false;
+ bool isInClass = false;
+ bool isInSwitch = false;
+ bool isImmediatelyAfterConst = false;
+ bool isSpecialChar = false;
+
+ char ch = ' ';
+ char prevCh;
+ string outBuffer; // the newly idented line is bufferd here
+ int tabCount = 0;
+ const string *lastLineHeader = NULL;
+ bool closingBracketReached = false;
+ int spaceTabCount = 0;
+ char tempCh;
+ unsigned int headerStackSize = headerStack->size();
+ //bool isLineInStatement = isInStatement;
+ bool shouldIndentBrackettedLine = true;
+ int lineOpeningBlocksNum = 0;
+ int lineClosingBlocksNum = 0;
+ bool previousLineProbation = (probationHeader != NULL);
+ unsigned int i;
+
+ currentHeader = NULL;
+
+ lineStartsInComment = isInComment;
+
+ // handle and remove white spaces around the line:
+ // If not in comment, first find out size of white space before line,
+ // so that possible comments starting in the line continue in
+ // relation to the preliminary white-space.
+ if (!isInComment)
+ {
+ leadingWhiteSpaces = 0;
+ while (leadingWhiteSpaces<originalLine.length() && originalLine[leadingWhiteSpaces] <= 0x20)
+ leadingWhiteSpaces++;
+
+ line = trim(originalLine);
+ }
+ else
+ {
+ unsigned int trimSize;
+ for (trimSize=0;
+ trimSize < originalLine.length() && trimSize<leadingWhiteSpaces && originalLine[trimSize] <= 0x20 ;
+ trimSize++)
+ ;
+ line = originalLine.substr(trimSize);
+ }
+
+
+ if (line.length() == 0)
+ {
+ if (emptyLineFill)
+ return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount);
+ else
+ return line;
+ }
+
+ // handle preprocessor commands
+
+ if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine))
+ {
+ if (line[0] == '#')
+ {
+ string preproc = trim(string(line.c_str() + 1));
+
+
+ // When finding a multi-lined #define statement, the original beautifier
+ // 1. sets its isInDefineDefinition flag
+ // 2. clones a new beautifier that will be used for the actual indentation
+ // of the #define. This clone is put into the activeBeautifierStack in order
+ // to be called for the actual indentation.
+ // The original beautifier will have isInDefineDefinition = true, isInDefine = false
+ // The cloned beautifier will have isInDefineDefinition = true, isInDefine = true
+ if (preprocessorIndent && preproc.COMPARE(0, 6, string("define")) == 0 && line[line.length() - 1] == '\\')
+ {
+ if (!isInDefineDefinition)
+ {
+ ASBeautifier *defineBeautifier;
+
+ // this is the original beautifier
+ isInDefineDefinition = true;
+
+ // push a new beautifier into the active stack
+ // this breautifier will be used for the indentation of this define
+ defineBeautifier = new ASBeautifier(*this);
+ //defineBeautifier->init();
+ //defineBeautifier->isInDefineDefinition = true;
+ //defineBeautifier->beautify("");
+ activeBeautifierStack->push_back(defineBeautifier);
+ }
+ else
+ {
+ // the is the cloned beautifier that is in charge of indenting the #define.
+ isInDefine = true;
+ }
+ }
+ else if (preproc.COMPARE(0, 2, string("if")) == 0)
+ {
+ // push a new beautifier into the stack
+ waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size());
+ activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size());
+ waitingBeautifierStack->push_back(new ASBeautifier(*this));
+ }
+ else if (preproc.COMPARE(0, 4/*2*/, string("else")) == 0)
+ {
+ if (!waitingBeautifierStack->empty())
+ {
+ // MOVE current waiting beautifier to active stack.
+ activeBeautifierStack->push_back(waitingBeautifierStack->back());
+ waitingBeautifierStack->pop_back();
+ }
+ }
+ else if (preproc.COMPARE(0, 4, string("elif")) == 0)
+ {
+ if (!waitingBeautifierStack->empty())
+ {
+ // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original.
+ activeBeautifierStack->push_back( new ASBeautifier( *(waitingBeautifierStack->back()) ) );
+ }
+ }
+ else if (preproc.COMPARE(0, 5, string("endif")) == 0)
+ {
+ unsigned int stackLength;
+ ASBeautifier *beautifier;
+
+ if (!waitingBeautifierStackLengthStack->empty())
+ {
+ stackLength = waitingBeautifierStackLengthStack->back();
+ waitingBeautifierStackLengthStack->pop_back();
+ while (waitingBeautifierStack->size() > stackLength)
+ {
+ beautifier = waitingBeautifierStack->back();
+ waitingBeautifierStack->pop_back();
+ delete beautifier;
+ }
+ }
+
+ if (!activeBeautifierStackLengthStack->empty())
+ {
+ stackLength = activeBeautifierStackLengthStack->back();
+ activeBeautifierStackLengthStack->pop_back();
+ while (activeBeautifierStack->size() > stackLength)
+ {
+ beautifier = activeBeautifierStack->back();
+ activeBeautifierStack->pop_back();
+ delete beautifier;
+ }
+ }
+
+
+ }
+ }
+
+ // check if the last char is a backslash
+ if(line.length() > 0)
+ backslashEndsPrevLine = (line[line.length() - 1] == '\\');
+ else
+ backslashEndsPrevLine = false;
+
+ // check if this line ends a multi-line #define
+ // if so, use the #define's cloned beautifier for the line's indentation
+ // and then remove it from the active beautifier stack and delete it.
+ if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine)
+ {
+ string beautifiedLine;
+ ASBeautifier *defineBeautifier;
+
+ isInDefineDefinition = false;
+ defineBeautifier = activeBeautifierStack->back();
+ activeBeautifierStack->pop_back();
+
+ beautifiedLine = defineBeautifier->beautify(line);
+ delete defineBeautifier;
+ return beautifiedLine;
+ }
+
+ // unless this is a multi-line #define, return this precompiler line as is.
+ if (!isInDefine && !isInDefineDefinition)
+ return originalLine;
+ }
+
+ // if there exists any worker beautifier in the activeBeautifierStack,
+ // then use it instead of me to indent the current line.
+ if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty())
+ {
+ return activeBeautifierStack->back()->beautify(line);
+ }
+
+ // calculate preliminary indentation based on data from past lines
+ if (!inStatementIndentStack->empty())
+ spaceTabCount = inStatementIndentStack->back();
+
+
+ for (i=0; i<headerStackSize; i++)
+ {
+ isInClass = false;
+
+ if (blockIndent || (!(i>0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
+ && (*headerStack)[i] == &AS_OPEN_BRACKET)))
+ ++tabCount;
+
+ if (isCStyle && !namespaceIndent && i >= 1
+ && (*headerStack)[i-1] == &AS_NAMESPACE
+ && (*headerStack)[i] == &AS_OPEN_BRACKET)
+ --tabCount;
+
+ if (isCStyle && i >= 1
+ && (*headerStack)[i-1] == &AS_CLASS
+ && (*headerStack)[i] == &AS_OPEN_BRACKET )
+ {
+ if (classIndent)
+ ++tabCount;
+ isInClass = true;
+ }
+
+ // is the switchIndent option is on, indent switch statements an additional indent.
+ else if (switchIndent && i > 1 &&
+ (*headerStack)[i-1] == &AS_SWITCH &&
+ (*headerStack)[i] == &AS_OPEN_BRACKET
+ )
+ {
+ ++tabCount;
+ isInSwitch = true;
+ }
+
+ }
+
+ if (!lineStartsInComment
+ && isCStyle
+ && isInClass
+ && classIndent
+ && headerStackSize >= 2
+ &&(*headerStack)[headerStackSize-2] == &AS_CLASS
+ && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
+ && line[0] == '}')
+ --tabCount;
+
+ else if (!lineStartsInComment
+ && isInSwitch
+ && switchIndent
+ && headerStackSize >= 2
+ && (*headerStack)[headerStackSize-2] == &AS_SWITCH
+ && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
+ && line[0] == '}')
+ --tabCount;
+
+ if (isInClassHeader)
+ {
+ isInClassHeaderTab = true;
+ tabCount += 2;
+ }
+
+ if (isInConditional)
+ {
+ --tabCount;
+ }
+
+
+ // parse characters in the current line.
+
+ for (i=0; i<line.length(); i++)
+ {
+ tempCh = line[i];
+
+ prevCh = ch;
+ ch = tempCh;
+
+ outBuffer.append(1, ch);
+
+ if (isWhiteSpace(ch))
+ continue;
+
+
+ // handle special characters (i.e. backslash+character such as \n, \t, ...)
+ if (isSpecialChar)
+ {
+ isSpecialChar = false;
+ continue;
+ }
+ if (!(isInComment || isInLineComment) && line.COMPARE(i, 2, string("\\\\")) == 0)
+ {
+ outBuffer.append(1, '\\');
+ i++;
+ continue;
+ }
+ if (!(isInComment || isInLineComment) && ch=='\\')
+ {
+ isSpecialChar = true;
+ continue;
+ }
+
+ // handle quotes (such as 'x' and "Hello Dolly")
+ if (!(isInComment || isInLineComment) && (ch=='"' || ch=='\''))
+ if (!isInQuote)
+ {
+ quoteChar = ch;
+ isInQuote = true;
+ }
+ else if (quoteChar == ch)
+ {
+ isInQuote = false;
+ isInStatement = true;
+ continue;
+ }
+ if (isInQuote)
+ continue;
+
+ // handle comments
+
+ if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_LINE_COMMENT) == 0 )
+ {
+ isInLineComment = true;
+ outBuffer.append(1, '/');
+ i++;
+ continue;
+ }
+ else if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_COMMENT) == 0 )
+ {
+ isInComment = true;
+ outBuffer.append(1, '*');
+ i++;
+ continue;
+ }
+ else if ( (isInComment || isInLineComment) && line.COMPARE(i, 2, AS_CLOSE_COMMENT) == 0 )
+ {
+ isInComment = false;
+ outBuffer.append(1, '/');
+ i++;
+ continue;
+ }
+
+ if (isInComment||isInLineComment)
+ continue;
+
+ // if we have reached this far then we are NOT in a comment or string of special character...
+
+ if (probationHeader != NULL)
+ {
+ if ( ((probationHeader == &AS_STATIC || probationHeader == &AS_CONST) && ch == '{')
+ || (probationHeader == &AS_SYNCHRONIZED && ch == '('))
+ {
+ // insert the probation header as a new header
+ isInHeader = true;
+ headerStack->push_back(probationHeader);
+
+ // handle the specific probation header
+ isInConditional = (probationHeader == &AS_SYNCHRONIZED);
+ if (probationHeader == &AS_CONST)
+ isImmediatelyAfterConst = true;
+ // isInConst = true;
+ /* TODO:
+ * There is actually no more need for the global isInConst variable.
+ * The only reason for checking const is to see if there is a const
+ * immediately before an open-bracket.
+ * Since CONST is now put into probation and is checked during itspost-char,
+ * isImmediatelyAfterConst can be set by its own...
+ */
+
+ isInStatement = false;
+ // if the probation comes from the previous line, then indent by 1 tab count.
+ if (previousLineProbation && ch == '{')
+ tabCount++;
+ previousLineProbation = false;
+ }
+
+ // dismiss the probation header
+ probationHeader = NULL;
+ }
+
+ prevNonSpaceCh = currentNonSpaceCh;
+ currentNonSpaceCh = ch;
+ if (!isLegalNameChar(ch) && ch != ',' && ch != ';' )
+ {
+ prevNonLegalCh = currentNonLegalCh;
+ currentNonLegalCh = ch;
+ }
+
+ //if (isInConst)
+ //{
+ // isInConst = false;
+ // isImmediatelyAfterConst = true;
+ //}
+
+ if (isInHeader)
+ {
+ isInHeader = false;
+ currentHeader = headerStack->back();
+ }
+ else
+ currentHeader = NULL;
+
+ if (isCStyle && isInTemplate
+ && (ch == '<' || ch == '>')
+ && findHeader(line, i, nonAssignmentOperators) == NULL) //;
+ {
+ if (ch == '<')
+ {
+ ++templateDepth;
+ }
+ else if (ch == '>')
+ {
+ if (--templateDepth <= 0)
+ {
+ if (isInTemplate)
+ ch = ';';
+ else
+ ch = 't';
+ isInTemplate = false;
+ templateDepth = 0;
+ }
+
+ }
+ }
+
+ // handle parenthesies
+ if (ch == '(' || ch == '[' || ch == ')' || ch == ']')
+ {
+ if (ch == '(' || ch == '[')
+ {
+ if (parenDepth == 0)
+ {
+ parenStatementStack->push_back(isInStatement);
+ isInStatement = true;
+ }
+ parenDepth++;
+
+ inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
+
+ if (currentHeader != NULL)
+ registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true);
+ else
+ registerInStatementIndent(line, i, spaceTabCount, 0, true);
+ }
+ else if (ch == ')' || ch == ']')
+ {
+ parenDepth--;
+ if (parenDepth == 0)
+ {
+ isInStatement = parenStatementStack->back();
+ parenStatementStack->pop_back();
+ ch = ' ';
+
+ isInConditional = false;
+ }
+
+ if (!inStatementIndentStackSizeStack->empty())
+ {
+ unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back();
+ inStatementIndentStackSizeStack->pop_back();
+ while (previousIndentStackSize < inStatementIndentStack->size())
+ inStatementIndentStack->pop_back();
+
+ if (!parenIndentStack->empty())
+ {
+ int poppedIndent = parenIndentStack->back();
+ parenIndentStack->pop_back();
+
+ if (i == 0)
+ spaceTabCount = poppedIndent;
+ }
+ }
+ }
+
+ continue;
+ }
+
+
+ if (ch == '{')
+ {
+ bool isBlockOpener = false;
+
+ // first, check if '{' is a block-opener or an static-array opener
+ isBlockOpener = ( (prevNonSpaceCh == '{' && bracketBlockStateStack->back())
+ || prevNonSpaceCh == '}'
+ || prevNonSpaceCh == ')'
+ || prevNonSpaceCh == ';'
+ || isInClassHeader
+ || isBlockOpener
+ || isImmediatelyAfterConst
+ || (isInDefine &&
+ (prevNonSpaceCh == '('
+ || prevNonSpaceCh == '_'
+ || isalnum(prevNonSpaceCh))) );
+
+ isInClassHeader = false;
+ if (!isBlockOpener && currentHeader != NULL)
+ {
+ for (unsigned int n=0; n < nonParenHeaders.size(); n++)
+ if (currentHeader == nonParenHeaders[n])
+ {
+ isBlockOpener = true;
+ break;
+ }
+ }
+ bracketBlockStateStack->push_back(isBlockOpener);
+ if (!isBlockOpener)
+ {
+ inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
+ registerInStatementIndent(line, i, spaceTabCount, 0, true);
+ parenDepth++;
+ if (i == 0)
+ shouldIndentBrackettedLine = false;
+
+ continue;
+ }
+
+ // this bracket is a block opener...
+
+ ++lineOpeningBlocksNum;
+
+ if (isInClassHeader)
+ isInClassHeader = false;
+ if (isInClassHeaderTab)
+ {
+ isInClassHeaderTab = false;
+ tabCount -= 2;
+ }
+
+ blockParenDepthStack->push_back(parenDepth);
+ blockStatementStack->push_back(isInStatement);
+
+ inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
+
+ blockTabCount += isInStatement? 1 : 0;
+ parenDepth = 0;
+ isInStatement = false;
+
+ tempStacks->push_back(new vector<const string*>);
+ headerStack->push_back(&AS_OPEN_BRACKET);
+ lastLineHeader = &AS_OPEN_BRACKET; // <------
+
+ continue;
+ }
+
+ //check if a header has been reached
+ if (prevCh == ' ')
+ {
+ bool isIndentableHeader = true;
+ const string *newHeader = findHeader(line, i, headers);
+ if (newHeader != NULL)
+ {
+ // if we reached here, then this is a header...
+ isInHeader = true;
+
+ vector<const string*> *lastTempStack;
+ if (tempStacks->empty())
+ lastTempStack = NULL;
+ else
+ lastTempStack = tempStacks->back();
+
+ // if a new block is opened, push a new stack into tempStacks to hold the
+ // future list of headers in the new block.
+
+ // take care of the special case: 'else if (...)'
+ if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE)
+ {
+ //spaceTabCount += indentLength; // to counter the opposite addition that occurs when the 'if' is registered below...
+ headerStack->pop_back();
+ }
+
+ // take care of 'else'
+ else if (newHeader == &AS_ELSE)
+ {
+ if (lastTempStack != NULL)
+ {
+ int indexOfIf = indexOf(*lastTempStack, &AS_IF); // <---
+ if (indexOfIf != -1)
+ {
+ // recreate the header list in headerStack up to the previous 'if'
+ // from the temporary snapshot stored in lastTempStack.
+ int restackSize = lastTempStack->size() - indexOfIf - 1;
+ for (int r=0; r<restackSize; r++)
+ {
+ headerStack->push_back(lastTempStack->back());
+ lastTempStack->pop_back();
+ }
+ if (!closingBracketReached)
+ tabCount += restackSize;
+ }
+ /*
+ * If the above if is not true, i.e. no 'if' before the 'else',
+ * then nothing beautiful will come out of this...
+ * I should think about inserting an Exception here to notify the caller of this...
+ */
+ }
+ }
+
+ // check if 'while' closes a previous 'do'
+ else if (newHeader == &AS_WHILE)
+ {
+ if (lastTempStack != NULL)
+ {
+ int indexOfDo = indexOf(*lastTempStack, &AS_DO); // <---
+ if (indexOfDo != -1)
+ {
+ // recreate the header list in headerStack up to the previous 'do'
+ // from the temporary snapshot stored in lastTempStack.
+ int restackSize = lastTempStack->size() - indexOfDo - 1;
+ for (int r=0; r<restackSize; r++)
+ {
+ headerStack->push_back(lastTempStack->back());
+ lastTempStack->pop_back();
+ }
+ if (!closingBracketReached)
+ tabCount += restackSize;
+ }
+ }
+ }
+ // check if 'catch' closes a previous 'try' or 'catch'
+ else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY)
+ {
+ if (lastTempStack != NULL)
+ {
+ int indexOfTry = indexOf(*lastTempStack, &AS_TRY);
+ if (indexOfTry == -1)
+ indexOfTry = indexOf(*lastTempStack, &AS_CATCH);
+ if (indexOfTry != -1)
+ {
+ // recreate the header list in headerStack up to the previous 'try'
+ // from the temporary snapshot stored in lastTempStack.
+ int restackSize = lastTempStack->size() - indexOfTry - 1;
+ for (int r=0; r<restackSize; r++)
+ {
+ headerStack->push_back(lastTempStack->back());
+ lastTempStack->pop_back();
+ }
+
+ if (!closingBracketReached)
+ tabCount += restackSize;
+ }
+ }
+ }
+ else if (newHeader == &AS_CASE)
+ {
+ isInCase = true;
+ if (!caseIndent)
+ --tabCount;
+ }
+ else if(newHeader == &AS_DEFAULT)
+ {
+ isInCase = true;
+ if (!caseIndent)
+ --tabCount;
+ }
+ else if (newHeader == &AS_PUBLIC || newHeader == &AS_PROTECTED || newHeader == &AS_PRIVATE)
+ {
+ if (isCStyle && !isInClassHeader)
+ --tabCount;
+ isIndentableHeader = false;
+ }
+ //else if ((newHeader == &STATIC || newHeader == &SYNCHRONIZED) &&
+ // !headerStack->empty() &&
+ // (headerStack->back() == &STATIC || headerStack->back() == &SYNCHRONIZED))
+ //{
+ // isIndentableHeader = false;
+ //}
+ else if (newHeader == &AS_STATIC
+ || newHeader == &AS_SYNCHRONIZED
+ || (newHeader == &AS_CONST && isCStyle))
+ {
+ if (!headerStack->empty() &&
+ (headerStack->back() == &AS_STATIC
+ || headerStack->back() == &AS_SYNCHRONIZED
+ || headerStack->back() == &AS_CONST))
+ {
+ isIndentableHeader = false;
+ }
+ else
+ {
+ isIndentableHeader = false;
+ probationHeader = newHeader;
+ }
+ }
+ else if (newHeader == &AS_CONST)
+ {
+ // this will be entered only if NOT in C style
+ // since otherwise the CONST would be found to be a probstion header...
+
+ //if (isCStyle)
+ // isInConst = true;
+ isIndentableHeader = false;
+ }
+ /*
+ else if (newHeader == &OPERATOR)
+ {
+ if (isCStyle)
+ isInOperator = true;
+ isIndentableHeader = false;
+ }
+ */
+ else if (newHeader == &AS_TEMPLATE)
+ {
+ if (isCStyle)
+ isInTemplate = true;
+ isIndentableHeader = false;
+ }
+
+
+ if (isIndentableHeader)
+ {
+ // 3.2.99
+ //spaceTabCount-=indentLength;
+ headerStack->push_back(newHeader);
+ isInStatement = false;
+ if (indexOf(nonParenHeaders, newHeader) == -1)
+ {
+ isInConditional = true;
+ }
+ lastLineHeader = newHeader;
+ }
+ else
+ isInHeader = false;
+
+ //lastLineHeader = newHeader;
+
+ outBuffer.append(newHeader->substr(1));
+ i += newHeader->length() - 1;
+
+ continue;
+ }
+ }
+
+ if (isCStyle && !isalpha(prevCh)
+ && line.COMPARE(i, 8, AS_OPERATOR) == 0 && !isalnum(line[i+8]))
+ {
+ isInOperator = true;
+ outBuffer.append(AS_OPERATOR.substr(1));
+ i += 7;
+ continue;
+ }
+
+ if (ch == '?')
+ isInQuestion = true;
+
+
+ // special handling of 'case' statements
+ if (ch == ':')
+ {
+ if (line.length() > i+1 && line[i+1] == ':') // look for ::
+ {
+ ++i;
+ outBuffer.append(1, ':');
+ ch = ' ';
+ continue;
+ }
+
+ else if (isCStyle && isInClass && prevNonSpaceCh != ')')
+ {
+ // BEGIN Content of ASBeautifier.cpp.BITFIELD.patch:
+
+ unsigned int chIndex;
+ char nextCh = 0;
+ for (chIndex = i+1; chIndex < line.length(); chIndex++)
+ if (!isWhiteSpace(line[chIndex]))
+ break;
+ if (chIndex< line.length())
+ nextCh = line[chIndex];
+ int nWord =0;
+ for (chIndex = 0; chIndex < i; chIndex++)
+ {
+ if (!isWhiteSpace(line[chIndex]))
+ {
+ nWord ++;
+ while (!isWhiteSpace(line[++chIndex]));
+ }
+ }
+ if ((nextCh >= '0' && nextCh <= '9') || (nWord >1))
+ continue;
+ // END Content of ASBeautifier.cpp.BITFIELD.patch:
+
+ --tabCount;
+ // found a 'private:' or 'public:' inside a class definition
+ // so do nothing special
+ }
+
+ else if (isCStyle && isInClassHeader)
+ {
+
+ // found a 'class A : public B' definition
+ // so do nothing special
+ }
+
+ else if (isInQuestion)
+ {
+ isInQuestion = false;
+ }
+ else if (isCStyle && prevNonSpaceCh == ')')
+ {
+ isInClassHeader = true;
+ if (i==0)
+ tabCount += 2;
+ }
+ else
+ {
+ currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers
+ if (isInCase)
+ {
+ isInCase = false;
+ ch = ';'; // from here on, treat char as ';'
+ }
+ // BEGIN content of ASBeautifier.cpp.BITFIELD.patch.bz2
+ else // bitfield or labels
+ {
+ unsigned int chIndex;
+ char nextCh = 0;
+ for (chIndex = i+1; (isCStyle && chIndex < line.length()); chIndex++)
+ if (!isWhiteSpace(line[chIndex]))
+ break;
+ if (chIndex< line.length())
+ nextCh = line[chIndex];
+
+ int nWord =0;
+ for (chIndex = 0; chIndex < i; chIndex++)
+ {
+ if (!isWhiteSpace(line[chIndex]))
+ {
+ nWord ++;
+ while (!isWhiteSpace(line[++chIndex]));
+ }
+ }
+ if (isCStyle && (nextCh >= '0' && nextCh <= '9') || (nWord >1))
+ {
+ continue;
+ }
+ // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2
+
+ else // is in a label (e.g. 'label1:')
+ {
+ if (labelIndent)
+ --tabCount; // unindent label by one indent
+ else
+ tabCount = 0; // completely flush indent to left
+ }
+
+ // BEGIN content of ASASBeautifier.cpp.BITFIELD.patch.bz2
+ }
+ // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2
+
+ }
+ }
+
+ if ((ch == ';' || (parenDepth>0 && ch == ',')) && !inStatementIndentStackSizeStack->empty())
+ while ((unsigned int)inStatementIndentStackSizeStack->back() + (parenDepth>0 ? 1 : 0) < inStatementIndentStack->size())
+ inStatementIndentStack->pop_back();
+
+
+ // handle ends of statements
+ if ( (ch == ';' && parenDepth == 0) || ch == '}'/* || (ch == ',' && parenDepth == 0)*/)
+ {
+ if (ch == '}')
+ {
+ // first check if this '}' closes a previous block, or a static array...
+ if (!bracketBlockStateStack->empty())
+ {
+ bool bracketBlockState = bracketBlockStateStack->back();
+ bracketBlockStateStack->pop_back();
+ if (!bracketBlockState)
+ {
+ if (!inStatementIndentStackSizeStack->empty())
+ {
+ // this bracket is a static array
+
+ unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back();
+ inStatementIndentStackSizeStack->pop_back();
+ while (previousIndentStackSize < inStatementIndentStack->size())
+ inStatementIndentStack->pop_back();
+ parenDepth--;
+ if (i == 0)
+ shouldIndentBrackettedLine = false;
+
+ if (!parenIndentStack->empty())
+ {
+ int poppedIndent = parenIndentStack->back();
+ parenIndentStack->pop_back();
+ if (i == 0)
+ spaceTabCount = poppedIndent;
+ }
+ }
+ continue;
+ }
+ }
+
+ // this bracket is block closer...
+
+ ++lineClosingBlocksNum;
+
+ if(!inStatementIndentStackSizeStack->empty())
+ inStatementIndentStackSizeStack->pop_back();
+
+ if (!blockParenDepthStack->empty())
+ {
+ parenDepth = blockParenDepthStack->back();
+ blockParenDepthStack->pop_back();
+ isInStatement = blockStatementStack->back();
+ blockStatementStack->pop_back();
+
+ if (isInStatement)
+ blockTabCount--;
+ }
+
+ closingBracketReached = true;
+ int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET); // <---
+ if (headerPlace != -1)
+ {
+ const string *popped = headerStack->back();
+ while (popped != &AS_OPEN_BRACKET)
+ {
+ headerStack->pop_back();
+ popped = headerStack->back();
+ }
+ headerStack->pop_back();
+
+ if (!tempStacks->empty())
+ {
+ vector<const string*> *temp = tempStacks->back();
+ tempStacks->pop_back();
+ delete temp;
+ }
+ }
+
+
+ ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified...
+ }
+
+ /*
+ * Create a temporary snapshot of the current block's header-list in the
+ * uppermost inner stack in tempStacks, and clear the headerStack up to
+ * the begining of the block.
+ * Thus, the next future statement will think it comes one indent past
+ * the block's '{' unless it specifically checks for a companion-header
+ * (such as a previous 'if' for an 'else' header) within the tempStacks,
+ * and recreates the temporary snapshot by manipulating the tempStacks.
+ */
+ if (!tempStacks->back()->empty())
+ while (!tempStacks->back()->empty())
+ tempStacks->back()->pop_back();
+ while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET)
+ {
+ tempStacks->back()->push_back(headerStack->back());
+ headerStack->pop_back();
+ }
+
+ if (parenDepth == 0 && ch == ';')
+ isInStatement=false;
+
+ isInClassHeader = false;
+
+ continue;
+ }
+
+
+ // check for preBlockStatements ONLY if not within parenthesies
+ // (otherwise 'struct XXX' statements would be wrongly interpreted...)
+ if (prevCh == ' ' && !isInTemplate && parenDepth == 0)
+ {
+ const string *newHeader = findHeader(line, i, preBlockStatements);
+ if (newHeader != NULL)
+ {
+ isInClassHeader = true;
+ outBuffer.append(newHeader->substr(1));
+ i += newHeader->length() - 1;
+ //if (isCStyle)
+ headerStack->push_back(newHeader);
+ }
+ }
+
+ // Handle operators
+ //
+
+ //// // PRECHECK if a '==' or '--' or '++' operator was reached.
+ //// // If not, then register an indent IF an assignment operator was reached.
+ //// // The precheck is important, so that statements such as 'i--==2' are not recognized
+ //// // to have assignment operators (here, '-=') in them . . .
+
+ const string *foundAssignmentOp = NULL;
+ const string *foundNonAssignmentOp = NULL;
+
+ immediatelyPreviousAssignmentOp = NULL;
+
+ // Check if an operator has been reached.
+ foundAssignmentOp = findHeader(line, i, assignmentOperators, false);
+ foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false);
+
+ // Since findHeader's boundry checking was not used above, it is possible
+ // that both an assignment op and a non-assignment op where found,
+ // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
+ // found operator.
+ if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
+ if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
+ foundAssignmentOp = NULL;
+ else
+ foundNonAssignmentOp = NULL;
+
+ if (foundNonAssignmentOp != NULL)
+ {
+ if (foundNonAssignmentOp->length() > 1)
+ {
+ outBuffer.append(foundNonAssignmentOp->substr(1));
+ i += foundNonAssignmentOp->length() - 1;
+ }
+ }
+
+ else if (foundAssignmentOp != NULL)
+
+ {
+ if (foundAssignmentOp->length() > 1)
+ {
+ outBuffer.append(foundAssignmentOp->substr(1));
+ i += foundAssignmentOp->length() - 1;
+ }
+
+ if (!isInOperator && !isInTemplate)
+ {
+ registerInStatementIndent(line, i, spaceTabCount, 0, false);
+ immediatelyPreviousAssignmentOp = foundAssignmentOp;
+ isInStatement = true;
+ }
+ }
+
+ /*
+ immediatelyPreviousAssignmentOp = NULL;
+ bool isNonAssingmentOperator = false;
+ for (int n = 0; n < nonAssignmentOperators.size(); n++)
+ if (line.COMPARE(i, nonAssignmentOperators[n]->length(), *(nonAssignmentOperators[n])) == 0)
+ {
+ if (nonAssignmentOperators[n]->length() > 1)
+ {
+ outBuffer.append(nonAssignmentOperators[n]->substr(1));
+ i += nonAssignmentOperators[n]->length() - 1;
+ }
+ isNonAssingmentOperator = true;
+ break;
+ }
+ if (!isNonAssingmentOperator)
+ {
+ for (int a = 0; a < assignmentOperators.size(); a++)
+ if (line.COMPARE(i, assignmentOperators[a]->length(), *(assignmentOperators[a])) == 0)
+ {
+ if (assignmentOperators[a]->length() > 1)
+ {
+ outBuffer.append(assignmentOperators[a]->substr(1));
+ i += assignmentOperators[a]->length() - 1;
+ }
+
+ if (!isInOperator && !isInTemplate)
+ {
+ registerInStatementIndent(line, i, spaceTabCount, 0, false);
+ immediatelyPreviousAssignmentOp = assignmentOperators[a];
+ isInStatement = true;
+ }
+ break;
+ }
+ }
+ */
+
+ if (isInOperator)
+ isInOperator = false;
+ }
+
+ // handle special cases of unindentation:
+
+ /*
+ * if '{' doesn't follow an immediately previous '{' in the headerStack
+ * (but rather another header such as "for" or "if", then unindent it
+ * by one indentation relative to its block.
+ */
+ // cerr << endl << lineOpeningBlocksNum << " " << lineClosingBlocksNum << " " << previousLastLineHeader << endl;
+
+ // indent #define lines with one less tab
+ //if (isInDefine)
+ // tabCount -= defineTabCount-1;
+
+
+ if (!lineStartsInComment
+ && !blockIndent
+ && outBuffer.length()>0
+ && outBuffer[0]=='{'
+ && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum)
+ && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET)
+ && shouldIndentBrackettedLine)
+ --tabCount;
+
+ else if (!lineStartsInComment
+ && outBuffer.length()>0
+ && outBuffer[0]=='}'
+ && shouldIndentBrackettedLine )
+ --tabCount;
+
+ // correctly indent one-line-blocks...
+ else if (!lineStartsInComment
+ && outBuffer.length()>0
+ && lineOpeningBlocksNum > 0
+ && lineOpeningBlocksNum == lineClosingBlocksNum
+ && previousLastLineHeader != NULL
+ && previousLastLineHeader != &AS_OPEN_BRACKET)
+ tabCount -= 1; //lineOpeningBlocksNum - (blockIndent ? 1 : 0);
+
+ if (tabCount < 0)
+ tabCount = 0;
+
+ // take care of extra bracket indentatation option...
+ if (bracketIndent && outBuffer.length()>0 && shouldIndentBrackettedLine)
+ if (outBuffer[0]=='{' || outBuffer[0]=='}')
+ tabCount++;
+
+
+ if (isInDefine)
+ {
+ if (outBuffer[0] == '#')
+ {
+ string preproc = trim(string(outBuffer.c_str() + 1));
+ if (preproc.COMPARE(0, 6, string("define")) == 0)
+ {
+ if (!inStatementIndentStack->empty()
+ && inStatementIndentStack->back() > 0)
+ {
+ defineTabCount = tabCount;
+ }
+ else
+ {
+ defineTabCount = tabCount - 1;
+ tabCount--;
+ }
+ }
+ }
+
+ tabCount -= defineTabCount;
+ }
+
+ if (tabCount < 0)
+ tabCount = 0;
+
+
+ // finally, insert indentations into begining of line
+
+ prevFinalLineSpaceTabCount = spaceTabCount;
+ prevFinalLineTabCount = tabCount;
+
+ if (shouldForceTabIndentation)
+ {
+ tabCount += spaceTabCount / indentLength;
+ spaceTabCount = spaceTabCount % indentLength;
+ }
+
+ outBuffer = preLineWS(spaceTabCount,tabCount) + outBuffer;
+
+ if (lastLineHeader != NULL)
+ previousLastLineHeader = lastLineHeader;
+
+ return outBuffer;
+ }
+
+
+ string ASBeautifier::preLineWS(int spaceTabCount, int tabCount)
+ {
+ string ws;
+
+ for (int i=0; i<tabCount; i++)
+ ws += indentString;
+
+ while ((spaceTabCount--) > 0)
+ ws += string(" ");
+
+ return ws;
+
+ }
+
+ /**
+ * register an in-statement indent.
+ */
+ void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount,
+ int minIndent, bool updateParenStack)
+ {
+ int inStatementIndent;
+ int remainingCharNum = line.length() - i;
+ int nextNonWSChar = 1;
+
+ nextNonWSChar = getNextProgramCharDistance(line, i);
+
+ // if indent is around the last char in the line, indent instead 2 spaces from the previous indent
+ if (nextNonWSChar == remainingCharNum)
+ {
+ int previousIndent = spaceTabCount;
+ if (!inStatementIndentStack->empty())
+ previousIndent = inStatementIndentStack->back();
+
+ inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent );
+ if (updateParenStack)
+ parenIndentStack->push_back( previousIndent );
+ return;
+ }
+
+ if (updateParenStack)
+ parenIndentStack->push_back(i+spaceTabCount);
+
+ inStatementIndent = i + nextNonWSChar + spaceTabCount;
+
+ if (i + nextNonWSChar < minIndent)
+ inStatementIndent = minIndent + spaceTabCount;
+
+ if (i + nextNonWSChar > maxInStatementIndent)
+ inStatementIndent = indentLength*2 + spaceTabCount;
+
+
+
+ if (!inStatementIndentStack->empty() &&
+ inStatementIndent < inStatementIndentStack->back())
+ inStatementIndent = inStatementIndentStack->back();
+
+ inStatementIndentStack->push_back(inStatementIndent);
+ }
+
+ /**
+ * get distance to the next non-white sspace, non-comment character in the line.
+ * if no such character exists, return the length remaining to the end of the line.
+ */
+ int ASBeautifier::getNextProgramCharDistance(const string &line, int i)
+ {
+ bool inComment = false;
+ int remainingCharNum = line.length() - i;
+ int charDistance = 1;
+ int ch;
+
+ for (charDistance = 1; charDistance < remainingCharNum; charDistance++)
+ {
+ ch = line[i + charDistance];
+ if (inComment)
+ {
+ if (line.COMPARE(i + charDistance, 2, AS_CLOSE_COMMENT) == 0)
+ {
+ charDistance++;
+ inComment = false;
+ }
+ continue;
+ }
+ else if (isWhiteSpace(ch))
+ continue;
+ else if (ch == '/')
+ {
+ if (line.COMPARE(i + charDistance, 2, AS_OPEN_LINE_COMMENT) == 0)
+ return remainingCharNum;
+ else if (line.COMPARE(i + charDistance, 2, AS_OPEN_COMMENT) == 0)
+ {
+ charDistance++;
+ inComment = true;
+ }
+ }
+ else
+ return charDistance;
+ }
+
+ return charDistance;
+ }
+
+
+ /**
+ * check if a specific character can be used in a legal variable/method/class name
+ *
+ * @return legality of the char.
+ * @param ch the character to be checked.
+ */
+ bool ASBeautifier::isLegalNameChar(char ch) const
+ {
+ return (isalnum(ch) //(ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9') ||
+ || ch=='.' || ch=='_' || (!isCStyle && ch=='$') || (isCStyle && ch=='~'));
+ }
+
+
+ /**
+ * check if a specific line position contains a header, out of several possible headers.
+ *
+ * @return a pointer to the found header. if no header was found then return NULL.
+ */
+ const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry)
+ {
+ int maxHeaders = possibleHeaders.size();
+ const string *header = NULL;
+ int p;
+
+ for (p=0; p < maxHeaders; p++)
+ {
+ header = possibleHeaders[p];
+
+ if (line.COMPARE(i, header->length(), *header) == 0)
+ {
+ // check that this is a header and not a part of a longer word
+ // (e.g. not at its begining, not at its middle...)
+
+ int lineLength = line.length();
+ int headerEnd = i + header->length();
+ char startCh = (*header)[0]; // first char of header
+ char endCh = 0; // char just after header
+ char prevCh = 0; // char just before header
+
+ if (headerEnd < lineLength)
+ {
+ endCh = line[headerEnd];
+ }
+ if (i > 0)
+ {
+ prevCh = line[i-1];
+ }
+
+ if (!checkBoundry)
+ {
+ return header;
+ }
+ else if (prevCh != 0
+ && isLegalNameChar(startCh)
+ && isLegalNameChar(prevCh))
+ {
+ return NULL;
+ }
+ else if (headerEnd >= lineLength
+ || !isLegalNameChar(startCh)
+ || !isLegalNameChar(endCh))
+ {
+ return header;
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+
+ /**
+ * check if a specific character can be used in a legal variable/method/class name
+ *
+ * @return legality of the char.
+ * @param ch the character to be checked.
+ */
+ bool ASBeautifier::isWhiteSpace(char ch) const
+ {
+ return (ch == ' ' || ch == '\t');
+ }
+
+ /**
+ * find the index number of a string element in a container of strings
+ *
+ * @return the index number of element in the ocntainer. -1 if element not found.
+ * @param container a vector of strings.
+ * @param element the element to find .
+ */
+ int ASBeautifier::indexOf(vector<const string*> &container, const string *element)
+ {
+ vector<const string*>::const_iterator where;
+
+ where= find(container.begin(), container.end(), element);
+ if (where == container.end())
+ return -1;
+ else
+ return where - container.begin();
+ }
+
+ /**
+ * trim removes the white space surrounding a line.
+ *
+ * @return the trimmed line.
+ * @param str the line to trim.
+ */
+ string ASBeautifier::trim(const string &str)
+ {
+
+ int start = 0;
+ int end = str.length() - 1;
+
+ while (start < end && isWhiteSpace(str[start]))
+ start++;
+
+ while (start <= end && isWhiteSpace(str[end]))
+ end--;
+
+ string returnStr(str, start, end+1-start);
+ return returnStr;
+ }
+
+#ifdef USES_NAMESPACE
+}
+#endif
+/*
+ * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
+ *
+ * compiler_defines.h (1 January 1999)
+ * by Tal Davidson (davidsont@bigfoot.com)
+ * This file is a part of "Artistic Style" - an indentater and reformatter
+ * of C, C++, C# and Java source files.
+ *
+ * The "Artistic Style" project, including all files needed to compile it,
+ * is free software; you can redistribute it and/or use it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program.
+ */
+
+
+#ifndef ASBEAUTIFIER_H
+#define ASBEAUTIFIER_H
+
+#include "ASResource.h"
+#include "compiler_defines.h"
+#include "ASSourceIterator.h"
+
+#include <string>
+#include <vector>
+
+
+using namespace std;
+
+namespace astyle
+ {
+
+ enum BracketMode { NONE_MODE, ATTACH_MODE, BREAK_MODE, BDAC_MODE };
+ enum BracketType { NULL_TYPE = 0,
+ DEFINITION_TYPE = 1,
+ COMMAND_TYPE = 2,
+ ARRAY_TYPE = 4,
+ SINGLE_LINE_TYPE = 8};
+
+
+ class ASBeautifier : protected ASResource
+ {
+ public:
+ ASBeautifier();
+ virtual ~ASBeautifier();
+ virtual void init(ASSourceIterator* iter); // pointer to dynamically created iterator.
+ virtual void init();
+ virtual bool hasMoreLines() const;
+ virtual string nextLine();
+ virtual string beautify(const string &line);
+ void setTabIndentation(int length = 4, bool forceTabs = false);
+ void setSpaceIndentation(int length = 4);
+ void setMaxInStatementIndentLength(int max);
+ void setMinConditionalIndentLength(int min);
+ void setClassIndent(bool state);
+ void setSwitchIndent(bool state);
+ void setCaseIndent(bool state);
+ void setBracketIndent(bool state);
+ void setBlockIndent(bool state);
+ void setNamespaceIndent(bool state);
+ void setLabelIndent(bool state);
+ void setCStyle();
+ void setJavaStyle();
+ void setEmptyLineFill(bool state);
+ void setPreprocessorIndent(bool state);
+
+
+ protected:
+ int getNextProgramCharDistance(const string &line, int i);
+ bool isLegalNameChar(char ch) const;
+ bool isWhiteSpace(char ch) const;
+ const string *findHeader(const string &line, int i,
+ const vector<const string*> &possibleHeaders,
+ bool checkBoundry = true);
+ string trim(const string &str);
+ int indexOf(vector<const string*> &container, const string *element);
+
+ private:
+ ASBeautifier(const ASBeautifier &copy);
+ void operator=(ASBeautifier&); // not to be implemented
+
+ void initStatic();
+ void registerInStatementIndent(const string &line, int i, int spaceTabCount,
+ int minIndent, bool updateParenStack);
+ string preLineWS(int spaceTabCount, int tabCount);
+
+ static vector<const string*> headers;
+ static vector<const string*> nonParenHeaders;
+ static vector<const string*> preprocessorHeaders;
+ static vector<const string*> preBlockStatements;
+ static vector<const string*> assignmentOperators;
+ static vector<const string*> nonAssignmentOperators;
+
+ static bool calledInitStatic;
+
+ ASSourceIterator *sourceIterator;
+ vector<ASBeautifier*> *waitingBeautifierStack;
+ vector<ASBeautifier*> *activeBeautifierStack;
+ vector<int> *waitingBeautifierStackLengthStack;
+ vector<int> *activeBeautifierStackLengthStack;
+ vector<const string*> *headerStack;
+ vector< vector<const string*>* > *tempStacks;
+ vector<int> *blockParenDepthStack;
+ vector<bool> *blockStatementStack;
+ vector<bool> *parenStatementStack;
+ vector<int> *inStatementIndentStack;
+ vector<int> *inStatementIndentStackSizeStack;
+ vector<int> *parenIndentStack;
+ vector<bool> *bracketBlockStateStack;
+ string indentString;
+ const string *currentHeader;
+ const string *previousLastLineHeader;
+ const string *immediatelyPreviousAssignmentOp;
+ const string *probationHeader;
+ bool isInQuote;
+ bool isInComment;
+ bool isInCase;
+ bool isInQuestion;
+ bool isInStatement;
+ bool isInHeader;
+ bool isCStyle;
+ bool isInOperator;
+ bool isInTemplate;
+ bool isInConst;
+ bool isInDefine;
+ bool isInDefineDefinition;
+ bool classIndent;
+ bool isInClassHeader;
+ bool isInClassHeaderTab;
+ bool switchIndent;
+ bool caseIndent;
+ bool namespaceIndent;
+ bool bracketIndent;
+ bool blockIndent;
+ bool labelIndent;
+ bool preprocessorIndent;
+ bool isInConditional;
+ bool isMinimalConditinalIndentSet;
+ bool shouldForceTabIndentation;
+ int minConditionalIndent;
+ int parenDepth;
+ int indentLength;
+ int blockTabCount;
+ unsigned int leadingWhiteSpaces;
+ int maxInStatementIndent;
+ int templateDepth;
+ char quoteChar;
+ char prevNonSpaceCh;
+ char currentNonSpaceCh;
+ char currentNonLegalCh;
+ char prevNonLegalCh;
+ int prevFinalLineSpaceTabCount;
+ int prevFinalLineTabCount;
+ bool emptyLineFill;
+ bool backslashEndsPrevLine;
+ int defineTabCount;
+ };
+}
+
+#endif
+/*
+ * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
+ *
+ * ASFormatter.cpp
+ * by Tal Davidson (davidsont@bigfoot.com)
+ * This file is a part of "Artistic Style" - an indentater and reformatter
+ * of C, C++, C# and Java source files.
+ *
+ * The "Artistic Style" project, including all files needed to compile it,
+ * is free software; you can redistribute it and/or use it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program.
+ *
+ *
+ * Patches:
+ * 26 November 1998 - Richard Bullington -
+ * A correction of line-breaking in headers following '}',
+
+ * was created using a variation of a patch by Richard Bullington.
+ * 08 May 2004
+ * applied ASFormatter450670.patch.bz2, ASFormatter.cpp.patch.bz2,
+ * patch1_ssvb_patch.tar.gz
+ */
+
+#include "compiler_defines.h"
+#include "ASFormatter.h"
+
+
+#include <string>
+#include <cctype>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+
+
+#define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); }
+#define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container) ; }
+#define IS_A(a,b) ( ((a) & (b)) == (b))
+#ifdef USES_NAMESPACE
+using namespace std;
+
+namespace astyle
+ {
+#endif
+
+
+ bool ASFormatter::calledInitStatic = false;
+ vector<const string*> ASFormatter::headers;
+ vector<const string*> ASFormatter::nonParenHeaders;
+ vector<const string*> ASFormatter::preprocessorHeaders;
+ vector<const string*> ASFormatter::preDefinitionHeaders;
+ vector<const string*> ASFormatter::preCommandHeaders;
+ vector<const string*> ASFormatter::operators;
+ vector<const string*> 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<const string*> );
+ INIT_CONTAINER( bracketTypeStack, new vector<BracketType> );
+ bracketTypeStack->push_back(DEFINITION_TYPE);
+ INIT_CONTAINER( parenStack, new vector<int> );
+ 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<bar> or foo<bar,fig>
+ // 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<int, char>
+ || oper == &AS_BIT_AND // reference, e.g. A<int&>
+ || oper == &AS_MULT // pointer, e.g. A<int*>
+ || oper == &AS_COLON_COLON) // ::, e.g. std::string
+ {
+ continue;
+ }
+ else if (!isLegalNameChar(currentLine[i]) && !isWhiteSpace(currentLine[i]))
+ {
+ // this is not a template -> leave...
+ //
+ isInTemplate = false;
+ break;
+ }
+ }
+ }
+
+
+ // handle parenthesies
+ //
+ if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
+ {
+ parenStack->back()++;
+ }
+ 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<class A>
+ if (newHeader == &AS_TEMPLATE)
+ {
+ isInTemplate = true;
+ }
+
+ // check if the found header is non-paren header
+ isNonParenHeader = ( find(nonParenHeaders.begin(), nonParenHeaders.end(),
+ newHeader) != nonParenHeaders.end() );
+ appendSequence(*currentHeader);
+ goForward(currentHeader->length() - 1);
+ // if 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<const string*> &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 &copy); // 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<const string*> &headers, bool checkBoundry = true);
+
+ static vector<const string*> headers;
+ static vector<const string*> nonParenHeaders;
+ static vector<const string*> preprocessorHeaders;
+ static vector<const string*> preDefinitionHeaders;
+ static vector<const string*> preCommandHeaders;
+ static vector<const string*> operators;
+ static vector<const string*> assignmentOperators;
+ static bool calledInitStatic;
+
+ ASSourceIterator *sourceIterator;
+ vector<const string*> *preBracketHeaderStack;
+ vector<BracketType> *bracketTypeStack;
+ vector<int> *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<class A>) and template usage (e.g. F<int>).
+ 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 <string>
+
+
+#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 <iostream>
+#include <fstream>
+#include <string>
+
+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 <string>
+#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 <iostream>
+#include <fstream>
+#include <string>
+
+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 " <<c<< endl;
+ }
+ }
+
+ if (optind < argc) //still args left
+ {
+ if (inputFileNames.empty()) {
+ while (optind < argc){
+ inputFileNames.push_back(string(argv[optind++]));
+ }
+ }
+ } else if (inputFileNames.empty()) {
+ inputFileNames.push_back("");
+ }
+ if (printDebugInfo() && configFileRead) {
+ cout << "Configuration file \""<<configFilePath<<"\" was read.\n";
+ }
+}
+
+CmdLineOptions::~CmdLineOptions(){
+}
+
+const string &CmdLineOptions::getSingleOutFilename()
+ {
+ if (!inputFileNames.empty() && !outDirectory.empty()) {
+ if (outFilename.empty()) {
+ outFilename = outDirectory;
+ int delim = getSingleInFilename().find_last_of(Platform::pathSeparator)+1;
+ outFilename += getSingleInFilename().substr((delim>-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 <string> & 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 \""<<oldOption << "\" is DEPRECATED.";
+ cerr << " Use \""<<newOption << "\" instead.\n";
+}
+/***************************************************************************
+ cmdlineoptions.h - 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef CMDLINEOPTIONS_H
+#define CMDLINEOPTIONS_H
+
+#include <string>
+#include <map>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+
+#include "platform_fs.h"
+#include "configurationreader.h"
+#include "datadir.h"
+#include "enums.h"
+
+#ifdef _WIN32
+ #include <windows.h>
+#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 <getopt.h>
+#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 <string> & 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 <string> 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 ((i<s.length()) && !isdigit(s[i])) ;
+
+ // Zahl zusammensetzen
+ while ((i<s.length()) && isdigit(s[i])){
+ result = result *10 + (s[i]-'0');
+ ++i;
+ }
+ return ((result)? (State)result:_UNKNOWN);
+}
+
+string CodeGenerator::getIdentifier()
+{
+ --lineIndex;
+ unsigned int startPos=lineIndex;
+ char c= line[lineIndex];
+
+ while ( ( lineIndex < line.length()
+ && ( StringTools::isAlpha(c)
+ || isdigit(c))
+ || isAllowedChar(c))
+ )
+ {
+ ++lineIndex;
+ c= line[lineIndex];
+ }
+ return string(line, startPos, lineIndex - startPos);
+}
+
+string CodeGenerator::getNumber()
+{
+ --lineIndex;
+ unsigned int startPos=lineIndex;
+ char c=line[lineIndex];
+
+ while ( lineIndex < line.length() && (
+ isdigit(c)
+ // don't highlight methods applied on numbers as part of the number
+ // i.e. Ruby: 3.xxx()
+ || (c == '.' && isdigit(line[lineIndex+1]))
+ // '-' is accepted as first character
+ || (c == '-' && lineIndex == startPos)
+ || (StringTools::isAlpha(c) && line[lineIndex-1]=='0')
+ || (isxdigit(c) || c=='L' || c=='U' || c=='l' || c=='u') ))
+ {
+ ++lineIndex;
+ c= line[lineIndex];
+ }
+ return string(line,startPos, lineIndex-startPos);
+}
+
+unsigned int CodeGenerator::getLineNumber()
+{
+ return lineNumber;
+}
+
+bool CodeGenerator::readNewLine(string &newLine){
+ bool eof;
+ terminatingChar=newLine[lineIndex-1];
+ if (formattingPossible && formattingEnabled)
+ {
+ eof=!formatter->hasMoreLines();
+ 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<string> &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<string>::iterator keyStyleOpenBegin =
+ styleTagOpen.begin() + NUMBER_BUILTIN_STYLES;
+ vector<string>::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 (lineIndex<line.length()){
+ char c=line[lineIndex];
+ int charsToSkip=1;
+ // Escape Sequenz /ooo Oktal, /x000 hex, /u00xx Java unicode
+ if (isdigit(c) ){
+ // \0 abfangen
+ while ( isdigit(line[lineIndex+charsToSkip]) && charsToSkip<4) {
+ ++charsToSkip;
+ }
+ } else if (tolower(c)=='x'){
+ charsToSkip=langInfo.isJava() ? 4 : 3;
+ } else if (tolower(c)=='u'){
+ charsToSkip=5;
+ }
+ while (charsToSkip-- && lineIndex++<line.length()){
+ *out <<maskCharacter(line[lineIndex-1]);
+ }
+ }
+}
+
+
+void CodeGenerator::processWsState()
+{
+ if (!maskWs) {
+ wsBuffer += token;
+ token.clear();
+ return;
+ }
+ flushWs();
+ int cntWs=0;
+ lineIndex--;
+
+ while (isspace(line[lineIndex]) ) {
+ ++cntWs;
+ ++lineIndex;
+ }
+
+ if (cntWs>1) {
+ unsigned int styleID=getStyleID(currentState, currentKeywordClass);
+ if (excludeWs && styleID!=_UNKNOWN) {
+ *out << styleTagClose[styleID];
+ }
+ *out << maskWsBegin;
+ for (int i=0; i<cntWs; i++){
+ *out << spacer;
+ }
+ *out << maskWsEnd;
+ if (excludeWs && styleID!=_UNKNOWN){
+ *out << styleTagOpen[styleID];
+ }
+ } else {
+ *out << token;
+ }
+ token.clear();
+}
+
+void CodeGenerator::flushWs(){
+ *out<<wsBuffer;
+ wsBuffer.clear();
+}
+
+bool CodeGenerator::isFirstNonWsChar() {
+ unsigned int i=lineIndex-1;
+ while (i--){
+ if (!isspace(line[i])){
+ return false;
+ }
+ }
+ return true;
+}
+
+string CodeGenerator::getNewLine(){
+ return newLineTag;
+}
+
+void CodeGenerator::insertLineNumber(bool insertNewLine) {
+ if (insertNewLine){
+ wsBuffer += getNewLine();
+ }
+ if (showLineNumbers) {
+ ostringstream os;
+ ostringstream numberPrefix;
+ if (lineNumberFillZeroes) {
+ os.fill('0');
+ }
+ os <<setw(LINE_NUMBER_WIDTH) << right << lineNumber;
+
+ numberPrefix << styleTagOpen[LINENUMBER]
+ << maskString(os.str()) << spacer
+ << styleTagClose[LINENUMBER];
+
+ wsBuffer += numberPrefix.str();
+ }
+}
+
+unsigned int CodeGenerator::getLineIndex(){
+ return lineIndex;
+}
+
+bool CodeGenerator::printExternalStyle(const string &outFile)
+{
+ if (!includeStyleDef && langInfo.getSyntaxHighlight()) {
+ ofstream cssOutFile(outFile.c_str());
+ if (cssOutFile) {
+ cssOutFile << styleCommentOpen
+ <<" Style definition file generated by highlight "
+ << HIGHLIGHT_VERSION << ", " << HIGHLIGHT_URL
+ << " " << styleCommentClose << "\n";
+ cssOutFile << "\n"<<styleCommentOpen<<" Highlighting theme definition: "
+ << styleCommentClose << "\n\n"
+ << getStyleDefinition()
+ << "\n";
+ cssOutFile << readUserStyleDef();
+ cssOutFile.close();
+ } else {
+ return false;
+ }
+ }
+ return true;
+}
+
+string CodeGenerator::readUserStyleDef(){
+ ostringstream ostr;
+ if (!styleInputPath.empty()){
+ ifstream userStyleDef(styleInputPath.c_str());
+ if (userStyleDef) {
+ ostr << "\n"<<styleCommentOpen<<" Content of "<<styleInputPath<<": "<<styleCommentClose<<"\n";
+ string line;
+ while (getline(userStyleDef, line)){
+ ostr << line << "\n";
+ }
+ userStyleDef.close();
+ } else {
+ ostr << styleCommentOpen<<" ERROR: Could not include "
+ << styleInputPath
+ << "."<<styleCommentClose<<"\n";
+ }
+ }
+ return ostr.str();
+}
+
+bool CodeGenerator::checkSpecialCmd(){
+ bool insertNL = (lineIndex-token.length());
+ cerr << "token: "<<token<< " index"<< lineIndex << " "<<line [ lineIndex ]<<endl;
+
+ if (line [ lineIndex ]=='!'){
+ // find cmd
+ size_t cmdPos1 = line.find('@', lineIndex+1);
+
+ cerr << "cmdPos"<<cmdPos1<<endl;
+ if(cmdPos1==string::npos) return false;
+ size_t cmdPos2=cmdPos1+1;
+ while (cmdPos2 < line.length() && StringTools::isAlpha(line[cmdPos2])) cmdPos2++;
+ cerr << "cmdPos2"<<cmdPos2<<endl;
+ cerr << line.substr(cmdPos1, cmdPos2)<<endl;
+
+ // hide comment line
+ token.clear();
+ lineIndex=line.length();
+ getInputChar(); lineNumber--;
+ if (insertNL) { lineNumber++;insertLineNumber();};
+ // end hide
+
+ return true;
+ }
+
+ return false;
+}
+
+}
+/***************************************************************************
+ codeparser.h - description
+ -------------------
+ begin : Die Jul 9 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 CODEPARSER_H
+#define CODEPARSER_H
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <iomanip>
+#include <cctype>
+
+#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.<br>
+ Deriving classes have to define the output format.<br>
+ 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<string> & 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 <string> 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<string> &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 <string>
+#include <sstream>
+#include <map>
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+#include "stringtools.h"
+
+using namespace std;
+
+/** Maps parameter keys to values*/
+typedef map<string, string> ParameterMap;
+
+
+/** \brief Class to handle ASCII config files
+
+ Configuration file format:<br>
+ $ParamName=ParamValue<br>
+ ParamValue may be splittet over multiple lines<br>
+ ParamName is not case sensitive<br>
+ 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<string> &getParameterNames();
+
+ private:
+ ParameterMap parameterMap;
+ bool fileFound;
+ vector<string> 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 <string>
+#include <fstream>
+#include <iostream>
+//#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<string> paramNames=styleConfig.getParameterNames();
+
+ //collect keyword classes, save corresponding style definition
+ for (unsigned int i=0;i<paramNames.size();i++){
+ paramVal=paramNames[i];
+ if (paramVal.find("kw_class") != string::npos){
+ keywordStyles.insert(make_pair(StringTools::getParantheseVal(paramVal),
+ new ElementStyle(styleConfig.getParameter(paramVal))));
+ }
+ }
+
+ fileFound = true;
+ }
+ else {
+ fileFound = false;
+ }
+ return fileFound;
+}
+
+DocumentStyle::~DocumentStyle()
+{
+ for(KSIterator iter = keywordStyles.begin(); iter != keywordStyles.end(); iter++){
+ delete (*iter).second; //remove ElementStyle*
+ }
+}
+
+string& DocumentStyle::getFontSize()
+ {
+ return fontsize;
+ }
+StyleColour& DocumentStyle::getBgColour()
+ {
+ return bgColour;
+ }
+ElementStyle& DocumentStyle::getDefaultStyle()
+ {
+ return defaultElem;
+ }
+ElementStyle& DocumentStyle::getCommentStyle()
+ {
+ return comment;
+ }
+ElementStyle& DocumentStyle::getSingleLineCommentStyle()
+ {
+ return slcomment;
+ }
+
+
+ElementStyle& DocumentStyle::getStringStyle()
+ {
+ return str;
+ }
+ElementStyle& DocumentStyle::getDirectiveStringStyle()
+ {
+ return dstr;
+ }
+ElementStyle& DocumentStyle::getEscapeCharStyle()
+ {
+ return escapeChar;
+ }
+ElementStyle& DocumentStyle::getNumberStyle()
+ {
+ return number;
+ }
+ElementStyle& DocumentStyle::getDirectiveStyle()
+ {
+ return directive;
+ }
+ElementStyle& DocumentStyle::getLineStyle()
+ {
+ return line;
+ }
+ElementStyle& DocumentStyle::getSymbolStyle()
+ {
+ return symbol;
+ }
+bool DocumentStyle::found () const
+ {
+ return fileFound;
+ }
+ElementStyle& DocumentStyle::getKeywordStyle(const string &className){
+ if (!keywordStyles.count(className)) return defaultElem;
+ return *keywordStyles[className];
+}
+
+vector <string> DocumentStyle::getClassNames(){
+ vector <string> 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 <string>
+#include <iostream>
+#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 <string, ElementStyle*> 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 <string> 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 <sstream>
+
+#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 <andre.simon1@gmx.de>, (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 <stdio.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#include <cstdio>
+#include <cstring>
+//#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 <stdlib.h>
+#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 <string.h>
+#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 <features.h>, but
+ that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
+ not defined, include <ctype.h>, which will pull in <features.h> 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 <ctype.h>
+#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 <iostream>
+#include <fstream>
+#include <string>
+
+/**\ 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 << "."<<elemName<<"\t{ color:#"
+ << (elem.getColour().getHexRedValue())
+ << (elem.getColour().getHexGreenValue())
+ << (elem.getColour().getHexBlueValue() )
+ << ( elem.isBold() ?"; font-weight:bold" :"" )
+ << ( elem.isItalic() ?"; font-style:italic" :"" )
+ << ( elem.isUnderline() ?"; text-decoration:underline" :"" )
+ << "; }\n" ;
+ return s.str();
+}
+
+string HtmlGenerator::getOpenTag(const string& styleName ){
+ return "<span class=\""+styleName+"\">";
+}
+
+HtmlGenerator::HtmlGenerator (
+ const string &cssStyle,
+ const string &enc,
+ bool omitEnc,
+ bool withAnchors)
+ : CodeGenerator( cssStyle),
+ brTag("<br>"),
+ hrTag("<hr>"),
+ idAttr("name"),
+ fileSuffix(".html"),
+ encoding(enc),
+ omitEncoding(omitEnc),
+ HTML_FOOTER(
+ "\n</body>\n</html>\n<!--HTML generated by highlight "
+ HIGHLIGHT_VERSION
+ ", "
+ HIGHLIGHT_URL
+ "-->\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<NUMBER_BUILTIN_STYLES; i++) {
+ styleTagClose.push_back("</span>");
+ }
+
+ /*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-<head> einfuegen
+ {
+ os << "<style type=\"text/css\">\n";
+ os << "<!--\n";
+ os << getStyleDefinition();
+ os << CodeGenerator::readUserStyleDef();
+ os << "//-->\n";
+ os << "</style>" << endl;
+ }
+ else //Referenz auf CSS-Datei einfuegen
+ {
+ os << "<link rel=\"stylesheet\" type=\"text/css\" href=\""
+ << getStyleOutputPath()
+ << "\""
+ << ">\n";
+ }
+ }
+ os << "</head>\n<body class=\"hl\">\n<pre class=\"hl\">";
+ return os.str();
+}
+
+string HtmlGenerator::getFooter()
+{
+ return "</pre>" + HTML_FOOTER;
+}
+
+
+void HtmlGenerator::printBody()
+{
+ processRootState();
+}
+
+
+
+string HtmlGenerator::maskCharacter(unsigned char c)
+{
+ switch (c) {
+ case '<' :
+ return "&lt;";
+ break;
+ case '>' :
+ return "&gt;";
+ break;
+ case '&' :
+ return "&amp;";
+ break;
+ case '\"' :
+ return "&quot;";
+ break;
+
+ case '@' :
+ return "&#64;";
+ 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 << "<a "
+ << idAttr
+ << "=\"l_"
+ << lineNumber
+ << "\">";
+ }
+ ostringstream os;
+ if (lineNumberFillZeroes) os.fill('0');
+ os <<setw(LINE_NUMBER_WIDTH)<<right<< lineNumber;
+ numberPrefix<< styleTagOpen[LINENUMBER]
+ << os.str()
+ << spacer
+ << styleTagClose[LINENUMBER];
+
+ if (attachAnchors) {
+ numberPrefix << "</a>";
+ }
+
+ wsBuffer += numberPrefix.str();
+ }
+}
+
+string HtmlGenerator::getHeaderStart(const string &title){
+ ostringstream header;
+ header<< "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">"
+ << "\n<html>\n<head>\n";
+ if (!omitEncoding){
+ header << "<meta http-equiv=\"content-type\" content=\"text/html; charset="<<encoding<<"\">\n";
+ }
+ header << "<title>" << title <<"</title>\n";
+ return header.str();
+}
+
+bool HtmlGenerator::printIndexFile(const vector<string> &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 << "</head>\n<body>\n<h1> Source Index</h1>\n"
+ << hrTag
+ << "\n<ul>\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 << "</ul>\n<h2>";
+ indexfile << newInFilePath;
+ indexfile << "</h2>\n<ul>\n";
+ inFilePath=newInFilePath;
+ }
+ inFileName = (fileList[i]).substr(pos+1);
+ indexfile << "<li><a href=\"" << inFileName << suffix << "\">";
+ indexfile << inFileName << suffix <<"</a></li>\n";
+ }
+
+ indexfile << "</ul>\n"
+ << hrTag << brTag
+ << "<small>Generated by highlight "
+ << HIGHLIGHT_VERSION
+ << ", <a href=\"" << HIGHLIGHT_URL << "\" target=\"new\">"
+ << HIGHLIGHT_URL << "</a></small>";
+ 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 "</span>";
+}
+
+}
+/***************************************************************************
+ 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 <fstream>
+#include <iostream>
+#include <string>
+#include <sstream>
+
+#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<string> & 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 << " "<<delimPrefix <<" " << stateBegin;
+ symbolStream <<" "<< delimSuffix<<" "<< stateEnd;
+ delimiterPrefixes.insert(make_pair(delimPrefix, classID));
+ };
+}
+
+bool LanguageDefinition::getFlag( string& paramValue){
+ return (StringTools::lowerCase(paramValue)=="true");
+}
+
+unsigned char LanguageDefinition::getSymbol(const string& paramValue){
+ istringstream valueStream(paramValue);
+ unsigned char symbol;
+ valueStream >> 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<keywordClasses.size() && !found){
+ found= (newClassName==keywordClasses[newClassID++]);
+ }
+ if (!found){
+ newClassID++;
+ keywordClasses.push_back(newClassName);
+ }
+ return newClassID;
+}
+
+unsigned int LanguageDefinition::getDelimPrefixClassID(const string& prefix){
+ if (delimiterPrefixes.count(prefix)){
+ return delimiterPrefixes[prefix];
+ }
+ return 0;
+}
+
+bool LanguageDefinition::load(const string& langDefPath, bool clear)
+{
+ if (clear) reset();
+
+ ConfigurationReader langDef(langDefPath);
+ if (langDef.found())
+ {
+ currentPath=langDefPath;
+ disableHighlighting=false;
+ string token;
+ stringstream symbolStrStream;
+
+ //Stringstream zum Einlesen der Token:
+ istringstream valueStream;
+
+ addDelimiterSymbol(symbolStrStream, ML_COMMENT_BEGIN, ML_COMMENT_END,
+ langDef.getParameter("ml_comment"));
+
+ addSimpleSymbol(symbolStrStream, SL_COMMENT,
+ langDef.getParameter("sl_comment"));
+
+ addSimpleSymbol(symbolStrStream, ESC_CHAR,
+ langDef.getParameter("escchar"));
+
+ addSimpleSymbol(symbolStrStream, DIRECTIVE_LINE,
+ langDef.getParameter("directive"));
+
+ addSimpleSymbol(symbolStrStream, DIRECTIVE_LINE_END,
+ langDef.getParameter("directiveend"));
+
+ addSimpleSymbol(symbolStrStream, STRING,
+ langDef.getParameter("stringdelimiters"));
+
+ ignoreCase=getFlag(langDef.getParameter("ignorecase"));
+ allowNestedComments=getFlag(langDef.getParameter("allownestedcomments"));
+ vhdl_mode=getFlag(langDef.getParameter("vhdl_mode"));
+ java_mode=getFlag(langDef.getParameter("java_mode"));
+ disableHighlighting=getFlag(langDef.getParameter("disablehighlighting"));
+ fullLineComment=getFlag(langDef.getParameter("fl_comment"));
+ reformatCode=getFlag(langDef.getParameter("reformatting"));
+ rawStringPrefix=getSymbol(langDef.getParameter("rawstringprefix"));
+ continuationChar=getSymbol(langDef.getParameter("continuationsymbol"));
+ allowExtEscape=getFlag(langDef.getParameter("allowextescape"));
+
+ string paramName, className, classValue;
+ vector<string> paramNames=langDef.getParameterNames();
+ for (unsigned int i=0;i<paramNames.size();i++){
+ paramName=paramNames[i];
+ className=StringTools::getParantheseVal(paramName);
+ classValue=langDef.getParameter(paramName);
+ if (paramName.find("kw_list") != string::npos ){
+ addKeywords(classValue, generateNewKWClass(className));
+ }
+ if (paramName.find("kw_prefix") != string::npos){
+ prefixes.insert(make_pair(classValue[0], generateNewKWClass(className)));
+ }
+ if (paramName.find("kw_delim") != string::npos ){
+ addDelimiterSymbol(symbolStrStream, KEYWORD_BEGIN, KEYWORD_END,
+ classValue, generateNewKWClass(className));
+ }
+ if (paramName.find("tag_delim") != string::npos ){
+ addDelimiterSymbol(symbolStrStream, TAG_BEGIN, TAG_END,
+ classValue, generateNewKWClass(className));
+ }
+ }
+
+ // zuletzt einlesen, um Probleme mit Delimitern, die Zeichen der
+ // Symbolliste enthalten, zu vermeiden
+ addSimpleSymbol(symbolStrStream, SYMBOL, langDef.getParameter("symbols"));
+
+ valueStream.str(langDef.getParameter("allowedchars"));
+ while (valueStream >> 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<string>&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 <string>
+#include <map>
+#include <iostream>
+#include <fstream>
+#include <iterator>
+#include <sstream>
+
+#include "configurationreader.h"
+//#include "stringtools.h"
+#include "platform_fs.h"
+#include "enums.h"
+
+
+namespace highlight {
+
+/** maps keywords and the corresponding class IDs*/
+typedef map <string, int> KeywordMap;
+
+/** maps keyword prefixes and the corresponding class IDs*/
+typedef map <unsigned char, int> 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<string>& 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 <string> 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<NUMBER_BUILTIN_STYLES; i++){
+ styleTagClose.push_back( "}");
+ }
+
+ // avoid "Underfull \hbox (badness 10000)" warnings
+ newLineTag = "\\\\\n";
+ longLineTag = "\\hspace*{\\fill}" + newLineTag;
+
+ spacer = "\\ ";
+
+ maskWs=true;
+ maskWsBegin = "\\hlstd{";
+ maskWsEnd = "}";
+
+ excludeWs=true;
+
+ styleCommentOpen="%";
+}
+
+LatexGenerator::LatexGenerator()
+{}
+LatexGenerator::~LatexGenerator()
+{}
+
+string LatexGenerator::formatStyleAttributes(const string & elemName,
+ const ElementStyle &elem)
+{
+ ostringstream s;
+ s << "\\newcommand{\\hl"
+ << elemName
+ << "}[1]{\\textcolor[rgb]{"
+ << elem.getColour().getLatexRedValue() << ","
+ << elem.getColour().getLatexGreenValue() << ","
+ << elem.getColour().getLatexBlueValue()
+ << "}{";
+
+ if (elem.isBold())
+ s << "\\bf{";
+ if (elem.isItalic())
+ s << "\\it{";
+
+ s <<"#1";
+
+ if (elem.isBold())
+ s << "}";
+ if (elem.isItalic())
+ s << "}";
+
+ s <<"}}\n";
+ return s.str();
+}
+
+void LatexGenerator::printBody()
+{
+ *out << "\\noindent\n"
+ << "\\ttfamily\n";
+
+ processRootState();
+
+ *out << "\\mbox{}\n"
+ << "\n\\normalfont\n";
+}
+
+string LatexGenerator::getHeader(const string & title)
+{
+ ostringstream os;
+ os << "\\documentclass{article}\n"
+ << "\\usepackage{color}\n"
+ << "\\usepackage{alltt}\n";
+
+ if (langInfo.getSyntaxHighlight()) {
+ if (includeStyleDef) {
+ os << "\n"<<getStyleDefinition();
+ os << CodeGenerator::readUserStyleDef();
+ } else {
+ os << "\n\\input {"
+ << getStyleOutputPath()
+ << "}\n";
+ }
+ }
+
+ os << "\n\\title{" << title << "}\n"
+ << "\\begin{document}\n"
+ << "\\pagecolor{bgcolor}\n";
+ return os.str();
+}
+
+string LatexGenerator::getFooter()
+{
+ ostringstream os;
+ os << "\\end {document}\n"
+ << "(* LaTeX generated by highlight "
+ << HIGHLIGHT_VERSION
+ << ", "
+ << HIGHLIGHT_URL
+ << " *)\n";
+ return os.str();
+}
+
+string LatexGenerator::getNewLine(){
+ return (showLineNumbers)? newLineTag:longLineTag;
+}
+
+string LatexGenerator::maskCharacter(unsigned char c)
+{
+ switch (c)
+ {
+ case '<' :
+ return "$<$";
+ break;
+ case '>' :
+ 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 <string>
+#include <iostream>
+#include <sstream>
+
+#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 <andre.simon1@gmx.de>"
+ << "\n\n Artistic Style Classes (1.15.3)"
+ << "\n Copyright (C) 1998-2002 Tal Davidson <davidsont@bigfoot.com>"
+ << "\n\n Dirstream Classes (0.4)"
+ << "\n Copyright (C) 2002-2004 Benjamin Kaufmann <hume@c-plusplus.de>"
+ << "\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: \"" <<HL_DATA_DIR<< "\" )\n";
+ #endif
+}
+
+void HighlightApp::printBadInstallationInfo()
+{
+ cerr << "highlight: Data directory not found. Bad installation or wrong "
+ << OPT_DATADIR << " parameter."
+ << "\n\nCopy the highlight files into one of the directories listed "
+ << "in INSTALL.\nYou may also set the data directory with "
+ << OPT_DATADIR << " and " << OPT_ADDDATADIR << ".\n";
+}
+
+bool HighlightApp::listInstalledFiles(bool showThemes)
+{
+ vector <string> 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 << " "<<temp.substr(0, temp.length()- suffixLength) << endl;
+ }
+ cout <<"\n Use name of the desired "
+ << ((showThemes)?"theme":"language")
+ << " with the --"
+ << ((showThemes)? OPT_STYLE : OPT_SYNTAX)
+ << " option.\n" << endl;
+ return true;
+}
+
+void HighlightApp::printDebugInfo(highlight::LanguageDefinition &lang,
+ const string & langDefPath)
+{
+ cerr << "\nLoading language definition: " << langDefPath;
+ cerr << "\n\nSYMBOLS: "
+ << lang.getSymbolString();
+ cerr << "\n\nKEYWORDS: ";
+ highlight::KeywordMap::iterator it;
+ highlight::KeywordMap keys=lang.getKeywords();
+ cerr << "\n\nID Keyword \n";
+ for (it=keys.begin(); it!=keys.end();it++){
+ cerr << it->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<config.getParameterNames().size();i++){
+ paramName = config.getParameterNames()[i];
+ values.str(config.getParameter(paramName)) ;
+ while (values >> 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<numProgressItems)?"#":" ");
+ }
+ cout<< "] " <<setw(3)<<p<<"%, "<<count << " / " << total << " " <<flush;
+ if (p==100) {
+ cout << endl;
+ }
+}
+
+void HighlightApp::printCurrentAction(const string&outfilePath,
+ int total, int count, int countWidth){
+ cout << "Writing file "
+ << setw(countWidth)<< count
+ << " of "
+ << total
+ << ": "
+ << outfilePath
+ << "\n";
+}
+
+void HighlightApp::printIOErrorReport(unsigned int numberErrorFiles,
+ vector<string> & fileList,
+ const string &action){
+ cerr << "highlight: Could not "
+ << action
+ << " file"
+ << ((numberErrorFiles>1)?"s":"")<<":\n";
+ copy (fileList.begin(), fileList.end(), ostream_iterator<string>(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 <string> 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<string> 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 <andre.simon1@gmx.de>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef HIGHLIGHT_APP
+#define HIGHLIGHT_APP
+
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <map>
+#include <iomanip>
+#include <cassert>
+
+#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<string, string> 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<string> & 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<string> &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 <andre.simon1@gmx.de>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "platform_fs.h"
+#include "./dirstream0.4/dirstream.h"
+
+#include <iostream>
+
+using namespace std;
+
+namespace Platform {
+
+#ifdef _WIN32
+ #include <windows.h>
+
+ 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<string> &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 " <<entry<<"\n";
+ }
+ }
+ return !(fileList.empty());
+}
+
+}
+
+//
+// C++ Interface: platform_fs
+//
+// Description:
+//
+//
+// Author: André Simon <andre.simon1@gmx.de>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef PLATFORM_FS__H__INCLUDED
+#define PLATFORM_FS__H__INCLUDED
+
+#include <string>
+#include <iostream>
+#include <vector>
+
+#ifdef USE_FN_MATCH
+ #include <fnmatch.h>
+#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<std::string> &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: "<<pattern_<< " entry: "<<e.c_str()<< " Res fn: " <<::fnmatch(pattern_, e.c_str(), FNM_PATHNAME)<< " \n";
+ return ! ::fnmatch(pattern_, e.c_str(), flags_);
+ }
+ private:
+ const char* pattern_;
+ int flags_;
+ };
+#endif
+}
+#endif
+/***************************************************************************
+ 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. *
+ * *
+ ***************************************************************************/
+
+#include "preformatter.h"
+
+namespace highlight {
+
+PreFormatter::PreFormatter(bool wrap, bool replTabs):
+ maxLineLength(80),
+ index(0),
+ numberSpaces(0),
+ wsPrefixLength(string::npos),
+ hasMore(false),
+ indentAfterOpenBraces(true),
+ redefineWsPrefix(false),
+ wrapLines(wrap),
+ replaceTabs(replTabs)
+{
+}
+
+PreFormatter::PreFormatter():
+ maxLineLength(80),
+ index(0),
+ numberSpaces(0),
+ wsPrefixLength(string::npos),
+ hasMore(false),
+ indentAfterOpenBraces(true),
+ redefineWsPrefix(false),
+ wrapLines(false),
+ replaceTabs(false)
+{
+}
+
+PreFormatter::~PreFormatter()
+{
+}
+
+bool PreFormatter::hasMoreLines(){
+ return hasMore;
+}
+
+bool PreFormatter::indentCode(){
+ return indentAfterOpenBraces;
+}
+
+void PreFormatter::setLine(const std::string newLine){
+
+ line=newLine;
+
+ if (replaceTabs && numberSpaces) {
+ size_t tabPos=line.find('\t');
+ while (tabPos!=string::npos){
+ line.replace(tabPos , 1, numberSpaces - (tabPos % numberSpaces) , ' ');
+ tabPos = line.find('\t', tabPos+1);
+ }
+ }
+
+ if (wrapLines){
+ wsPrefix.clear();
+ index=0;
+ wsPrefixLength=string::npos;
+ hasMore=true;
+ redefineWsPrefix=false;
+ }
+}
+
+std::string PreFormatter::getNextLine(){
+
+ if (!wrapLines){
+ hasMore = false;
+ return line;
+ }
+
+ if (!index && line.length() > 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 <string>
+#include <iostream>
+
+#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"<<col.getColour().getRTFGreenValue()
+ << "\\blue"<<col.getColour().getRTFBlueValue()
+ << ";";
+
+ return s.str();
+}
+
+string RtfGenerator::getOpenTag(int styleNumber,const ElementStyle & elem)
+{
+ ostringstream s;
+ s << "{\\cf"<<(styleNumber+1)<<"{";
+ if (elem.isBold()) s << "\\b ";
+ if (elem.isItalic()) s << "\\i ";
+ if (elem.isUnderline()) s << "\\ul ";
+ return s.str();
+}
+
+string RtfGenerator::getCloseTag(const ElementStyle &elem)
+{
+ ostringstream s;
+ if (elem.isBold()) s << "\\b0 ";
+ if (elem.isItalic()) s << "\\i0 ";
+ if (elem.isUnderline()) s << "\\ul0 ";
+ s << "}}";
+ return s.str();
+}
+
+RtfGenerator::RtfGenerator(const string &colourTheme)
+ : CodeGenerator( colourTheme)
+{
+ styleTagOpen.push_back(getOpenTag(STANDARD, docStyle.getDefaultStyle()));
+ styleTagOpen.push_back(getOpenTag(STRING, docStyle.getStringStyle()));
+ styleTagOpen.push_back(getOpenTag(NUMBER, docStyle.getNumberStyle()));
+ styleTagOpen.push_back(getOpenTag(SL_COMMENT, docStyle.getSingleLineCommentStyle()));
+ styleTagOpen.push_back(getOpenTag(ML_COMMENT_BEGIN,docStyle.getCommentStyle()));
+ styleTagOpen.push_back(getOpenTag(ESC_CHAR, docStyle.getEscapeCharStyle()));
+ styleTagOpen.push_back(getOpenTag(DIRECTIVE_LINE, docStyle.getDirectiveStyle()));
+ styleTagOpen.push_back(getOpenTag(DIRECTIVE_STRING, docStyle.getDirectiveStringStyle()));
+ styleTagOpen.push_back(getOpenTag(LINENUMBER, docStyle.getLineStyle()));
+ styleTagOpen.push_back(getOpenTag(SYMBOL, docStyle.getSymbolStyle()));
+
+ styleTagClose.push_back(getCloseTag(docStyle.getDefaultStyle()));
+ styleTagClose.push_back(getCloseTag(docStyle.getStringStyle()));
+ styleTagClose.push_back(getCloseTag(docStyle.getNumberStyle()));
+ styleTagClose.push_back(getCloseTag(docStyle.getSingleLineCommentStyle()));
+ styleTagClose.push_back(getCloseTag(docStyle.getCommentStyle()));
+ styleTagClose.push_back(getCloseTag(docStyle.getEscapeCharStyle()));
+ styleTagClose.push_back(getCloseTag(docStyle.getDirectiveStyle()));
+ styleTagClose.push_back(getCloseTag(docStyle.getDirectiveStringStyle()));
+ styleTagClose.push_back(getCloseTag(docStyle.getLineStyle()));
+ styleTagClose.push_back(getCloseTag(docStyle.getSymbolStyle()));
+
+ newLineTag = "\\par\\pard\n";
+ spacer = " ";
+}
+
+RtfGenerator::RtfGenerator()
+{}
+RtfGenerator::~RtfGenerator()
+{}
+
+string RtfGenerator::getHeader(const string & title)
+{
+ return string();
+}
+
+void RtfGenerator::printBody()
+{
+ *out << "{\\rtf1\\ansi\\uc0 \\deff1"
+ << "{\\fonttbl{\\f1\\fmodern\\fprq1\\fcharset0 Courier;}}"
+ << "{\\colortbl;";
+
+ *out << formatStyleAttributes(docStyle.getDefaultStyle());
+
+ *out << formatStyleAttributes(docStyle.getStringStyle());
+ *out << formatStyleAttributes(docStyle.getNumberStyle());
+ *out << formatStyleAttributes(docStyle.getSingleLineCommentStyle());
+
+ *out << formatStyleAttributes(docStyle.getCommentStyle());
+ *out << formatStyleAttributes(docStyle.getEscapeCharStyle());
+ *out << formatStyleAttributes(docStyle.getDirectiveStyle());
+
+ *out << formatStyleAttributes(docStyle.getDirectiveStringStyle());
+ *out << formatStyleAttributes(docStyle.getLineStyle());
+ *out << formatStyleAttributes(docStyle.getSymbolStyle());
+
+ /* For output formats which can refer to external styles it is more safe
+ to use the colour theme's keyword class names, since the language
+ definitions (which may change during a batch conversion) do not have to define
+ all keyword classes, that are needed to highlight all input files correctly.
+ It is ok for RTF to use the language definition's class names, because RTF
+ does not refer to external styles.
+ We cannot use the theme's class names, because KSIterator returns an
+ alphabetically ordered list, which is not good because RTF is dependent
+ on the order. We access the keyword style with an ID, which is calculated
+ ignoring the alphabetic order.
+ */
+ vector<string> keywordClasses = langInfo.getKeywordClasses();
+ for (unsigned int i=0;i<keywordClasses.size();i++){
+ *out << formatStyleAttributes(docStyle.getKeywordStyle(keywordClasses[i]));
+ }
+
+ *out << "}\n{\\info }\\paperw11900\\paperh16820\\margl560\\margr560\\margt840"
+ << "\\margb840\\widowctrl\\ftnbj\\aenddoc\\formshade \\fet0\\sectd"
+ << "\\linex0\\endnhere\\plain\\f1\\fs20\n\\pard ";
+ processRootState();
+ *out << "}}"<<endl;
+}
+
+
+string RtfGenerator::getFooter()
+{
+ return string();
+}
+
+/** Gibt RTF-Code der Sonderzeichen zurueck */
+string RtfGenerator::maskCharacter(unsigned char c)
+{
+ switch (c)
+ {
+ case '}' :
+ case '{' :
+ case '\\' :
+ {
+ string m;
+ m="\\";
+ return m+=c;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ string m;
+ m="{";
+ m+=c;
+ m+="}";
+ return m;
+ }
+ break;
+ case AUML_LC:
+ return "\\'e4";
+ break;
+ case OUML_LC:
+ return "\\'f6";
+ break;
+ case UUML_LC:
+ return "\\'fc";
+ break;
+ case AUML_UC:
+ return "\\'c4";
+ break;
+ case OUML_UC:
+ return "\\'d6";
+ break;
+ case UUML_UC:
+ return "\\'dc";
+ break;
+
+ case AACUTE_LC:
+ return "\\'e1";
+ break;
+ case EACUTE_LC:
+ return "\\'e9";
+ break;
+ case OACUTE_LC:
+ return "\\'f3";
+ break;
+ case UACUTE_LC:
+ return "\\'fa";
+ break;
+
+ case AGRAVE_LC:
+ return "\\'e0";
+ break;
+ case EGRAVE_LC:
+ return "\\'e8";
+ break;
+ case OGRAVE_LC:
+ return "\\'f2";
+ break;
+ case UGRAVE_LC:
+ return "\\'f9";
+ break;
+
+ case AACUTE_UC:
+ return "\\'c1";
+ break;
+ case EACUTE_UC:
+ return "\\'c9";
+ break;
+ case OACUTE_UC:
+ return "\\'d3";
+ break;
+ case UACUTE_UC:
+ return "\\'da";
+ break;
+ case AGRAVE_UC:
+ return "\\'c0";
+ break;
+ case EGRAVE_UC:
+ return "\\'c8";
+ break;
+ case OGRAVE_UC:
+ return "\\'d2";
+ break;
+ case UGRAVE_UC:
+ return "\\'d9";
+ break;
+
+ case SZLIG:
+ return "\\'df";
+ break;
+ // skip first byte of multibyte chracters
+ /* #ifndef _WIN32
+ case 195:
+ return string("");
+ break;
+#endif*/
+
+ default :
+ {
+ string m;
+ return m += c;
+ }
+ }
+}
+
+string RtfGenerator::getMatchingOpenTag(unsigned int styleID){
+ return getOpenTag(KEYWORD+styleID,
+ docStyle.getKeywordStyle(langInfo.getKeywordClasses()[styleID]));
+}
+
+string RtfGenerator::getMatchingCloseTag(unsigned int styleID){
+ return getCloseTag(docStyle.getKeywordStyle(langInfo.getKeywordClasses()[styleID]));
+}
+
+
+}
+/***************************************************************************
+ rtfcode.h - description
+ -------------------
+ begin : Die Jul 9 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 RTFGENERATOR_H
+#define RTFGENERATOR_H
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <sstream>
+
+#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 <sstream>
+#include <iostream>
+#include <cctype>
+
+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 <string>
+
+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 <string>
+#include <sstream>
+#include <fstream>
+#include <cmath>
+#include <sstream>
+
+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<NUMBER_BUILTIN_STYLES; i++) {
+ styleTagClose.push_back( "}");
+ }
+
+ /*This makes TeX to use every par it encounters (the \\leavevmode has
+ no effect when TeX is in horizontal mode and when TeX is in vertical
+ mode, it switches it to horizontal mode).*/
+ newLineTag="\\leavevmode\\par\n";
+
+ spacer = "\\ ";
+ maskWs=true;
+ excludeWs=true;
+ maskWsBegin = "{\\hlstd";
+ maskWsEnd = "}";
+ styleCommentOpen="%";
+}
+
+TexGenerator::TexGenerator()
+{}
+TexGenerator::~TexGenerator()
+{}
+
+string TexGenerator::formatStyleAttributes(const string & elemName,const ElementStyle & elem)
+{
+ ostringstream s;
+ s << "\\def\\hl"
+ << elemName
+ << "{";
+ if (elem.isBold())
+ s << "\\bf";
+ if (elem.isItalic())
+ s << "\\it";
+ s << "\\textColor{"
+ << (elem.getColour().getTexRedValue())<<" "
+ << (elem.getColour().getTexGreenValue())<<" "
+ << (elem.getColour().getTexBlueValue())<<" 0.0}}\n";
+ return s.str();
+}
+
+string TexGenerator::getHeader(const string & title)
+{
+ ostringstream os;
+
+ if (langInfo.getSyntaxHighlight()) {
+ if (includeStyleDef) {
+ os << "\n"<<getStyleDefinition();
+ os << CodeGenerator::readUserStyleDef();
+ } else {
+ os << "\\input "
+ << getStyleOutputPath()
+ << "\n\n";
+ }
+ }
+
+ return os.str();
+}
+
+void TexGenerator::printBody()
+{
+ *out << "{\n\\tt\n";
+
+ processRootState();
+ *out << "}\n";
+}
+
+string TexGenerator::getFooter()
+{
+ ostringstream os;
+ os << "\\bye\n"
+ << "% TeX generated by Highlight "
+ << HIGHLIGHT_VERSION
+ << ", "
+ << HIGHLIGHT_URL
+ << endl;
+ return os.str();
+}
+
+string TexGenerator:: maskCharacter(unsigned char c)
+{
+ switch (c)
+ {
+ case '{':
+ case '}':
+ {
+ string m;
+ m = "$\\";
+ m += c;
+ m += "$";
+ return m;
+ }
+ break;
+ case '^':
+ return "{\\bf\\^{}}";
+ break;
+ case '_':
+ return "\\_{}";
+ break;
+ case '&':
+ case '$':
+ case '#':
+ case '%':
+ {
+ string m;
+ m = "\\";
+ m += c;
+ return m;
+ }
+ break;
+ case '\\':
+ return "$\\backslash$";
+ break;
+ case ' ':
+ return spacer;
+ break;
+ case '+':
+ case '-':
+ case '<':
+ case '>':
+ 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 <string>
+#include <iostream>
+#include <sstream>
+
+#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="<br />";
+ hrTag="<hr />";
+ idAttr="id";
+
+ HTML_FOOTER=
+ "\n</body>\n</html>\n<!--XHTML generated by highlight "
+ HIGHLIGHT_VERSION
+ ", "
+ HIGHLIGHT_URL
+ "-->\n";
+}
+
+string XHtmlGenerator::getHeaderStart(const string &title){
+ ostringstream header;
+ header << "<?xml version=\"1.0\"";
+ if (!omitEncoding) {
+ header << " encoding=\"" << encoding << "\"";
+ }
+ header << "?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\""
+ << " \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
+ << "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
+ << "<head>\n<title>" << title << "</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-<head> einfuegen
+ {
+ osPart1 << "<style type=\"text/css\">\n";
+ osPart1 << "<![CDATA[\n";
+ osPart1 << getStyleDefinition();
+ osPart1 << CodeGenerator::readUserStyleDef();
+ osPart1 << "]]>\n";
+ osPart1 << "</style>\n";
+ }
+ else //Referenz auf CSS-Datei einfuegen
+ {
+ osPart1 << "<link rel=\"stylesheet\" type=\"text/css\" href=\""
+ << getStyleOutputPath()
+ << "\""
+ << "/"
+ << ">\n";
+ }
+ }
+ osPart1 << "</head>\n<body class=\"hl\">\n<pre class=\"hl\">";
+
+ 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 = "<br />\n";
+}
+
+string XmlGenerator::getStyleDefinition()
+{
+ if (styleDefinitionCache.empty()) {
+ ostringstream os;
+ os << "\n<style>\n"
+ << "\t<bgcolor value=\""
+ << (docStyle.getBgColour().getHexRedValue())
+ << (docStyle.getBgColour().getHexGreenValue())
+ << (docStyle.getBgColour().getHexBlueValue())
+ << "\" />\n"
+ << "\t<font size=\""
+ << docStyle.getFontSize()
+ << "\" family=\"Courier\" />\n";
+
+ os << formatStyleAttributes("def", docStyle.getDefaultStyle())
+ << 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));
+ }
+ os << "</style>\n";
+ styleDefinitionCache=os.str();
+ }
+ return styleDefinitionCache;
+}
+
+
+string XmlGenerator::formatStyleAttributes(const string & elemName,
+ const ElementStyle & elem)
+{
+ ostringstream s;
+ s << "\t<class name=\""
+ << elemName
+ <<"\" color=\""
+ << (elem.getColour().getHexRedValue())
+ << (elem.getColour().getHexGreenValue())
+ << (elem.getColour().getHexBlueValue() )
+ << "\" bold=\""
+ << ( elem.isBold() ? "true" :"false" )
+ << "\" italic=\""
+ << ( elem.isItalic() ? "true" :"false" )
+ << "\" underline=\""
+ << ( elem.isUnderline() ? "true" :"false" )
+ << "\" />\n" ;
+ return s.str();
+}
+
+
+XmlGenerator::XmlGenerator()
+{}
+XmlGenerator::~XmlGenerator()
+{}
+
+string XmlGenerator::getOpenTag(const string& styleName ){
+ return "<"+styleName+">";
+}
+
+string XmlGenerator::getCloseTag(const string& styleName ){
+ return "</"+styleName+">";
+}
+
+string XmlGenerator::getHeader(const string & title)
+{
+ ostringstream header;
+ header << "<?xml version=\"1.0\"";
+ if (!omitEncoding) {
+ header << " encoding=\"" << encoding << "\"";
+ }
+ header << "?>\n<document>" << getStyleDefinition();
+ return header.str();
+}
+
+void XmlGenerator::printBody()
+{
+ *out << "<source>\n";
+ processRootState();
+ *out << "</source>\n";
+}
+
+
+string XmlGenerator::getFooter()
+{
+ ostringstream os;
+ os <<"</document>\n";
+ os<< "<!-- XML generated by Highlight "
+ << HIGHLIGHT_VERSION
+ << ", "
+ << HIGHLIGHT_URL
+ <<" -->\n";
+ return os.str();
+}
+
+string XmlGenerator::maskCharacter(unsigned char c)
+{
+ switch (c)
+ {
+ case '<' :
+ return "&lt;";
+ break;
+ case '>' :
+ return "&gt;";
+ break;
+ case '&' :
+ return "&amp;";
+ break;
+ case '\"' :
+ return "&quot;";
+ 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 <string>
+#include <sstream>
+#include <iostream>
+
+#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 << " <fo:block font-size=\""
+ << docStyle.getFontSize()
+ << "pt\" font-family=\"Courier\" white-space-collapse=\"false\" "
+ << "wrap-option=\"wrap\" line-height=\"12pt\" background-color=\"#"
+ << (docStyle.getBgColour().getHexRedValue())
+ << (docStyle.getBgColour().getHexGreenValue())
+ << (docStyle.getBgColour().getHexBlueValue())
+ << "\">";
+
+ for (int i=0;i<NUMBER_BUILTIN_STYLES; i++)
+ {
+ styleTagClose.push_back( "</fo:inline>");
+ }
+ if (fopOutput)
+ newLineTag ="</fo:block>\n<fo:block>";
+ else
+ newLineTag ="</fo:block>\n"+ snl.str();
+
+ spacer = " ";
+}
+
+XslFoGenerator::XslFoGenerator()
+{}
+XslFoGenerator::~XslFoGenerator()
+{}
+
+string XslFoGenerator::getOpenTag(const ElementStyle &elem)
+{
+ ostringstream s;
+ s << "<fo:inline color=\"#"
+ << (elem.getColour().getHexRedValue())
+ << (elem.getColour().getHexGreenValue())
+ << (elem.getColour().getHexBlueValue())
+ << "\"";
+ s << ( elem.isBold() ?" font-weight=\"bold\"" :"" )
+ << ( elem.isItalic() ?" font-style=\"italic\"" :"" )
+ << ( elem.isUnderline() ?" text-decoration=\"underline\"" :"" );
+ s << ">";
+ return s.str();
+}
+
+string XslFoGenerator::getHeader(const string & title)
+{
+ ostringstream os;
+ os << "<?xml version=\"1.0\"";
+ if (!omitEncoding) {
+ os << " encoding=\"" << encoding << "\"";
+ }
+ os << "?>\n<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\n"
+ << "<fo:layout-master-set>\n"
+ << "<fo:simple-page-master master-name=\"DINA4\"\n"
+ << " page-height=\"29.7cm\"\n"
+ << " page-width=\"21cm\"\n"
+ << " margin-top=\"1cm\"\n"
+ << " margin-bottom=\"2cm\"\n"
+ << " margin-left=\"2.5cm\"\n"
+ << " margin-right=\"2.5cm\">\n"
+ << "<fo:region-body />\n"
+ << "</fo:simple-page-master>\n"
+ << "<fo:page-sequence-master master-name=\"basic\">\n"
+ << "<fo:repeatable-page-master-alternatives>\n"
+ << "<fo:conditional-page-master-reference master-reference=\"DINA4\" />\n"
+ << "</fo:repeatable-page-master-alternatives>\n"
+ << "</fo:page-sequence-master>\n"
+ << "</fo:layout-master-set>\n\n"
+ << "<fo:page-sequence master-reference=\"basic\">\n"
+ << " <fo:flow flow-name=\"xsl-region-body\">\n";
+ if (fopOutput)
+ os << snl.str()<< "<fo:block>";
+ else
+ os << snl.str();
+
+ return os.str();
+}
+
+/** gibt RTF-Text aus */
+void XslFoGenerator::printBody()
+{
+ processRootState();
+}
+
+
+string XslFoGenerator::getFooter()
+{
+ ostringstream os;
+ if (fopOutput)
+ os <<"\n</fo:block>";
+ os <<"\n</fo:block>\n </fo:flow>\n</fo:page-sequence>\n</fo:root>"<<endl
+ << "<!-- XSL-FO generated by Highlight "
+ << HIGHLIGHT_VERSION
+ << ", "
+ << HIGHLIGHT_URL
+ <<" -->\n";
+ return os.str();
+}
+
+/** Gibt RTF-Code der Sonderzeichen zurueck */
+string XslFoGenerator::maskCharacter(unsigned char c)
+{
+ switch (c)
+ {
+ case '<' :
+ return "&lt;";
+ break;
+ case '>' :
+ return "&gt;";
+ break;
+ case '&' :
+ return "&amp;";
+ break;
+ case '\"' :
+ return "&quot;";
+ 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 "</fo:inline>";
+}
+
+}
+/***************************************************************************
+ 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 <string>
+#include <sstream>
+#include <iostream>
+#include <fstream>
+
+#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