KDevelop API Documentation

lib/astyle/ASBeautifier.cpp

Go to the documentation of this file.
00001 /* 00002 * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved. 00003 * 00004 * ASBeautifier.cpp 00005 * by Tal Davidson (davidsont@bigfoot.com) 00006 * This file is a part of "Artistic Style" - an indentater and reformatter 00007 * of C, C++, C# and Java source files. 00008 * 00009 * The "Artistic Style" project, including all files needed to compile it, 00010 * is free software; you can redistribute it and/or use it and/or modify it 00011 * under the terms of the GNU General Public License as published 00012 * by the Free Software Foundation; either version 2 of the License, 00013 * or (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00018 * 00019 * You should have received a copy of the GNU General Public 00020 * License along with this program. 00021 * 00022 * Patches: 00023 * 18 March 1999 - Brian Rampel - 00024 * Fixed inverse insertion of spaces vs. tabs when in -t mode. 00025 */ 00026 00027 #include "compiler_defines.h" 00028 #include "astyle.h" 00029 00030 #include <vector> 00031 #include <string> 00032 #include <cctype> 00033 #include <algorithm> 00034 #include <iostream> 00035 00036 00037 #define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); } 00038 #define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container) ; } 00039 00040 #ifdef USES_NAMESPACE 00041 using namespace std; 00042 #endif 00043 00044 00045 00046 00047 #ifdef USES_NAMESPACE 00048 namespace astyle 00049 { 00050 #endif 00051 00052 bool ASBeautifier::calledInitStatic = false; 00053 00054 vector<const string*> ASBeautifier::headers; 00055 vector<const string*> ASBeautifier::nonParenHeaders; 00056 vector<const string*> ASBeautifier::preBlockStatements; 00057 vector<const string*> ASBeautifier::assignmentOperators; 00058 vector<const string*> ASBeautifier::nonAssignmentOperators; 00059 00060 /* 00061 * initialize the static vars 00062 */ 00063 void ASBeautifier::initStatic() 00064 { 00065 if (calledInitStatic) 00066 return; 00067 00068 calledInitStatic = true; 00069 00070 headers.push_back(&AS_IF); 00071 headers.push_back(&AS_ELSE); 00072 headers.push_back(&AS_FOR); 00073 headers.push_back(&AS_WHILE); 00074 headers.push_back(&AS_DO); 00075 headers.push_back(&AS_TRY); 00076 headers.push_back(&AS_CATCH); 00077 headers.push_back(&AS_FINALLY); 00078 headers.push_back(&AS_SYNCHRONIZED); 00079 headers.push_back(&AS_SWITCH); 00080 headers.push_back(&AS_CASE); 00081 headers.push_back(&AS_DEFAULT); 00082 headers.push_back(&AS_FOREACH); 00083 headers.push_back(&AS_LOCK); 00084 headers.push_back(&AS_UNSAFE); 00085 headers.push_back(&AS_FIXED); 00086 headers.push_back(&AS_GET); 00087 headers.push_back(&AS_SET); 00088 headers.push_back(&AS_ADD); 00089 headers.push_back(&AS_REMOVE); 00090 //headers.push_back(&AS_PUBLIC); 00091 //headers.push_back(&AS_PRIVATE); 00092 //headers.push_back(&AS_PROTECTED); 00093 00094 //headers.push_back(&AS_OPERATOR); 00095 headers.push_back(&AS_TEMPLATE); 00096 headers.push_back(&AS_CONST); 00097 00098 headers.push_back(&AS_STATIC); 00099 headers.push_back(&AS_EXTERN); 00100 00101 nonParenHeaders.push_back(&AS_ELSE); 00102 nonParenHeaders.push_back(&AS_DO); 00103 nonParenHeaders.push_back(&AS_TRY); 00104 nonParenHeaders.push_back(&AS_FINALLY); 00105 nonParenHeaders.push_back(&AS_STATIC); 00106 nonParenHeaders.push_back(&AS_CONST); 00107 nonParenHeaders.push_back(&AS_EXTERN); 00108 nonParenHeaders.push_back(&AS_CASE); 00109 nonParenHeaders.push_back(&AS_DEFAULT); 00110 nonParenHeaders.push_back(&AS_UNSAFE); 00111 nonParenHeaders.push_back(&AS_GET); 00112 nonParenHeaders.push_back(&AS_SET); 00113 nonParenHeaders.push_back(&AS_ADD); 00114 nonParenHeaders.push_back(&AS_REMOVE); 00115 00116 00117 00118 nonParenHeaders.push_back(&AS_PUBLIC); 00119 nonParenHeaders.push_back(&AS_PRIVATE); 00120 nonParenHeaders.push_back(&AS_PROTECTED); 00121 nonParenHeaders.push_back(&AS_TEMPLATE); 00122 nonParenHeaders.push_back(&AS_CONST); 00124 00125 preBlockStatements.push_back(&AS_CLASS); 00126 preBlockStatements.push_back(&AS_STRUCT); 00127 preBlockStatements.push_back(&AS_UNION); 00128 preBlockStatements.push_back(&AS_INTERFACE); 00129 preBlockStatements.push_back(&AS_NAMESPACE); 00130 preBlockStatements.push_back(&AS_THROWS); 00131 preBlockStatements.push_back(&AS_EXTERN); 00132 00133 assignmentOperators.push_back(&AS_ASSIGN); 00134 assignmentOperators.push_back(&AS_PLUS_ASSIGN); 00135 assignmentOperators.push_back(&AS_MINUS_ASSIGN); 00136 assignmentOperators.push_back(&AS_MULT_ASSIGN); 00137 assignmentOperators.push_back(&AS_DIV_ASSIGN); 00138 assignmentOperators.push_back(&AS_MOD_ASSIGN); 00139 assignmentOperators.push_back(&AS_OR_ASSIGN); 00140 assignmentOperators.push_back(&AS_AND_ASSIGN); 00141 assignmentOperators.push_back(&AS_XOR_ASSIGN); 00142 assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN); 00143 assignmentOperators.push_back(&AS_GR_GR_ASSIGN); 00144 assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN); 00145 assignmentOperators.push_back(&AS_LS_LS_ASSIGN); 00146 00147 assignmentOperators.push_back(&AS_RETURN); 00148 00149 nonAssignmentOperators.push_back(&AS_EQUAL); 00150 nonAssignmentOperators.push_back(&AS_PLUS_PLUS); 00151 nonAssignmentOperators.push_back(&AS_MINUS_MINUS); 00152 nonAssignmentOperators.push_back(&AS_NOT_EQUAL); 00153 nonAssignmentOperators.push_back(&AS_GR_EQUAL); 00154 nonAssignmentOperators.push_back(&AS_GR_GR_GR); 00155 nonAssignmentOperators.push_back(&AS_GR_GR); 00156 nonAssignmentOperators.push_back(&AS_LS_EQUAL); 00157 nonAssignmentOperators.push_back(&AS_LS_LS_LS); 00158 nonAssignmentOperators.push_back(&AS_LS_LS); 00159 nonAssignmentOperators.push_back(&AS_ARROW); 00160 nonAssignmentOperators.push_back(&AS_AND); 00161 nonAssignmentOperators.push_back(&AS_OR); 00162 } 00163 00167 ASBeautifier::ASBeautifier() 00168 { 00169 initStatic(); 00170 00171 waitingBeautifierStack = NULL; 00172 activeBeautifierStack = NULL; 00173 waitingBeautifierStackLengthStack = NULL; 00174 activeBeautifierStackLengthStack = NULL; 00175 00176 headerStack = NULL; 00177 tempStacks = NULL; 00178 blockParenDepthStack = NULL; 00179 blockStatementStack = NULL; 00180 parenStatementStack = NULL; 00181 bracketBlockStateStack = NULL; 00182 inStatementIndentStack = NULL; 00183 inStatementIndentStackSizeStack = NULL; 00184 parenIndentStack = NULL; 00185 sourceIterator = NULL; 00186 00187 isMinimalConditinalIndentSet = false; 00188 shouldForceTabIndentation = false; 00189 00190 setSpaceIndentation(4); 00191 setMaxInStatementIndentLength(40); 00192 setClassIndent(false); 00193 setSwitchIndent(false); 00194 setCaseIndent(false); 00195 setBlockIndent(false); 00196 setBracketIndent(false); 00197 setNamespaceIndent(false); 00198 setLabelIndent(false); 00199 setEmptyLineFill(false); 00200 setCStyle(); 00201 setPreprocessorIndent(false); 00202 } 00203 00204 ASBeautifier::ASBeautifier(const ASBeautifier &other) 00205 { 00206 waitingBeautifierStack = NULL; 00207 activeBeautifierStack = NULL; 00208 waitingBeautifierStackLengthStack = NULL; 00209 activeBeautifierStackLengthStack = NULL; 00210 00211 headerStack = new vector<const string*>; 00212 *headerStack = *other.headerStack; 00213 00214 tempStacks = new vector< vector<const string*>* >; 00215 vector< vector<const string*>* >::iterator iter; 00216 for (iter = other.tempStacks->begin(); 00217 iter != other.tempStacks->end(); 00218 ++iter) 00219 { 00220 vector<const string*> *newVec = new vector<const string*>; 00221 *newVec = **iter; 00222 tempStacks->push_back(newVec); 00223 } 00224 blockParenDepthStack = new vector<int>; 00225 *blockParenDepthStack = *other.blockParenDepthStack; 00226 00227 blockStatementStack = new vector<bool>; 00228 *blockStatementStack = *other.blockStatementStack; 00229 00230 parenStatementStack = new vector<bool>; 00231 *parenStatementStack = *other.parenStatementStack; 00232 00233 bracketBlockStateStack = new vector<bool>; 00234 *bracketBlockStateStack = *other.bracketBlockStateStack; 00235 00236 inStatementIndentStack = new vector<int>; 00237 *inStatementIndentStack = *other.inStatementIndentStack; 00238 00239 inStatementIndentStackSizeStack = new vector<int>; 00240 *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack; 00241 00242 parenIndentStack = new vector<int>; 00243 *parenIndentStack = *other.parenIndentStack; 00244 00245 sourceIterator = other.sourceIterator; 00246 00247 indentString = other.indentString; 00248 currentHeader = other.currentHeader; 00249 previousLastLineHeader = other.previousLastLineHeader; 00250 immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp; 00251 isInQuote = other.isInQuote; 00252 isInComment = other.isInComment; 00253 isInCase = other.isInCase; 00254 isInQuestion = other.isInQuestion; 00255 isInStatement =other. isInStatement; 00256 isInHeader = other.isInHeader; 00257 isCStyle = other.isCStyle; 00258 isInOperator = other.isInOperator; 00259 isInTemplate = other.isInTemplate; 00260 isInConst = other.isInConst; 00261 classIndent = other.classIndent; 00262 isInClassHeader = other.isInClassHeader; 00263 isInClassHeaderTab = other.isInClassHeaderTab; 00264 switchIndent = other.switchIndent; 00265 caseIndent = other.caseIndent; 00266 namespaceIndent = other.namespaceIndent; 00267 bracketIndent = other.bracketIndent; 00268 blockIndent = other.blockIndent; 00269 labelIndent = other.labelIndent; 00270 preprocessorIndent = other.preprocessorIndent; 00271 parenDepth = other.parenDepth; 00272 indentLength = other.indentLength; 00273 blockTabCount = other.blockTabCount; 00274 leadingWhiteSpaces = other.leadingWhiteSpaces; 00275 maxInStatementIndent = other.maxInStatementIndent; 00276 templateDepth = other.templateDepth; 00277 quoteChar = other.quoteChar; 00278 prevNonSpaceCh = other.prevNonSpaceCh; 00279 currentNonSpaceCh = other.currentNonSpaceCh; 00280 currentNonLegalCh = other.currentNonLegalCh; 00281 prevNonLegalCh = other.prevNonLegalCh; 00282 isInConditional = other.isInConditional; 00283 minConditionalIndent = other.minConditionalIndent; 00284 prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount; 00285 prevFinalLineTabCount = other.prevFinalLineTabCount; 00286 emptyLineFill = other.emptyLineFill; 00287 probationHeader = other.probationHeader; 00288 isInDefine = other.isInDefine; 00289 isInDefineDefinition = other.isInDefineDefinition; 00290 backslashEndsPrevLine = other.backslashEndsPrevLine; 00291 defineTabCount = other.defineTabCount; 00292 } 00293 00297 ASBeautifier::~ASBeautifier() 00298 { 00299 DELETE_CONTAINER( headerStack ); 00300 DELETE_CONTAINER( tempStacks ); 00301 DELETE_CONTAINER( blockParenDepthStack ); 00302 DELETE_CONTAINER( blockStatementStack ); 00303 DELETE_CONTAINER( parenStatementStack ); 00304 DELETE_CONTAINER( bracketBlockStateStack ); 00305 DELETE_CONTAINER( inStatementIndentStack ); 00306 DELETE_CONTAINER( inStatementIndentStackSizeStack ); 00307 DELETE_CONTAINER( parenIndentStack ); 00308 00309 //DELETE_CONTAINER( sourceIterator ); 00310 } 00311 00324 void ASBeautifier::init(ASSourceIterator *iter) 00325 { 00326 sourceIterator = iter; 00327 init(); 00328 } 00329 00333 void ASBeautifier::init() 00334 { 00335 INIT_CONTAINER( waitingBeautifierStack, new vector<ASBeautifier*> ); 00336 INIT_CONTAINER( activeBeautifierStack, new vector<ASBeautifier*> ); 00337 00338 INIT_CONTAINER( waitingBeautifierStackLengthStack, new vector<int> ); 00339 INIT_CONTAINER( activeBeautifierStackLengthStack, new vector<int> ); 00340 00341 INIT_CONTAINER( headerStack, new vector<const string*> ); 00342 INIT_CONTAINER( tempStacks, new vector< vector<const string*>* > ); 00343 tempStacks->push_back(new vector<const string*>); 00344 00345 INIT_CONTAINER( blockParenDepthStack, new vector<int> ); 00346 INIT_CONTAINER( blockStatementStack, new vector<bool> ); 00347 INIT_CONTAINER( parenStatementStack, new vector<bool> ); 00348 00349 INIT_CONTAINER( bracketBlockStateStack, new vector<bool> ); 00350 bracketBlockStateStack->push_back(true); 00351 00352 INIT_CONTAINER( inStatementIndentStack, new vector<int> ); 00353 INIT_CONTAINER( inStatementIndentStackSizeStack, new vector<int> ); 00354 inStatementIndentStackSizeStack->push_back(0); 00355 INIT_CONTAINER( parenIndentStack, new vector<int> ); 00356 00357 immediatelyPreviousAssignmentOp = NULL; 00358 previousLastLineHeader = NULL; 00359 00360 isInQuote = false; 00361 isInComment = false; 00362 isInStatement = false; 00363 isInCase = false; 00364 isInQuestion = false; 00365 isInClassHeader = false; 00366 isInClassHeaderTab = false; 00367 isInHeader = false; 00368 isInOperator = false; 00369 isInTemplate = false; 00370 isInConst = false; 00371 isInConditional = false; 00372 templateDepth = 0; 00373 parenDepth=0; 00374 blockTabCount = 0; 00375 leadingWhiteSpaces = 0; 00376 prevNonSpaceCh = '{'; 00377 currentNonSpaceCh = '{'; 00378 prevNonLegalCh = '{'; 00379 currentNonLegalCh = '{'; 00380 prevFinalLineSpaceTabCount = 0; 00381 prevFinalLineTabCount = 0; 00382 probationHeader = NULL; 00383 backslashEndsPrevLine = false; 00384 isInDefine = false; 00385 isInDefineDefinition = false; 00386 defineTabCount = 0; 00387 } 00388 00392 void ASBeautifier::setCStyle() 00393 { 00394 isCStyle = true; 00395 } 00396 00400 void ASBeautifier::setJavaStyle() 00401 { 00402 isCStyle = false; 00403 } 00404 00408 void ASBeautifier::setTabIndentation(int length, bool forceTabs) 00409 { 00410 indentString = "\t"; 00411 indentLength = length; 00412 shouldForceTabIndentation = forceTabs; 00413 00414 if (!isMinimalConditinalIndentSet) 00415 minConditionalIndent = indentLength * 2; 00416 } 00417 00423 void ASBeautifier::setSpaceIndentation(int length) 00424 { 00425 indentString=string(length, ' '); 00426 indentLength = length; 00427 00428 if (!isMinimalConditinalIndentSet) 00429 minConditionalIndent = indentLength * 2; 00430 } 00431 00437 void ASBeautifier::setMaxInStatementIndentLength(int max) 00438 { 00439 maxInStatementIndent = max; 00440 } 00441 00447 void ASBeautifier::setMinConditionalIndentLength(int min) 00448 { 00449 minConditionalIndent = min; 00450 isMinimalConditinalIndentSet = true; 00451 } 00452 00459 void ASBeautifier::setBracketIndent(bool state) 00460 { 00461 bracketIndent = state; 00462 } 00463 00470 void ASBeautifier::setBlockIndent(bool state) 00471 { 00472 if (state) 00473 setBracketIndent(false); // so that we don't have both bracket and block indent 00474 blockIndent = state; 00475 } 00476 00483 void ASBeautifier::setClassIndent(bool state) 00484 { 00485 classIndent = state; 00486 } 00487 00494 void ASBeautifier::setSwitchIndent(bool state) 00495 { 00496 switchIndent = state; 00497 } 00498 00505 void ASBeautifier::setCaseIndent(bool state) 00506 { 00507 caseIndent = state; 00508 } 00516 void ASBeautifier::setNamespaceIndent(bool state) 00517 { 00518 namespaceIndent = state; 00519 } 00520 00530 void ASBeautifier::setLabelIndent(bool state) 00531 { 00532 labelIndent = state; 00533 } 00534 00541 void ASBeautifier::setPreprocessorIndent(bool state) 00542 { 00543 preprocessorIndent = state; 00544 } 00545 00554 void ASBeautifier::setEmptyLineFill(bool state) 00555 { 00556 emptyLineFill = state; 00557 } 00558 00564 bool ASBeautifier::hasMoreLines() const 00565 { 00566 return sourceIterator->hasMoreLines(); 00567 } 00568 00574 string ASBeautifier::nextLine() 00575 { 00576 return beautify(sourceIterator->nextLine()); 00577 } 00578 00587 string ASBeautifier::beautify(const string &originalLine) 00588 { 00589 string line; 00590 bool isInLineComment = false; 00591 bool lineStartsInComment = false; 00592 bool isInClass = false; 00593 bool isInSwitch = false; 00594 bool isImmediatelyAfterConst = false; 00595 bool isSpecialChar = false; 00596 char ch = ' '; 00597 char prevCh; 00598 string outBuffer; // the newly idented line is bufferd here 00599 int tabCount = 0; 00600 const string *lastLineHeader = NULL; 00601 bool closingBracketReached = false; 00602 int spaceTabCount = 0; 00603 char tempCh; 00604 int headerStackSize = headerStack->size(); 00605 //bool isLineInStatement = isInStatement; 00606 bool shouldIndentBrackettedLine = true; 00607 int lineOpeningBlocksNum = 0; 00608 int lineClosingBlocksNum = 0; 00609 bool previousLineProbation = (probationHeader != NULL); 00610 int i; 00611 00612 currentHeader = NULL; 00613 00614 lineStartsInComment = isInComment; 00615 00616 // handle and remove white spaces around the line: 00617 // If not in comment, first find out size of white space before line, 00618 // so that possible comments starting in the line continue in 00619 // relation to the preliminary white-space. 00620 if (!isInComment) 00621 { 00622 leadingWhiteSpaces = 0; 00623 while (leadingWhiteSpaces<(int)originalLine.length() && originalLine[leadingWhiteSpaces] <= 0x20) 00624 leadingWhiteSpaces++; 00625 00626 line = trim(originalLine); 00627 } 00628 else 00629 { 00630 int trimSize; 00631 for (trimSize=0; 00632 trimSize < (int)originalLine.length() && trimSize<leadingWhiteSpaces && originalLine[trimSize] <= 0x20 ; 00633 trimSize++) 00634 ; 00635 line = originalLine.substr(trimSize); 00636 } 00637 00638 00639 if (line.length() == 0) 00640 { 00641 if (emptyLineFill) 00642 return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount); 00643 else 00644 return line; 00645 } 00646 00647 // handle preprocessor commands 00648 00649 if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine)) 00650 { 00651 if (line[0] == '#') 00652 { 00653 string preproc = trim(string(line.c_str() + 1)); 00654 00655 00656 // When finding a multi-lined #define statement, the original beautifier 00657 // 1. sets its isInDefineDefinition flag 00658 // 2. clones a new beautifier that will be used for the actual indentation 00659 // of the #define. This clone is put into the activeBeautifierStack in order 00660 // to be called for the actual indentation. 00661 // The original beautifier will have isInDefineDefinition = true, isInDefine = false 00662 // The cloned beautifier will have isInDefineDefinition = true, isInDefine = true 00663 if (preprocessorIndent && preproc.COMPARE(0, 6, string("define")) == 0 && line[line.length() - 1] == '\\') 00664 { 00665 if (!isInDefineDefinition) 00666 { 00667 ASBeautifier *defineBeautifier; 00668 00669 // this is the original beautifier 00670 isInDefineDefinition = true; 00671 00672 // push a new beautifier into the active stack 00673 // this breautifier will be used for the indentation of this define 00674 defineBeautifier = new ASBeautifier(*this); 00675 //defineBeautifier->init(); 00676 //defineBeautifier->isInDefineDefinition = true; 00677 //defineBeautifier->beautify(""); 00678 activeBeautifierStack->push_back(defineBeautifier); 00679 } 00680 else 00681 { 00682 // the is the cloned beautifier that is in charge of indenting the #define. 00683 isInDefine = true; 00684 } 00685 } 00686 else if (preproc.COMPARE(0, 2, string("if")) == 0) 00687 { 00688 // push a new beautifier into the stack 00689 waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size()); 00690 activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size()); 00691 waitingBeautifierStack->push_back(new ASBeautifier(*this)); 00692 } 00693 else if (preproc.COMPARE(0, 4/*2*/, string("else")) == 0) 00694 { 00695 if (!waitingBeautifierStack->empty()) 00696 { 00697 // MOVE current waiting beautifier to active stack. 00698 activeBeautifierStack->push_back(waitingBeautifierStack->back()); 00699 waitingBeautifierStack->pop_back(); 00700 } 00701 } 00702 else if (preproc.COMPARE(0, 4, string("elif")) == 0) 00703 { 00704 if (!waitingBeautifierStack->empty()) 00705 { 00706 // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original. 00707 activeBeautifierStack->push_back( new ASBeautifier( *(waitingBeautifierStack->back()) ) ); 00708 } 00709 } 00710 else if (preproc.COMPARE(0, 5, string("endif")) == 0) 00711 { 00712 int stackLength; 00713 ASBeautifier *beautifier; 00714 00715 if (!waitingBeautifierStackLengthStack->empty()) 00716 { 00717 stackLength = waitingBeautifierStackLengthStack->back(); 00718 waitingBeautifierStackLengthStack->pop_back(); 00719 while ((int)waitingBeautifierStack->size() > stackLength) 00720 { 00721 beautifier = waitingBeautifierStack->back(); 00722 waitingBeautifierStack->pop_back(); 00723 delete beautifier; 00724 } 00725 } 00726 00727 if (!activeBeautifierStackLengthStack->empty()) 00728 { 00729 stackLength = activeBeautifierStackLengthStack->back(); 00730 activeBeautifierStackLengthStack->pop_back(); 00731 while ((int)activeBeautifierStack->size() > stackLength) 00732 { 00733 beautifier = activeBeautifierStack->back(); 00734 activeBeautifierStack->pop_back(); 00735 delete beautifier; 00736 } 00737 } 00738 00739 00740 } 00741 } 00742 00743 // check if the last char is a backslash 00744 if(line.length() > 0) 00745 backslashEndsPrevLine = (line[line.length() - 1] == '\\'); 00746 else 00747 backslashEndsPrevLine = false; 00748 00749 // check if this line ends a multi-line #define 00750 // if so, use the #define's cloned beautifier for the line's indentation 00751 // and then remove it from the active beautifier stack and delete it. 00752 if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine) 00753 { 00754 string beautifiedLine; 00755 ASBeautifier *defineBeautifier; 00756 00757 isInDefineDefinition = false; 00758 defineBeautifier = activeBeautifierStack->back(); 00759 activeBeautifierStack->pop_back(); 00760 00761 beautifiedLine = defineBeautifier->beautify(line); 00762 delete defineBeautifier; 00763 return beautifiedLine; 00764 } 00765 00766 // unless this is a multi-line #define, return this precompiler line as is. 00767 if (!isInDefine && !isInDefineDefinition) 00768 return originalLine; 00769 } 00770 00771 // if there exists any worker beautifier in the activeBeautifierStack, 00772 // then use it instead of me to indent the current line. 00773 if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty()) 00774 { 00775 return activeBeautifierStack->back()->beautify(line); 00776 } 00777 00778 // calculate preliminary indentation based on data from past lines 00779 if (!inStatementIndentStack->empty()) 00780 spaceTabCount = inStatementIndentStack->back(); 00781 00782 00783 for (i=0; i<headerStackSize; i++) 00784 { 00785 isInClass = false; 00786 00787 if (blockIndent || (!(i>0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET 00788 && (*headerStack)[i] == &AS_OPEN_BRACKET))) 00789 ++tabCount; 00790 00791 if (isCStyle && !namespaceIndent && i >= 1 00792 && (*headerStack)[i-1] == &AS_NAMESPACE 00793 && (*headerStack)[i] == &AS_OPEN_BRACKET) 00794 --tabCount; 00795 00796 if (isCStyle && i >= 1 00797 && (*headerStack)[i-1] == &AS_CLASS 00798 && (*headerStack)[i] == &AS_OPEN_BRACKET ) 00799 { 00800 if (classIndent) 00801 ++tabCount; 00802 isInClass = true; 00803 } 00804 00805 // is the switchIndent option is on, indent switch statements an additional indent. 00806 else if (switchIndent && i > 1 && 00807 (*headerStack)[i-1] == &AS_SWITCH && 00808 (*headerStack)[i] == &AS_OPEN_BRACKET 00809 ) 00810 { 00811 ++tabCount; 00812 isInSwitch = true; 00813 } 00814 00815 } 00816 00817 if (!lineStartsInComment 00818 && isCStyle 00819 && isInClass 00820 && classIndent 00821 && headerStackSize >= 2 00822 &&(*headerStack)[headerStackSize-2] == &AS_CLASS 00823 && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET 00824 && line[0] == '}') 00825 --tabCount; 00826 00827 else if (!lineStartsInComment 00828 && isInSwitch 00829 && switchIndent 00830 && headerStackSize >= 2 00831 && (*headerStack)[headerStackSize-2] == &AS_SWITCH 00832 && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET 00833 && line[0] == '}') 00834 --tabCount; 00835 00836 if (isInClassHeader) 00837 { 00838 isInClassHeaderTab = true; 00839 tabCount += 2; 00840 } 00841 00842 if (isInConditional) 00843 { 00844 --tabCount; 00845 } 00846 00847 00848 // parse characters in the current line. 00849 00850 for (i=0; i<(int)line.length(); i++) 00851 { 00852 tempCh = line[i]; 00853 00854 prevCh = ch; 00855 ch = tempCh; 00856 00857 outBuffer.append(1, ch); 00858 00859 if (isWhiteSpace(ch)) 00860 continue; 00861 00862 // handle special characters (i.e. backslash+character such as \n, \t, ...) 00863 if (isSpecialChar) 00864 { 00865 isSpecialChar = false; 00866 continue; 00867 } 00868 if (!(isInComment || isInLineComment) && line.COMPARE(i, 2, string("\\\\")) == 0) 00869 { 00870 outBuffer.append(1, '\\'); 00871 i++; 00872 continue; 00873 } 00874 if (!(isInComment || isInLineComment) && ch=='\\') 00875 { 00876 isSpecialChar = true; 00877 continue; 00878 } 00879 00880 // handle quotes (such as 'x' and "Hello Dolly") 00881 if (!(isInComment || isInLineComment) && (ch=='"' || ch=='\'')) 00882 if (!isInQuote) 00883 { 00884 quoteChar = ch; 00885 isInQuote = true; 00886 } 00887 else if (quoteChar == ch) 00888 { 00889 isInQuote = false; 00890 isInStatement = true; 00891 continue; 00892 } 00893 if (isInQuote) 00894 continue; 00895 00896 // handle comments 00897 00898 if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_LINE_COMMENT) == 0 ) 00899 { 00900 isInLineComment = true; 00901 outBuffer.append(1, '/'); 00902 i++; 00903 continue; 00904 } 00905 else if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_COMMENT) == 0 ) 00906 { 00907 isInComment = true; 00908 outBuffer.append(1, '*'); 00909 i++; 00910 continue; 00911 } 00912 else if ( (isInComment || isInLineComment) && line.COMPARE(i, 2, AS_CLOSE_COMMENT) == 0 ) 00913 { 00914 isInComment = false; 00915 outBuffer.append(1, '/'); 00916 i++; 00917 continue; 00918 } 00919 00920 if (isInComment||isInLineComment) 00921 continue; 00922 00923 // if we have reached this far then we are NOT in a comment or string of special character... 00924 00925 if (probationHeader != NULL) 00926 { 00927 if ( ((probationHeader == &AS_STATIC || probationHeader == &AS_CONST) && ch == '{') 00928 || (probationHeader == &AS_SYNCHRONIZED && ch == '(')) 00929 { 00930 // insert the probation header as a new header 00931 isInHeader = true; 00932 headerStack->push_back(probationHeader); 00933 00934 // handle the specific probation header 00935 isInConditional = (probationHeader == &AS_SYNCHRONIZED); 00936 if (probationHeader == &AS_CONST) 00937 isImmediatelyAfterConst = true; 00938 // isInConst = true; 00947 isInStatement = false; 00948 // if the probation comes from the previous line, then indent by 1 tab count. 00949 if (previousLineProbation && ch == '{') 00950 tabCount++; 00951 previousLineProbation = false; 00952 } 00953 00954 // dismiss the probation header 00955 probationHeader = NULL; 00956 } 00957 00958 prevNonSpaceCh = currentNonSpaceCh; 00959 currentNonSpaceCh = ch; 00960 if (!isLegalNameChar(ch) && ch != ',' && ch != ';' ) 00961 { 00962 prevNonLegalCh = currentNonLegalCh; 00963 currentNonLegalCh = ch; 00964 } 00965 00966 //if (isInConst) 00967 //{ 00968 // isInConst = false; 00969 // isImmediatelyAfterConst = true; 00970 //} 00971 00972 if (isInHeader) 00973 { 00974 isInHeader = false; 00975 currentHeader = headerStack->back(); 00976 } 00977 else 00978 currentHeader = NULL; 00979 00980 if (isCStyle && isInTemplate 00981 && (ch == '<' || ch == '>') 00982 && findHeader(line, i, nonAssignmentOperators) == NULL) //; 00983 { 00984 if (ch == '<') 00985 { 00986 ++templateDepth; 00987 } 00988 else if (ch == '>') 00989 { 00990 if (--templateDepth <= 0) 00991 { 00992 if (isInTemplate) 00993 ch = ';'; 00994 else 00995 ch = 't'; 00996 isInTemplate = false; 00997 templateDepth = 0; 00998 } 00999 } 01000 } 01001 01002 // handle parenthesies 01003 if (ch == '(' || ch == '[' || ch == ')' || ch == ']') 01004 { 01005 if (ch == '(' || ch == '[') 01006 { 01007 if (parenDepth == 0) 01008 { 01009 parenStatementStack->push_back(isInStatement); 01010 isInStatement = true; 01011 } 01012 parenDepth++; 01013 01014 inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); 01015 01016 if (currentHeader != NULL) 01017 registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true); 01018 else 01019 registerInStatementIndent(line, i, spaceTabCount, 0, true); 01020 } 01021 else if (ch == ')' || ch == ']') 01022 { 01023 parenDepth--; 01024 if (parenDepth == 0) 01025 { 01026 isInStatement = parenStatementStack->back(); 01027 parenStatementStack->pop_back(); 01028 ch = ' '; 01029 01030 isInConditional = false; 01031 } 01032 01033 if (!inStatementIndentStackSizeStack->empty()) 01034 { 01035 int previousIndentStackSize = inStatementIndentStackSizeStack->back(); 01036 inStatementIndentStackSizeStack->pop_back(); 01037 while (previousIndentStackSize < (int)inStatementIndentStack->size()) 01038 inStatementIndentStack->pop_back(); 01039 01040 if (!parenIndentStack->empty()) 01041 { 01042 int poppedIndent = parenIndentStack->back(); 01043 parenIndentStack->pop_back(); 01044 01045 if (i == 0) 01046 spaceTabCount = poppedIndent; 01047 } 01048 } 01049 } 01050 01051 continue; 01052 } 01053 01054 01055 if (ch == '{') 01056 { 01057 bool isBlockOpener = false; 01058 01059 // first, check if '{' is a block-opener or an static-array opener 01060 isBlockOpener = ( (prevNonSpaceCh == '{' && bracketBlockStateStack->back()) 01061 || prevNonSpaceCh == '}' 01062 || prevNonSpaceCh == ')' 01063 || prevNonSpaceCh == ';' 01064 || isInClassHeader 01065 || isBlockOpener 01066 || isImmediatelyAfterConst 01067 || (isInDefine && 01068 (prevNonSpaceCh == '(' 01069 || prevNonSpaceCh == '_' 01070 || isalnum(prevNonSpaceCh))) ); 01071 01072 isInClassHeader = false; 01073 if (!isBlockOpener && currentHeader != NULL) 01074 { 01075 for (int n=0; n < (int)nonParenHeaders.size(); n++) 01076 if (currentHeader == nonParenHeaders[n]) 01077 { 01078 isBlockOpener = true; 01079 break; 01080 } 01081 } 01082 bracketBlockStateStack->push_back(isBlockOpener); 01083 if (!isBlockOpener) 01084 { 01085 inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); 01086 registerInStatementIndent(line, i, spaceTabCount, 0, true); 01087 parenDepth++; 01088 if (i == 0) 01089 shouldIndentBrackettedLine = false; 01090 01091 continue; 01092 } 01093 01094 // this bracket is a block opener... 01095 01096 ++lineOpeningBlocksNum; 01097 01098 if (isInClassHeader) 01099 isInClassHeader = false; 01100 if (isInClassHeaderTab) 01101 { 01102 isInClassHeaderTab = false; 01103 tabCount -= 2; 01104 } 01105 01106 blockParenDepthStack->push_back(parenDepth); 01107 blockStatementStack->push_back(isInStatement); 01108 01109 inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); 01110 01111 blockTabCount += isInStatement? 1 : 0; 01112 parenDepth = 0; 01113 isInStatement = false; 01114 01115 tempStacks->push_back(new vector<const string*>); 01116 headerStack->push_back(&AS_OPEN_BRACKET); 01117 lastLineHeader = &AS_OPEN_BRACKET; // <------ 01118 01119 continue; 01120 } 01121 01122 //check if a header has been reached 01123 if (prevCh == ' ') 01124 { 01125 bool isIndentableHeader = true; 01126 const string *newHeader = findHeader(line, i, headers); 01127 if (newHeader != NULL) 01128 { 01129 // if we reached here, then this is a header... 01130 isInHeader = true; 01131 01132 vector<const string*> *lastTempStack; 01133 if (tempStacks->empty()) 01134 lastTempStack = NULL; 01135 else 01136 lastTempStack = tempStacks->back(); 01137 01138 // if a new block is opened, push a new stack into tempStacks to hold the 01139 // future list of headers in the new block. 01140 01141 // take care of the special case: 'else if (...)' 01142 if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE) 01143 { 01144 //spaceTabCount += indentLength; // to counter the opposite addition that occurs when the 'if' is registered below... 01145 headerStack->pop_back(); 01146 } 01147 01148 // take care of 'else' 01149 else if (newHeader == &AS_ELSE) 01150 { 01151 if (lastTempStack != NULL) 01152 { 01153 int indexOfIf = indexOf(*lastTempStack, &AS_IF); // <--- 01154 if (indexOfIf != -1) 01155 { 01156 // recreate the header list in headerStack up to the previous 'if' 01157 // from the temporary snapshot stored in lastTempStack. 01158 int restackSize = lastTempStack->size() - indexOfIf - 1; 01159 for (int r=0; r<restackSize; r++) 01160 { 01161 headerStack->push_back(lastTempStack->back()); 01162 lastTempStack->pop_back(); 01163 } 01164 if (!closingBracketReached) 01165 tabCount += restackSize; 01166 } 01167 /* 01168 * If the above if is not true, i.e. no 'if' before the 'else', 01169 * then nothing beautiful will come out of this... 01170 * I should think about inserting an Exception here to notify the caller of this... 01171 */ 01172 } 01173 } 01174 01175 // check if 'while' closes a previous 'do' 01176 else if (newHeader == &AS_WHILE) 01177 { 01178 if (lastTempStack != NULL) 01179 { 01180 int indexOfDo = indexOf(*lastTempStack, &AS_DO); // <--- 01181 if (indexOfDo != -1) 01182 { 01183 // recreate the header list in headerStack up to the previous 'do' 01184 // from the temporary snapshot stored in lastTempStack. 01185 int restackSize = lastTempStack->size() - indexOfDo - 1; 01186 for (int r=0; r<restackSize; r++) 01187 { 01188 headerStack->push_back(lastTempStack->back()); 01189 lastTempStack->pop_back(); 01190 } 01191 if (!closingBracketReached) 01192 tabCount += restackSize; 01193 } 01194 } 01195 } 01196 // check if 'catch' closes a previous 'try' or 'catch' 01197 else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY) 01198 { 01199 if (lastTempStack != NULL) 01200 { 01201 int indexOfTry = indexOf(*lastTempStack, &AS_TRY); 01202 if (indexOfTry == -1) 01203 indexOfTry = indexOf(*lastTempStack, &AS_CATCH); 01204 if (indexOfTry != -1) 01205 { 01206 // recreate the header list in headerStack up to the previous 'try' 01207 // from the temporary snapshot stored in lastTempStack. 01208 int restackSize = lastTempStack->size() - indexOfTry - 1; 01209 for (int r=0; r<restackSize; r++) 01210 { 01211 headerStack->push_back(lastTempStack->back()); 01212 lastTempStack->pop_back(); 01213 } 01214 01215 if (!closingBracketReached) 01216 tabCount += restackSize; 01217 } 01218 } 01219 } 01220 else if (newHeader == &AS_CASE) 01221 { 01222 isInCase = true; 01223 if (!caseIndent) 01224 --tabCount; 01225 } 01226 else if(newHeader == &AS_DEFAULT) 01227 { 01228 isInCase = true; 01229 if (!caseIndent) 01230 --tabCount; 01231 } 01232 else if (newHeader == &AS_PUBLIC || newHeader == &AS_PROTECTED || newHeader == &AS_PRIVATE) 01233 { 01234 if (isCStyle && !isInClassHeader) 01235 --tabCount; 01236 isIndentableHeader = false; 01237 } 01238 //else if ((newHeader == &STATIC || newHeader == &SYNCHRONIZED) && 01239 // !headerStack->empty() && 01240 // (headerStack->back() == &STATIC || headerStack->back() == &SYNCHRONIZED)) 01241 //{ 01242 // isIndentableHeader = false; 01243 //} 01244 else if (newHeader == &AS_STATIC 01245 || newHeader == &AS_SYNCHRONIZED 01246 || (newHeader == &AS_CONST && isCStyle)) 01247 { 01248 if (!headerStack->empty() && 01249 (headerStack->back() == &AS_STATIC 01250 || headerStack->back() == &AS_SYNCHRONIZED 01251 || headerStack->back() == &AS_CONST)) 01252 { 01253 isIndentableHeader = false; 01254 } 01255 else 01256 { 01257 isIndentableHeader = false; 01258 probationHeader = newHeader; 01259 } 01260 } 01261 else if (newHeader == &AS_CONST) 01262 { 01263 // this will be entered only if NOT in C style 01264 // since otherwise the CONST would be found to be a probstion header... 01265 01266 //if (isCStyle) 01267 // isInConst = true; 01268 isIndentableHeader = false; 01269 } 01270 /* 01271 else if (newHeader == &OPERATOR) 01272 { 01273 if (isCStyle) 01274 isInOperator = true; 01275 isIndentableHeader = false; 01276 } 01277 */ 01278 else if (newHeader == &AS_TEMPLATE) 01279 { 01280 if (isCStyle) 01281 isInTemplate = true; 01282 isIndentableHeader = false; 01283 } 01284 01285 01286 if (isIndentableHeader) 01287 { 01288 // 3.2.99 01289 //spaceTabCount-=indentLength; 01290 headerStack->push_back(newHeader); 01291 isInStatement = false; 01292 if (indexOf(nonParenHeaders, newHeader) == -1) 01293 { 01294 isInConditional = true; 01295 } 01296 lastLineHeader = newHeader; 01297 } 01298 else 01299 isInHeader = false; 01300 01301 //lastLineHeader = newHeader; 01302 01303 outBuffer.append(newHeader->substr(1)); 01304 i += newHeader->length() - 1; 01305 01306 continue; 01307 } 01308 } 01309 01310 if (isCStyle && !isalpha(prevCh) 01311 && line.COMPARE(i, 8, AS_OPERATOR) == 0 && !isalnum(line[i+8])) 01312 { 01313 isInOperator = true; 01314 outBuffer.append(AS_OPERATOR.substr(1)); 01315 i += 7; 01316 continue; 01317 } 01318 01319 if (ch == '?') 01320 isInQuestion = true; 01321 01322 01323 // special handling of 'case' statements 01324 if (ch == ':') 01325 { 01326 if ((int)line.length() > i+1 && line[i+1] == ':') // look for :: 01327 { 01328 ++i; 01329 outBuffer.append(1, ':'); 01330 ch = ' '; 01331 continue; 01332 } 01333 01334 else if (isCStyle && isInClass && prevNonSpaceCh != ')') 01335 { 01336 --tabCount; 01337 // found a 'private:' or 'public:' inside a class definition 01338 // so do nothing special 01339 } 01340 01341 else if (isCStyle && isInClassHeader) 01342 { 01343 01344 // found a 'class A : public B' definition 01345 // so do nothing special 01346 } 01347 01348 else if (isInQuestion) 01349 { 01350 isInQuestion = false; 01351 } 01352 else if (isCStyle && prevNonSpaceCh == ')') 01353 { 01354 isInClassHeader = true; 01355 if (i==0) 01356 tabCount += 2; 01357 } 01358 else 01359 { 01360 currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers 01361 if (isInCase) 01362 { 01363 isInCase = false; 01364 ch = ';'; // from here on, treat char as ';' 01365 } 01366 01367 01368 else // is in a label (e.g. 'label1:') 01369 { 01370 if (labelIndent) 01371 --tabCount; // unindent label by one indent 01372 else 01373 tabCount = 0; // completely flush indent to left 01374 } 01375 01376 01377 01378 } 01379 } 01380 01381 if ((ch == ';' || (parenDepth>0 && ch == ',')) && !inStatementIndentStackSizeStack->empty()) 01382 while (inStatementIndentStackSizeStack->back() + (parenDepth>0 ? 1 : 0) < (int)inStatementIndentStack->size()) 01383 inStatementIndentStack->pop_back(); 01384 01385 01386 // handle ends of statements 01387 if ( (ch == ';' && parenDepth == 0) || ch == '}'/* || (ch == ',' && parenDepth == 0)*/) 01388 { 01389 if (ch == '}') 01390 { 01391 // first check if this '}' closes a previous block, or a static array... 01392 if (!bracketBlockStateStack->empty()) 01393 { 01394 bool bracketBlockState = bracketBlockStateStack->back(); 01395 bracketBlockStateStack->pop_back(); 01396 if (!bracketBlockState) 01397 { 01398 if (!inStatementIndentStackSizeStack->empty()) 01399 { 01400 // this bracket is a static array 01401 01402 int previousIndentStackSize = inStatementIndentStackSizeStack->back(); 01403 inStatementIndentStackSizeStack->pop_back(); 01404 while (previousIndentStackSize < (int)inStatementIndentStack->size()) 01405 inStatementIndentStack->pop_back(); 01406 parenDepth--; 01407 if (i == 0) 01408 shouldIndentBrackettedLine = false; 01409 01410 if (!parenIndentStack->empty()) 01411 { 01412 int poppedIndent = parenIndentStack->back(); 01413 parenIndentStack->pop_back(); 01414 if (i == 0) 01415 spaceTabCount = poppedIndent; 01416 } 01417 } 01418 continue; 01419 } 01420 } 01421 01422 // this bracket is block closer... 01423 01424 ++lineClosingBlocksNum; 01425 01426 if(!inStatementIndentStackSizeStack->empty()) 01427 inStatementIndentStackSizeStack->pop_back(); 01428 01429 if (!blockParenDepthStack->empty()) 01430 { 01431 parenDepth = blockParenDepthStack->back(); 01432 blockParenDepthStack->pop_back(); 01433 isInStatement = blockStatementStack->back(); 01434 blockStatementStack->pop_back(); 01435 01436 if (isInStatement) 01437 blockTabCount--; 01438 } 01439 01440 closingBracketReached = true; 01441 int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET); // <--- 01442 if (headerPlace != -1) 01443 { 01444 const string *popped = headerStack->back(); 01445 while (popped != &AS_OPEN_BRACKET) 01446 { 01447 headerStack->pop_back(); 01448 popped = headerStack->back(); 01449 } 01450 headerStack->pop_back(); 01451 01452 if (!tempStacks->empty()) 01453 { 01454 vector<const string*> *temp = tempStacks->back(); 01455 tempStacks->pop_back(); 01456 delete temp; 01457 } 01458 } 01459 01460 01461 ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified... 01462 } 01463 01464 /* 01465 * Create a temporary snapshot of the current block's header-list in the 01466 * uppermost inner stack in tempStacks, and clear the headerStack up to 01467 * the begining of the block. 01468 * Thus, the next future statement will think it comes one indent past 01469 * the block's '{' unless it specifically checks for a companion-header 01470 * (such as a previous 'if' for an 'else' header) within the tempStacks, 01471 * and recreates the temporary snapshot by manipulating the tempStacks. 01472 */ 01473 if (!tempStacks->back()->empty()) 01474 while (!tempStacks->back()->empty()) 01475 tempStacks->back()->pop_back(); 01476 while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET) 01477 { 01478 tempStacks->back()->push_back(headerStack->back()); 01479 headerStack->pop_back(); 01480 } 01481 01482 if (parenDepth == 0 && ch == ';') 01483 isInStatement=false; 01484 01485 isInClassHeader = false; 01486 01487 continue; 01488 } 01489 01490 01491 // check for preBlockStatements ONLY if not within parenthesies 01492 // (otherwise 'struct XXX' statements would be wrongly interpreted...) 01493 if (prevCh == ' ' && !isInTemplate && parenDepth == 0) 01494 { 01495 const string *newHeader = findHeader(line, i, preBlockStatements); 01496 if (newHeader != NULL) 01497 { 01498 isInClassHeader = true; 01499 outBuffer.append(newHeader->substr(1)); 01500 i += newHeader->length() - 1; 01501 //if (isCStyle) 01502 headerStack->push_back(newHeader); 01503 } 01504 } 01505 01506 // Handle operators 01507 // 01508 01513 01514 const string *foundAssignmentOp = NULL; 01515 const string *foundNonAssignmentOp = NULL; 01516 01517 immediatelyPreviousAssignmentOp = NULL; 01518 01519 // Check if an operator has been reached. 01520 foundAssignmentOp = findHeader(line, i, assignmentOperators, false); 01521 foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false); 01522 01523 // Since findHeader's boundry checking was not used above, it is possible 01524 // that both an assignment op and a non-assignment op where found, 01525 // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the 01526 // found operator. 01527 if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL) 01528 if (foundAssignmentOp->length() < foundNonAssignmentOp->length()) 01529 foundAssignmentOp = NULL; 01530 else 01531 foundNonAssignmentOp = NULL; 01532 01533 if (foundNonAssignmentOp != NULL) 01534 { 01535 if (foundNonAssignmentOp->length() > 1) 01536 { 01537 outBuffer.append(foundNonAssignmentOp->substr(1)); 01538 i += foundNonAssignmentOp->length() - 1; 01539 } 01540 } 01541 01542 else if (foundAssignmentOp != NULL) 01543 { 01544 if (foundAssignmentOp->length() > 1) 01545 { 01546 outBuffer.append(foundAssignmentOp->substr(1)); 01547 i += foundAssignmentOp->length() - 1; 01548 } 01549 01550 if (!isInOperator && !isInTemplate) 01551 { 01552 registerInStatementIndent(line, i, spaceTabCount, 0, false); 01553 immediatelyPreviousAssignmentOp = foundAssignmentOp; 01554 isInStatement = true; 01555 } 01556 } 01557 01558 /* 01559 immediatelyPreviousAssignmentOp = NULL; 01560 bool isNonAssingmentOperator = false; 01561 for (int n = 0; n < nonAssignmentOperators.size(); n++) 01562 if (line.COMPARE(i, nonAssignmentOperators[n]->length(), *(nonAssignmentOperators[n])) == 0) 01563 { 01564 if (nonAssignmentOperators[n]->length() > 1) 01565 { 01566 outBuffer.append(nonAssignmentOperators[n]->substr(1)); 01567 i += nonAssignmentOperators[n]->length() - 1; 01568 } 01569 isNonAssingmentOperator = true; 01570 break; 01571 } 01572 if (!isNonAssingmentOperator) 01573 { 01574 for (int a = 0; a < assignmentOperators.size(); a++) 01575 if (line.COMPARE(i, assignmentOperators[a]->length(), *(assignmentOperators[a])) == 0) 01576 { 01577 if (assignmentOperators[a]->length() > 1) 01578 { 01579 outBuffer.append(assignmentOperators[a]->substr(1)); 01580 i += assignmentOperators[a]->length() - 1; 01581 } 01582 01583 if (!isInOperator && !isInTemplate) 01584 { 01585 registerInStatementIndent(line, i, spaceTabCount, 0, false); 01586 immediatelyPreviousAssignmentOp = assignmentOperators[a]; 01587 isInStatement = true; 01588 } 01589 break; 01590 } 01591 } 01592 */ 01593 01594 if (isInOperator) 01595 isInOperator = false; 01596 } 01597 01598 // handle special cases of unindentation: 01599 01600 /* 01601 * if '{' doesn't follow an immediately previous '{' in the headerStack 01602 * (but rather another header such as "for" or "if", then unindent it 01603 * by one indentation relative to its block. 01604 */ 01605 // cerr << endl << lineOpeningBlocksNum << " " << lineClosingBlocksNum << " " << previousLastLineHeader << endl; 01606 01607 // indent #define lines with one less tab 01608 //if (isInDefine) 01609 // tabCount -= defineTabCount-1; 01610 01611 01612 if (!lineStartsInComment 01613 && !blockIndent 01614 && outBuffer.length()>0 01615 && outBuffer[0]=='{' 01616 && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum) 01617 && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET) 01618 && shouldIndentBrackettedLine) 01619 --tabCount; 01620 01621 else if (!lineStartsInComment 01622 && outBuffer.length()>0 01623 && outBuffer[0]=='}' 01624 && shouldIndentBrackettedLine ) 01625 --tabCount; 01626 01627 // correctly indent one-line-blocks... 01628 else if (!lineStartsInComment 01629 && outBuffer.length()>0 01630 && lineOpeningBlocksNum > 0 01631 && lineOpeningBlocksNum == lineClosingBlocksNum 01632 && previousLastLineHeader != NULL 01633 && previousLastLineHeader != &AS_OPEN_BRACKET) 01634 tabCount -= 1; //lineOpeningBlocksNum - (blockIndent ? 1 : 0); 01635 01636 if (tabCount < 0) 01637 tabCount = 0; 01638 01639 // take care of extra bracket indentatation option... 01640 if (bracketIndent && outBuffer.length()>0 && shouldIndentBrackettedLine) 01641 if (outBuffer[0]=='{' || outBuffer[0]=='}') 01642 tabCount++; 01643 01644 01645 if (isInDefine) 01646 { 01647 if (outBuffer[0] == '#') 01648 { 01649 string preproc = trim(string(outBuffer.c_str() + 1)); 01650 if (preproc.COMPARE(0, 6, string("define")) == 0) 01651 { 01652 if (!inStatementIndentStack->empty() 01653 && inStatementIndentStack->back() > 0) 01654 { 01655 defineTabCount = tabCount; 01656 } 01657 else 01658 { 01659 defineTabCount = tabCount - 1; 01660 tabCount--; 01661 } 01662 } 01663 } 01664 01665 tabCount -= defineTabCount; 01666 } 01667 01668 if (tabCount < 0) 01669 tabCount = 0; 01670 01671 01672 // finally, insert indentations into begining of line 01673 01674 prevFinalLineSpaceTabCount = spaceTabCount; 01675 prevFinalLineTabCount = tabCount; 01676 01677 if (shouldForceTabIndentation) { 01678 tabCount += spaceTabCount / indentLength; 01679 spaceTabCount = spaceTabCount % indentLength; 01680 } 01681 01682 outBuffer = preLineWS(spaceTabCount,tabCount) + outBuffer; 01683 01684 if (lastLineHeader != NULL) 01685 previousLastLineHeader = lastLineHeader; 01686 01687 return outBuffer; 01688 } 01689 01690 01691 string ASBeautifier::preLineWS(int spaceTabCount, int tabCount) 01692 { 01693 string ws; 01694 01695 for (int i=0; i<tabCount; i++) 01696 ws += indentString; 01697 01698 while ((spaceTabCount--) > 0) 01699 ws += string(" "); 01700 01701 return ws; 01702 01703 } 01704 01708 void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount, 01709 int minIndent, bool updateParenStack) 01710 { 01711 int inStatementIndent; 01712 int remainingCharNum = line.length() - i; 01713 int nextNonWSChar = 1; 01714 01715 nextNonWSChar = getNextProgramCharDistance(line, i); 01716 01717 // if indent is around the last char in the line, indent instead 2 spaces from the previous indent 01718 if (nextNonWSChar == remainingCharNum) 01719 { 01720 int previousIndent = spaceTabCount; 01721 if (!inStatementIndentStack->empty()) 01722 previousIndent = inStatementIndentStack->back(); 01723 01724 inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent ); 01725 if (updateParenStack) 01726 parenIndentStack->push_back( previousIndent ); 01727 return; 01728 } 01729 01730 if (updateParenStack) 01731 parenIndentStack->push_back(i+spaceTabCount); 01732 01733 inStatementIndent = i + nextNonWSChar + spaceTabCount; 01734 01735 if (i + nextNonWSChar < minIndent) 01736 inStatementIndent = minIndent + spaceTabCount; 01737 01738 if (i + nextNonWSChar > maxInStatementIndent) 01739 inStatementIndent = indentLength*2 + spaceTabCount; 01740 01741 01742 01743 if (!inStatementIndentStack->empty() && 01744 inStatementIndent < inStatementIndentStack->back()) 01745 inStatementIndent = inStatementIndentStack->back(); 01746 01747 inStatementIndentStack->push_back(inStatementIndent); 01748 } 01749 01754 int ASBeautifier::getNextProgramCharDistance(const string &line, int i) 01755 { 01756 bool inComment = false; 01757 int remainingCharNum = line.length() - i; 01758 int charDistance = 1; 01759 int ch; 01760 01761 for (charDistance = 1; charDistance < remainingCharNum; charDistance++) 01762 { 01763 ch = line[i + charDistance]; 01764 if (inComment) 01765 { 01766 if (line.COMPARE(i + charDistance, 2, AS_CLOSE_COMMENT) == 0) 01767 { 01768 charDistance++; 01769 inComment = false; 01770 } 01771 continue; 01772 } 01773 else if (isWhiteSpace(ch)) 01774 continue; 01775 else if (ch == '/') 01776 { 01777 if (line.COMPARE(i + charDistance, 2, AS_OPEN_LINE_COMMENT) == 0) 01778 return remainingCharNum; 01779 else if (line.COMPARE(i + charDistance, 2, AS_OPEN_COMMENT) == 0) 01780 { 01781 charDistance++; 01782 inComment = true; 01783 } 01784 } 01785 else 01786 return charDistance; 01787 } 01788 01789 return charDistance; 01790 } 01791 01792 01799 bool ASBeautifier::isLegalNameChar(char ch) const 01800 { 01801 return (isalnum(ch) //(ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9') || 01802 || ch=='.' || ch=='_' || (!isCStyle && ch=='$') || (isCStyle && ch=='~')); 01803 } 01804 01805 01811 const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry) 01812 { 01813 int maxHeaders = possibleHeaders.size(); 01814 const string *header = NULL; 01815 int p; 01816 01817 for (p=0; p < maxHeaders; p++) 01818 { 01819 header = possibleHeaders[p]; 01820 01821 if (line.COMPARE(i, header->length(), *header) == 0) 01822 { 01823 // check that this is a header and not a part of a longer word 01824 // (e.g. not at its begining, not at its middle...) 01825 01826 int lineLength = line.length(); 01827 int headerEnd = i + header->length(); 01828 char startCh = (*header)[0]; // first char of header 01829 char endCh = 0; // char just after header 01830 char prevCh = 0; // char just before header 01831 01832 if (headerEnd < lineLength) 01833 { 01834 endCh = line[headerEnd]; 01835 } 01836 if (i > 0) 01837 { 01838 prevCh = line[i-1]; 01839 } 01840 01841 if (!checkBoundry) 01842 { 01843 return header; 01844 } 01845 else if (prevCh != 0 01846 && isLegalNameChar(startCh) 01847 && isLegalNameChar(prevCh)) 01848 { 01849 return NULL; 01850 } 01851 else if (headerEnd >= lineLength 01852 || !isLegalNameChar(startCh) 01853 || !isLegalNameChar(endCh)) 01854 { 01855 return header; 01856 } 01857 else 01858 { 01859 return NULL; 01860 } 01861 } 01862 } 01863 01864 return NULL; 01865 } 01866 01867 01874 bool ASBeautifier::isWhiteSpace(char ch) const 01875 { 01876 return (ch == ' ' || ch == '\t'); 01877 } 01878 01886 int ASBeautifier::indexOf(vector<const string*> &container, const string *element) 01887 { 01888 vector<const string*>::const_iterator where; 01889 01890 where= find(container.begin(), container.end(), element); 01891 if (where == container.end()) 01892 return -1; 01893 else 01894 return where - container.begin(); 01895 } 01896 01903 string ASBeautifier::trim(const string &str) 01904 { 01905 01906 int start = 0; 01907 int end = str.length() - 1; 01908 01909 while (start < end && isWhiteSpace(str[start])) 01910 start++; 01911 01912 while (start <= end && isWhiteSpace(str[end])) 01913 end--; 01914 01915 string returnStr(str, start, end+1-start); 01916 return returnStr; 01917 } 01918 01919 #ifdef USES_NAMESPACE 01920 } 01921 #endif 01922
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Oct 19 08:01:47 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003