1 /***************************************************************************
2                     ansigenerator.cpp  -  description
3                              -------------------
4     begin                : Jul 5 2004
5     copyright            : (C) 2004 by Andr� Simon
6     email                : andre.simon1@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "ansigenerator.h"
19 
20 using namespace std;
21 
22 namespace highlight {
23 
24 
getOpenTag(const string & font,const string & fgCol,const string & bgCol)25 string  AnsiGenerator::getOpenTag(const string&font,
26                                   const string&fgCol, const string&bgCol) {
27     ostringstream s;
28     s  << "\033["<<font;
29     if (!fgCol.empty())
30         s<<";"<<fgCol;
31     if (!bgCol.empty())
32         s<<";"<<bgCol;
33     s << "m";
34     return  s.str();
35 }
36 
37 
AnsiGenerator(const string & colourTheme)38 AnsiGenerator::AnsiGenerator(const string &colourTheme)
39         : CodeGenerator(colourTheme) {
40     styleTagOpen.push_back("");
41     styleTagOpen.push_back(getOpenTag("00", "31")); //str
42     styleTagOpen.push_back(getOpenTag("00", "34"));//number
43     styleTagOpen.push_back(getOpenTag("00", "34"));//sl comment
44     styleTagOpen.push_back(getOpenTag("00", "34"));//ml comment
45     styleTagOpen.push_back(getOpenTag("00", "35"));//escapeChar
46     styleTagOpen.push_back(getOpenTag("00", "35"));//directive
47     styleTagOpen.push_back(getOpenTag("01", "31"));//directive string
48     styleTagOpen.push_back(getOpenTag("00", "30"));//linenum
49     styleTagOpen.push_back(getOpenTag("01", "00"));//symbol
50 
51     styleTagClose.push_back("");
52     for (int i=1;i<NUMBER_BUILTIN_STYLES; i++) {
53         styleTagClose.push_back("\033[m");
54     }
55     newLineTag = "\n";
56     spacer = " ";
57 }
58 
AnsiGenerator()59 AnsiGenerator::AnsiGenerator() {}
~AnsiGenerator()60 AnsiGenerator::~AnsiGenerator() {}
61 
getHeader(const string & title)62 string AnsiGenerator::getHeader(const string & title) {
63     return string();
64 }
65 
printBody()66 void AnsiGenerator::printBody() {
67     processRootState();
68 }
69 
getFooter()70 string AnsiGenerator::getFooter() {
71     return string();
72 }
73 
maskCharacter(unsigned char c)74 string AnsiGenerator::maskCharacter(unsigned char c) {
75     string m;
76     m+=c;
77     return m;
78 }
79 
getMatchingOpenTag(unsigned int styleID)80 string AnsiGenerator::getMatchingOpenTag(unsigned int styleID) {
81     return (styleID)?getOpenTag("01", "32", ""):getOpenTag("00", "33");
82 }
83 
getMatchingCloseTag(unsigned int styleID)84 string AnsiGenerator::getMatchingCloseTag(unsigned int styleID) {
85     return "\033[m";
86 }
87 
88 }
89 /***************************************************************************
90                          ansicode.h  -  description
91                              -------------------
92     begin                : Jul 5 2004
93     copyright            : (C) 2004 by Andre Simon
94     email                : andre.simon1@gmx.de
95  ***************************************************************************/
96 
97 /***************************************************************************
98  *                                                                         *
99  *   This program is free software; you can redistribute it and/or modify  *
100  *   it under the terms of the GNU General Public License as published by  *
101  *   the Free Software Foundation; either version 2 of the License, or     *
102  *   (at your option) any later version.                                   *
103  *                                                                         *
104  ***************************************************************************/
105 
106 #ifndef ANSIGENERATOR_H
107 #define ANSIGENERATOR_H
108 
109 #include <iostream>
110 #include <fstream>
111 #include <string>
112 #include <sstream>
113 
114 #include "codegenerator.h"
115 #include "charcodes.h"
116 #include "version.h"
117 
118 namespace highlight {
119 
120 /**
121    \brief This class generates ANSI escape sequences.
122 
123    It contains information about the resulting document structure (document
124    header and footer), the colour system, white space handling and text
125    formatting attributes.
126 
127 * @author Andre Simon
128 */
129 
130 class AnsiGenerator : public highlight::CodeGenerator
131   {
132   public:
133 
134    /** Constructor
135      \param colourTheme Name of Colour theme to use
136     */
137     AnsiGenerator( const string &colourTheme);
138     AnsiGenerator();
139     ~AnsiGenerator();
140 
141    /** prints document header
142        \param  title Title of the document
143     */
144     string getHeader(const string & title);
145 
146     /** Prints document footer*/
147     string getFooter();
148 
149     /** Prints document body*/
150     void printBody();
151 
152   private:
153 
154     /** \return escaped character*/
155     virtual string maskCharacter(unsigned char );
156 
157 
158     /** gibt ANSI-"Tags" zurueck (Farbindex+bold+kursiv)*/
159     string getOpenTag(const string&font,
160                       const string&fgCol, const string&bgCol="");
161 
162 
163 
164     string getMatchingOpenTag(unsigned int styleID);
165     string getMatchingCloseTag(unsigned int styleID);
166   };
167 
168 }
169 #endif
170 /*
171  * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
172  *
173  * ASBeautifier.cpp
174  * by Tal Davidson (davidsont@bigfoot.com)
175  * This file is a part of "Artistic Style" - an indentater and reformatter
176  * of C, C, C# and Java source files.
177  *
178  * The "Artistic Style" project, including all files needed to compile it,
179  * is free software; you can redistribute it and/or use it and/or modify it
180  * under the terms of the GNU General Public License as published
181  * by the Free Software Foundation; either version 2 of the License,
182  * or (at your option) any later version.
183  *
184  * This program is distributed in the hope that it will be useful,
185  * but WITHOUT ANY WARRANTY; without even the implied warranty of
186  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
187  *
188  * You should have received a copy of the GNU General Public
189  * License along with this program.
190  *
191  * Patches:
192  * 18 March 1999 - Brian Rampel -
193  *       Fixed inverse insertion of spaces vs. tabs when in -t mode.
194  * 08 may 2004
195  *       applied ASBeautifier.cpp.BITFIELD.patch.bz2
196  */
197 
198 #include "compiler_defines.h"
199 #include "ASBeautifier.h"
200 
201 #include <vector>
202 #include <string>
203 #include <cctype>
204 #include <algorithm>
205 #include <iostream>
206 
207 
208 #define INIT_CONTAINER(container, value)     {if ( (container) != NULL ) delete (container); (container) = (value); }
209 #define DELETE_CONTAINER(container)          {if ( (container) != NULL ) delete (container) ; }
210 
211 #ifdef USES_NAMESPACE
212 using namespace std;
213 #endif
214 
215 
216 
217 
218 #ifdef USES_NAMESPACE
219 namespace astyle
220   {
221 #endif
222 
223   bool ASBeautifier::calledInitStatic = false;
224 
225   vector<const string*> ASBeautifier::headers;
226   vector<const string*> ASBeautifier::nonParenHeaders;
227   vector<const string*> ASBeautifier::preBlockStatements;
228   vector<const string*> ASBeautifier::assignmentOperators;
229   vector<const string*> ASBeautifier::nonAssignmentOperators;
230 
231   /*
232    * initialize the static vars
233    */
initStatic()234   void ASBeautifier::initStatic()
235   {
236     if (calledInitStatic)
237       return;
238 
239     calledInitStatic = true;
240 
241     headers.push_back(&AS_IF);
242     headers.push_back(&AS_ELSE);
243     headers.push_back(&AS_FOR);
244     headers.push_back(&AS_WHILE);
245     headers.push_back(&AS_DO);
246     headers.push_back(&AS_TRY);
247     headers.push_back(&AS_CATCH);
248     headers.push_back(&AS_FINALLY);
249     headers.push_back(&AS_SYNCHRONIZED);
250     headers.push_back(&AS_SWITCH);
251     headers.push_back(&AS_CASE);
252     headers.push_back(&AS_DEFAULT);
253     headers.push_back(&AS_FOREACH);
254     headers.push_back(&AS_LOCK);
255     headers.push_back(&AS_UNSAFE);
256     headers.push_back(&AS_FIXED);
257     headers.push_back(&AS_GET);
258     headers.push_back(&AS_SET);
259     headers.push_back(&AS_ADD);
260     headers.push_back(&AS_REMOVE);
261     //headers.push_back(&AS_PUBLIC);
262     //headers.push_back(&AS_PRIVATE);
263     //headers.push_back(&AS_PROTECTED);
264 
265     //headers.push_back(&AS_OPERATOR);
266     headers.push_back(&AS_TEMPLATE);
267     headers.push_back(&AS_CONST);
268     /**/
269     headers.push_back(&AS_STATIC);
270     headers.push_back(&AS_EXTERN);
271 
272     nonParenHeaders.push_back(&AS_ELSE);
273     nonParenHeaders.push_back(&AS_DO);
274     nonParenHeaders.push_back(&AS_TRY);
275     nonParenHeaders.push_back(&AS_FINALLY);
276     nonParenHeaders.push_back(&AS_STATIC);
277     nonParenHeaders.push_back(&AS_CONST);
278     nonParenHeaders.push_back(&AS_EXTERN);
279     nonParenHeaders.push_back(&AS_CASE);
280     nonParenHeaders.push_back(&AS_DEFAULT);
281     nonParenHeaders.push_back(&AS_UNSAFE);
282     nonParenHeaders.push_back(&AS_GET);
283     nonParenHeaders.push_back(&AS_SET);
284     nonParenHeaders.push_back(&AS_ADD);
285     nonParenHeaders.push_back(&AS_REMOVE);
286 
287 
288 
289     nonParenHeaders.push_back(&AS_PUBLIC);
290     nonParenHeaders.push_back(&AS_PRIVATE);
291     nonParenHeaders.push_back(&AS_PROTECTED);
292     nonParenHeaders.push_back(&AS_TEMPLATE);
293     nonParenHeaders.push_back(&AS_CONST);
294     ///    nonParenHeaders.push_back(&AS_ASM);
295 
296     preBlockStatements.push_back(&AS_CLASS);
297     preBlockStatements.push_back(&AS_STRUCT);
298     preBlockStatements.push_back(&AS_UNION);
299     preBlockStatements.push_back(&AS_INTERFACE);
300     preBlockStatements.push_back(&AS_NAMESPACE);
301     preBlockStatements.push_back(&AS_THROWS);
302     preBlockStatements.push_back(&AS_EXTERN);
303 
304     assignmentOperators.push_back(&AS_ASSIGN);
305     assignmentOperators.push_back(&AS_PLUS_ASSIGN);
306     assignmentOperators.push_back(&AS_MINUS_ASSIGN);
307     assignmentOperators.push_back(&AS_MULT_ASSIGN);
308     assignmentOperators.push_back(&AS_DIV_ASSIGN);
309     assignmentOperators.push_back(&AS_MOD_ASSIGN);
310     assignmentOperators.push_back(&AS_OR_ASSIGN);
311     assignmentOperators.push_back(&AS_AND_ASSIGN);
312     assignmentOperators.push_back(&AS_XOR_ASSIGN);
313     assignmentOperators.push_back(&AS_GR_GR_GR_ASSIGN);
314     assignmentOperators.push_back(&AS_GR_GR_ASSIGN);
315     assignmentOperators.push_back(&AS_LS_LS_LS_ASSIGN);
316     assignmentOperators.push_back(&AS_LS_LS_ASSIGN);
317 
318     assignmentOperators.push_back(&AS_RETURN);
319 
320     nonAssignmentOperators.push_back(&AS_EQUAL);
321     nonAssignmentOperators.push_back(&AS_PLUS_PLUS);
322     nonAssignmentOperators.push_back(&AS_MINUS_MINUS);
323     nonAssignmentOperators.push_back(&AS_NOT_EQUAL);
324     nonAssignmentOperators.push_back(&AS_GR_EQUAL);
325     nonAssignmentOperators.push_back(&AS_GR_GR_GR);
326     nonAssignmentOperators.push_back(&AS_GR_GR);
327     nonAssignmentOperators.push_back(&AS_LS_EQUAL);
328     nonAssignmentOperators.push_back(&AS_LS_LS_LS);
329     nonAssignmentOperators.push_back(&AS_LS_LS);
330     nonAssignmentOperators.push_back(&AS_ARROW);
331     nonAssignmentOperators.push_back(&AS_AND);
332     nonAssignmentOperators.push_back(&AS_OR);
333   }
334 
335   /**
336    * ASBeautifier's constructor
337    */
ASBeautifier()338   ASBeautifier::ASBeautifier()
339   {
340     initStatic();
341 
342     waitingBeautifierStack = NULL;
343     activeBeautifierStack = NULL;
344     waitingBeautifierStackLengthStack = NULL;
345     activeBeautifierStackLengthStack = NULL;
346 
347     headerStack  = NULL;
348     tempStacks = NULL;
349     blockParenDepthStack = NULL;
350     blockStatementStack = NULL;
351     parenStatementStack = NULL;
352     bracketBlockStateStack = NULL;
353     inStatementIndentStack = NULL;
354     inStatementIndentStackSizeStack = NULL;
355     parenIndentStack = NULL;
356     sourceIterator = NULL;
357 
358     isMinimalConditinalIndentSet = false;
359     shouldForceTabIndentation = false;
360 
361     setSpaceIndentation(4);
362     setMaxInStatementIndentLength(40);
363     setClassIndent(false);
364     setSwitchIndent(false);
365     setCaseIndent(false);
366     setBlockIndent(false);
367     setBracketIndent(false);
368     setNamespaceIndent(false);
369     setLabelIndent(false);
370     setEmptyLineFill(false);
371     setCStyle();
372     setPreprocessorIndent(false);
373   }
374 
ASBeautifier(const ASBeautifier & other)375   ASBeautifier::ASBeautifier(const ASBeautifier &other)
376   {
377     waitingBeautifierStack = NULL;
378     activeBeautifierStack = NULL;
379     waitingBeautifierStackLengthStack = NULL;
380     activeBeautifierStackLengthStack = NULL;
381 
382     headerStack  = new vector<const string*>;
383     *headerStack = *other.headerStack;
384 
385     tempStacks = new vector< vector<const string*>* >;
386     vector< vector<const string*>* >::iterator iter;
387     for (iter = other.tempStacks->begin();
388          iter != other.tempStacks->end();
389          ++iter)
390       {
391         vector<const string*> *newVec = new vector<const string*>;
392         *newVec = **iter;
393         tempStacks->push_back(newVec);
394       }
395     blockParenDepthStack = new vector<int>;
396     *blockParenDepthStack = *other.blockParenDepthStack;
397 
398     blockStatementStack = new vector<bool>;
399     *blockStatementStack = *other.blockStatementStack;
400 
401     parenStatementStack =  new vector<bool>;
402     *parenStatementStack = *other.parenStatementStack;
403 
404     bracketBlockStateStack = new vector<bool>;
405     *bracketBlockStateStack = *other.bracketBlockStateStack;
406 
407     inStatementIndentStack = new vector<int>;
408     *inStatementIndentStack = *other.inStatementIndentStack;
409 
410     inStatementIndentStackSizeStack = new vector<int>;
411     *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack;
412 
413     parenIndentStack = new vector<int>;
414     *parenIndentStack = *other.parenIndentStack;
415 
416     sourceIterator = other.sourceIterator;
417 
418     indentString = other.indentString;
419     currentHeader = other.currentHeader;
420     previousLastLineHeader = other.previousLastLineHeader;
421     immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp;
422     isInQuote = other.isInQuote;
423     isInComment = other.isInComment;
424     isInCase = other.isInCase;
425     isInQuestion = other.isInQuestion;
426     isInStatement =other. isInStatement;
427     isInHeader = other.isInHeader;
428     isCStyle = other.isCStyle;
429     isInOperator = other.isInOperator;
430     isInTemplate = other.isInTemplate;
431     isInConst = other.isInConst;
432     classIndent = other.classIndent;
433     isInClassHeader = other.isInClassHeader;
434     isInClassHeaderTab = other.isInClassHeaderTab;
435     switchIndent = other.switchIndent;
436     caseIndent = other.caseIndent;
437     namespaceIndent = other.namespaceIndent;
438     bracketIndent = other.bracketIndent;
439     blockIndent = other.blockIndent;
440     labelIndent = other.labelIndent;
441     preprocessorIndent = other.preprocessorIndent;
442     parenDepth = other.parenDepth;
443     indentLength = other.indentLength;
444     blockTabCount = other.blockTabCount;
445     leadingWhiteSpaces = other.leadingWhiteSpaces;
446     maxInStatementIndent = other.maxInStatementIndent;
447     templateDepth = other.templateDepth;
448     quoteChar = other.quoteChar;
449     prevNonSpaceCh = other.prevNonSpaceCh;
450     currentNonSpaceCh = other.currentNonSpaceCh;
451     currentNonLegalCh = other.currentNonLegalCh;
452     prevNonLegalCh = other.prevNonLegalCh;
453     isInConditional = other.isInConditional;
454     minConditionalIndent = other.minConditionalIndent;
455     prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount;
456     prevFinalLineTabCount = other.prevFinalLineTabCount;
457     emptyLineFill = other.emptyLineFill;
458     probationHeader = other.probationHeader;
459     isInDefine = other.isInDefine;
460     isInDefineDefinition = other.isInDefineDefinition;
461     backslashEndsPrevLine = other.backslashEndsPrevLine;
462     defineTabCount = other.defineTabCount;
463   }
464 
465   /**
466    * ASBeautifier's destructor
467    */
~ASBeautifier()468   ASBeautifier::~ASBeautifier()
469   {
470     DELETE_CONTAINER( headerStack );
471     DELETE_CONTAINER( tempStacks );
472     DELETE_CONTAINER( blockParenDepthStack );
473     DELETE_CONTAINER( blockStatementStack );
474     DELETE_CONTAINER( parenStatementStack );
475     DELETE_CONTAINER( bracketBlockStateStack );
476     DELETE_CONTAINER( inStatementIndentStack );
477     DELETE_CONTAINER( inStatementIndentStackSizeStack );
478     DELETE_CONTAINER( parenIndentStack );
479 
480     // DELETE_CONTAINER( sourceIterator );
481   }
482 
483   /**
484    * initialize the ASBeautifier.
485    *
486    * init() should be called every time a ABeautifier object is to start
487    * beautifying a NEW source file.
488    * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
489    * that will be used to iterate through the source code. This object will be
490    * deleted during the ASBeautifier's destruction, and thus should not be
491    * deleted elsewhere.
492    *
493    * @param iter     a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
494    */
init(ASSourceIterator * iter)495   void ASBeautifier::init(ASSourceIterator *iter)
496 
497   {
498     sourceIterator = iter;
499     init();
500   }
501 
502   /**
503    * initialize the ASBeautifier.
504    */
init()505   void ASBeautifier::init()
506   {
507     INIT_CONTAINER( waitingBeautifierStack,  new vector<ASBeautifier*> );
508     INIT_CONTAINER( activeBeautifierStack,  new vector<ASBeautifier*> );
509 
510     INIT_CONTAINER( waitingBeautifierStackLengthStack, new vector<int> );
511     INIT_CONTAINER( activeBeautifierStackLengthStack, new vector<int> );
512 
513     INIT_CONTAINER( headerStack,  new vector<const string*> );
514     INIT_CONTAINER( tempStacks, new vector< vector<const string*>* > );
515     tempStacks->push_back(new vector<const string*>);
516 
517     INIT_CONTAINER( blockParenDepthStack, new vector<int> );
518     INIT_CONTAINER( blockStatementStack, new vector<bool> );
519     INIT_CONTAINER( parenStatementStack, new vector<bool> );
520 
521     INIT_CONTAINER( bracketBlockStateStack, new vector<bool> );
522     bracketBlockStateStack->push_back(true);
523 
524     INIT_CONTAINER( inStatementIndentStack, new vector<int> );
525     INIT_CONTAINER( inStatementIndentStackSizeStack, new vector<int> );
526     inStatementIndentStackSizeStack->push_back(0);
527     INIT_CONTAINER( parenIndentStack, new vector<int> );
528 
529     immediatelyPreviousAssignmentOp = NULL;
530     previousLastLineHeader = NULL;
531 
532     isInQuote = false;
533     isInComment = false;
534     isInStatement = false;
535     isInCase = false;
536     isInQuestion = false;
537     isInClassHeader = false;
538     isInClassHeaderTab = false;
539     isInHeader = false;
540     isInOperator = false;
541     isInTemplate = false;
542     isInConst = false;
543     isInConditional = false;
544     templateDepth = 0;
545     parenDepth=0;
546     blockTabCount = 0;
547     leadingWhiteSpaces = 0;
548     prevNonSpaceCh = '{';
549     currentNonSpaceCh = '{';
550     prevNonLegalCh = '{';
551     currentNonLegalCh = '{';
552     prevFinalLineSpaceTabCount = 0;
553     prevFinalLineTabCount = 0;
554     probationHeader = NULL;
555     backslashEndsPrevLine = false;
556     isInDefine = false;
557     isInDefineDefinition = false;
558     defineTabCount = 0;
559   }
560 
561   /**
562    * set indentation style to ANSI C/C++.
563    */
setCStyle()564   void ASBeautifier::setCStyle()
565   {
566     isCStyle = true;
567   }
568 
569   /**
570    * set indentation style to Java / K&R.
571    */
setJavaStyle()572   void ASBeautifier::setJavaStyle()
573   {
574     isCStyle = false;
575   }
576 
577   /**
578    * indent using one tab per indentation
579    */
setTabIndentation(int length,bool forceTabs)580   void ASBeautifier::setTabIndentation(int length, bool forceTabs)
581   {
582     indentString = "\t";
583     indentLength = length;
584     shouldForceTabIndentation = forceTabs;
585 
586     if (!isMinimalConditinalIndentSet)
587       minConditionalIndent = indentLength * 2;
588   }
589 
590   /**
591 
592    * indent using a number of spaces per indentation.
593    *
594    * @param   length     number of spaces per indent.
595    */
setSpaceIndentation(int length)596   void ASBeautifier::setSpaceIndentation(int length)
597   {
598     indentString=string(length, ' ');
599     indentLength = length;
600 
601     if (!isMinimalConditinalIndentSet)
602       minConditionalIndent = indentLength * 2;
603   }
604 
605   /**
606    * set the maximum indentation between two lines in a multi-line statement.
607    *
608    * @param   max     maximum indentation length.
609    */
setMaxInStatementIndentLength(int max)610   void ASBeautifier::setMaxInStatementIndentLength(int max)
611   {
612     maxInStatementIndent = max;
613   }
614 
615   /**
616    * set the minimum indentation between two lines in a multi-line condition.
617    *
618    * @param   min     minimal indentation length.
619    */
setMinConditionalIndentLength(int min)620   void ASBeautifier::setMinConditionalIndentLength(int min)
621   {
622     minConditionalIndent = min;
623     isMinimalConditinalIndentSet = true;
624   }
625 
626   /**
627    * set the state of the bracket indentation option. If true, brackets will
628    * be indented one additional indent.
629    *
630    * @param   state             state of option.
631    */
setBracketIndent(bool state)632   void ASBeautifier::setBracketIndent(bool state)
633   {
634     bracketIndent = state;
635   }
636 
637   /**
638    * set the state of the block indentation option. If true, entire blocks
639    * will be indented one additional indent, similar to the GNU indent style.
640    *
641    * @param   state             state of option.
642    */
setBlockIndent(bool state)643   void ASBeautifier::setBlockIndent(bool state)
644   {
645     if (state)
646       setBracketIndent(false); // so that we don't have both bracket and block indent
647     blockIndent = state;
648   }
649 
650   /**
651    * set the state of the class indentation option. If true, C++ class
652    * definitions will be indented one additional indent.
653    *
654    * @param   state             state of option.
655    */
setClassIndent(bool state)656   void ASBeautifier::setClassIndent(bool state)
657   {
658     classIndent = state;
659   }
660 
661   /**
662    * set the state of the switch indentation option. If true, blocks of 'switch'
663    * statements will be indented one additional indent.
664    *
665    * @param   state             state of option.
666    */
setSwitchIndent(bool state)667   void ASBeautifier::setSwitchIndent(bool state)
668   {
669     switchIndent = state;
670   }
671 
672   /**
673    * set the state of the case indentation option. If true, lines of 'case'
674    * statements will be indented one additional indent.
675    *
676    * @param   state             state of option.
677    */
setCaseIndent(bool state)678   void ASBeautifier::setCaseIndent(bool state)
679   {
680     caseIndent = state;
681   }
682   /**
683    * set the state of the namespace indentation option.
684    * If true, blocks of 'namespace' statements will be indented one
685    * additional indent. Otherwise, NO indentation will be added.
686    *
687    * @param   state             state of option.
688    */
setNamespaceIndent(bool state)689   void ASBeautifier::setNamespaceIndent(bool state)
690   {
691     namespaceIndent = state;
692   }
693 
694   /**
695    * set the state of the label indentation option.
696    * If true, labels will be indented one indent LESS than the
697    * current indentation level.
698    * If false, labels will be flushed to the left with NO
699    * indent at all.
700    *
701    * @param   state             state of option.
702    */
setLabelIndent(bool state)703   void ASBeautifier::setLabelIndent(bool state)
704   {
705     labelIndent = state;
706   }
707 
708   /**
709    * set the state of the preprocessor indentation option.
710    * If true, multiline #define statements will be indented.
711    *
712    * @param   state             state of option.
713    */
setPreprocessorIndent(bool state)714   void ASBeautifier::setPreprocessorIndent(bool state)
715   {
716     preprocessorIndent = state;
717   }
718 
719   /**
720    * set the state of the empty line fill option.
721    * If true, empty lines will be filled with the whitespace.
722    * of their previous lines.
723    * If false, these lines will remain empty.
724    *
725    * @param   state             state of option.
726    */
setEmptyLineFill(bool state)727   void ASBeautifier::setEmptyLineFill(bool state)
728   {
729     emptyLineFill = state;
730   }
731 
732   /**
733    * check if there are any indented lines ready to be read by nextLine()
734    *
735    * @return    are there any indented lines ready?
736    */
hasMoreLines() const737   bool ASBeautifier::hasMoreLines() const
738     {
739       return sourceIterator->hasMoreLines();
740     }
741 
742   /**
743    * get the next indented line.
744    *
745    * @return    indented line.
746    */
nextLine()747   string ASBeautifier::nextLine()
748   {
749     return beautify(sourceIterator->nextLine());
750   }
751 
752   /**
753    * beautify a line of source code.
754    * every line of source code in a source code file should be sent
755    * one after the other to the beautify method.
756    *
757    * @return      the indented line.
758    * @param originalLine       the original unindented line.
759    */
beautify(const string & originalLine)760   string ASBeautifier::beautify(const string &originalLine)
761   {
762     string line;
763     bool isInLineComment = false;
764     bool lineStartsInComment = false;
765     bool isInClass = false;
766     bool isInSwitch = false;
767     bool isImmediatelyAfterConst = false;
768     bool isSpecialChar = false;
769 
770     char ch = ' ';
771     char prevCh;
772     string outBuffer; // the newly idented line is bufferd here
773     int tabCount = 0;
774     const string *lastLineHeader = NULL;
775     bool closingBracketReached = false;
776     int spaceTabCount = 0;
777     char tempCh;
778     unsigned int headerStackSize = headerStack->size();
779     //bool isLineInStatement = isInStatement;
780     bool shouldIndentBrackettedLine = true;
781     int lineOpeningBlocksNum = 0;
782     int lineClosingBlocksNum = 0;
783     bool previousLineProbation = (probationHeader != NULL);
784     unsigned int i;
785 
786     currentHeader = NULL;
787 
788     lineStartsInComment = isInComment;
789 
790     // handle and remove white spaces around the line:
791     // If not in comment, first find out size of white space before line,
792     // so that possible comments starting in the line continue in
793     // relation to the preliminary white-space.
794     if (!isInComment)
795       {
796         leadingWhiteSpaces = 0;
797         while (leadingWhiteSpaces<originalLine.length() && originalLine[leadingWhiteSpaces] <= 0x20)
798           leadingWhiteSpaces++;
799 
800         line = trim(originalLine);
801       }
802     else
803       {
804         unsigned int trimSize;
805         for (trimSize=0;
806              trimSize < originalLine.length() && trimSize<leadingWhiteSpaces && originalLine[trimSize] <= 0x20 ;
807              trimSize++)
808           ;
809         line = originalLine.substr(trimSize);
810       }
811 
812 
813     if (line.length() == 0)
814       {
815         if (emptyLineFill)
816           return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount);
817         else
818           return line;
819       }
820 
821     // handle preprocessor commands
822 
823     if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine))
824       {
825         if (line[0] == '#')
826           {
827             string preproc = trim(string(line.c_str() + 1));
828 
829 
830             // When finding a multi-lined #define statement, the original beautifier
831             // 1. sets its isInDefineDefinition flag
832             // 2. clones a new beautifier that will be used for the actual indentation
833             //    of the #define. This clone is put into the activeBeautifierStack in order
834             //    to be called for the actual indentation.
835             // The original beautifier will have isInDefineDefinition = true, isInDefine = false
836             // The cloned beautifier will have   isInDefineDefinition = true, isInDefine = true
837             if (preprocessorIndent && preproc.COMPARE(0, 6, string("define")) == 0 &&  line[line.length() - 1] == '\\')
838               {
839                 if (!isInDefineDefinition)
840                   {
841                     ASBeautifier *defineBeautifier;
842 
843                     // this is the original beautifier
844                     isInDefineDefinition = true;
845 
846                     // push a new beautifier into the active stack
847                     // this breautifier will be used for the indentation of this define
848                     defineBeautifier = new ASBeautifier(*this);
849                     //defineBeautifier->init();
850                     //defineBeautifier->isInDefineDefinition = true;
851                     //defineBeautifier->beautify("");
852                     activeBeautifierStack->push_back(defineBeautifier);
853                   }
854                 else
855                   {
856                     // the is the cloned beautifier that is in charge of indenting the #define.
857                     isInDefine = true;
858                   }
859               }
860             else if (preproc.COMPARE(0, 2, string("if")) == 0)
861               {
862                 // push a new beautifier into the stack
863                 waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size());
864                 activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size());
865                 waitingBeautifierStack->push_back(new ASBeautifier(*this));
866               }
867             else if (preproc.COMPARE(0, 4/*2*/, string("else")) == 0)
868               {
869                 if (!waitingBeautifierStack->empty())
870                   {
871                     // MOVE current waiting beautifier to active stack.
872                     activeBeautifierStack->push_back(waitingBeautifierStack->back());
873                     waitingBeautifierStack->pop_back();
874                   }
875               }
876             else if (preproc.COMPARE(0, 4, string("elif")) == 0)
877               {
878                 if (!waitingBeautifierStack->empty())
879                   {
880                     // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original.
881                     activeBeautifierStack->push_back( new ASBeautifier( *(waitingBeautifierStack->back()) ) );
882                   }
883               }
884             else if (preproc.COMPARE(0, 5, string("endif")) == 0)
885               {
886                 unsigned int stackLength;
887                 ASBeautifier *beautifier;
888 
889                 if (!waitingBeautifierStackLengthStack->empty())
890                   {
891                     stackLength = waitingBeautifierStackLengthStack->back();
892                     waitingBeautifierStackLengthStack->pop_back();
893                     while (waitingBeautifierStack->size() > stackLength)
894                       {
895                         beautifier = waitingBeautifierStack->back();
896                         waitingBeautifierStack->pop_back();
897                         delete beautifier;
898                       }
899                   }
900 
901                 if (!activeBeautifierStackLengthStack->empty())
902                   {
903                     stackLength = activeBeautifierStackLengthStack->back();
904                     activeBeautifierStackLengthStack->pop_back();
905                     while (activeBeautifierStack->size() > stackLength)
906                       {
907                         beautifier = activeBeautifierStack->back();
908                         activeBeautifierStack->pop_back();
909                         delete beautifier;
910                       }
911                   }
912 
913 
914               }
915           }
916 
917         // check if the last char is a backslash
918         if(line.length() > 0)
919           backslashEndsPrevLine = (line[line.length() - 1] == '\\');
920         else
921           backslashEndsPrevLine = false;
922 
923         // check if this line ends a multi-line #define
924         // if so, use the #define's cloned beautifier for the line's indentation
925         // and then remove it from the active beautifier stack and delete it.
926         if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine)
927           {
928             string beautifiedLine;
929             ASBeautifier *defineBeautifier;
930 
931             isInDefineDefinition = false;
932             defineBeautifier = activeBeautifierStack->back();
933             activeBeautifierStack->pop_back();
934 
935             beautifiedLine = defineBeautifier->beautify(line);
936             delete defineBeautifier;
937             return beautifiedLine;
938           }
939 
940         // unless this is a multi-line #define, return this precompiler line as is.
941         if (!isInDefine && !isInDefineDefinition)
942           return originalLine;
943       }
944 
945     // if there exists any worker beautifier in the activeBeautifierStack,
946     // then use it instead of me to indent the current line.
947     if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty())
948       {
949         return activeBeautifierStack->back()->beautify(line);
950       }
951 
952     // calculate preliminary indentation based on data from past lines
953     if (!inStatementIndentStack->empty())
954       spaceTabCount = inStatementIndentStack->back();
955 
956 
957     for (i=0; i<headerStackSize; i++)
958       {
959         isInClass = false;
960 
961         if (blockIndent || (!(i>0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
962                               && (*headerStack)[i] == &AS_OPEN_BRACKET)))
963           ++tabCount;
964 
965         if (isCStyle && !namespaceIndent && i >= 1
966             && (*headerStack)[i-1] == &AS_NAMESPACE
967             && (*headerStack)[i] == &AS_OPEN_BRACKET)
968           --tabCount;
969 
970         if (isCStyle && i >= 1
971             && (*headerStack)[i-1] == &AS_CLASS
972             && (*headerStack)[i] == &AS_OPEN_BRACKET )
973           {
974             if (classIndent)
975               ++tabCount;
976             isInClass = true;
977           }
978 
979         // is the switchIndent option is on, indent switch statements an additional indent.
980         else if (switchIndent && i > 1 &&
981                  (*headerStack)[i-1] == &AS_SWITCH &&
982                  (*headerStack)[i] == &AS_OPEN_BRACKET
983                 )
984           {
985             ++tabCount;
986             isInSwitch = true;
987           }
988 
989       }
990 
991     if (!lineStartsInComment
992         && isCStyle
993         && isInClass
994         && classIndent
995         && headerStackSize >= 2
996         &&(*headerStack)[headerStackSize-2] == &AS_CLASS
997         && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
998         && line[0] == '}')
999       --tabCount;
1000 
1001     else if (!lineStartsInComment
1002              && isInSwitch
1003              && switchIndent
1004              && headerStackSize >= 2
1005              && (*headerStack)[headerStackSize-2] == &AS_SWITCH
1006              && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
1007              && line[0] == '}')
1008       --tabCount;
1009 
1010     if (isInClassHeader)
1011       {
1012         isInClassHeaderTab = true;
1013         tabCount += 2;
1014       }
1015 
1016     if (isInConditional)
1017       {
1018         --tabCount;
1019       }
1020 
1021 
1022     // parse characters in the current line.
1023 
1024     for (i=0; i<line.length(); i++)
1025       {
1026         tempCh = line[i];
1027 
1028         prevCh = ch;
1029         ch = tempCh;
1030 
1031         outBuffer.append(1, ch);
1032 
1033         if (isWhiteSpace(ch))
1034           continue;
1035 
1036 
1037         // handle special characters (i.e. backslash+character such as \n, \t, ...)
1038         if (isSpecialChar)
1039           {
1040             isSpecialChar = false;
1041             continue;
1042           }
1043         if (!(isInComment || isInLineComment) && line.COMPARE(i, 2, string("\\\\")) == 0)
1044           {
1045             outBuffer.append(1, '\\');
1046             i++;
1047             continue;
1048           }
1049         if (!(isInComment || isInLineComment) && ch=='\\')
1050           {
1051             isSpecialChar = true;
1052             continue;
1053           }
1054 
1055         // handle quotes (such as 'x' and "Hello Dolly")
1056         if (!(isInComment || isInLineComment) && (ch=='"' || ch=='\''))
1057           if (!isInQuote)
1058             {
1059               quoteChar = ch;
1060               isInQuote = true;
1061             }
1062           else if (quoteChar == ch)
1063             {
1064               isInQuote = false;
1065               isInStatement = true;
1066               continue;
1067             }
1068         if (isInQuote)
1069           continue;
1070 
1071         // handle comments
1072 
1073         if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_LINE_COMMENT) == 0 )
1074           {
1075             isInLineComment = true;
1076             outBuffer.append(1, '/');
1077             i++;
1078             continue;
1079           }
1080         else if ( !(isInComment || isInLineComment) && line.COMPARE(i, 2, AS_OPEN_COMMENT) == 0 )
1081           {
1082             isInComment = true;
1083             outBuffer.append(1, '*');
1084             i++;
1085             continue;
1086           }
1087         else if ( (isInComment || isInLineComment) && line.COMPARE(i, 2, AS_CLOSE_COMMENT) == 0 )
1088           {
1089             isInComment = false;
1090             outBuffer.append(1, '/');
1091             i++;
1092             continue;
1093           }
1094 
1095         if (isInComment||isInLineComment)
1096           continue;
1097 
1098         // if we have reached this far then we are NOT in a comment or string of special character...
1099 
1100         if (probationHeader != NULL)
1101           {
1102             if ( ((probationHeader == &AS_STATIC || probationHeader == &AS_CONST) && ch == '{')
1103                  || (probationHeader == &AS_SYNCHRONIZED && ch == '('))
1104               {
1105                 // insert the probation header as a new header
1106                 isInHeader = true;
1107                 headerStack->push_back(probationHeader);
1108 
1109                 // handle the specific probation header
1110                 isInConditional = (probationHeader == &AS_SYNCHRONIZED);
1111                 if (probationHeader == &AS_CONST)
1112                   isImmediatelyAfterConst = true;
1113                 //  isInConst = true;
1114                 /* TODO:
1115                  * There is actually no more need for the global isInConst variable.
1116                                * The only reason for checking const is to see if there is a const
1117                  * immediately before an open-bracket.
1118                  * Since CONST is now put into probation and is checked during itspost-char,
1119                  * isImmediatelyAfterConst can be set by its own...
1120                  */
1121 
1122                 isInStatement = false;
1123                 // if the probation comes from the previous line, then indent by 1 tab count.
1124                 if (previousLineProbation && ch == '{')
1125                   tabCount++;
1126                 previousLineProbation = false;
1127               }
1128 
1129             // dismiss the probation header
1130             probationHeader = NULL;
1131           }
1132 
1133         prevNonSpaceCh = currentNonSpaceCh;
1134         currentNonSpaceCh = ch;
1135         if (!isLegalNameChar(ch) && ch != ',' && ch != ';' )
1136           {
1137             prevNonLegalCh = currentNonLegalCh;
1138             currentNonLegalCh = ch;
1139           }
1140 
1141         //if (isInConst)
1142         //{
1143         //    isInConst = false;
1144         //    isImmediatelyAfterConst = true;
1145         //}
1146 
1147         if (isInHeader)
1148           {
1149             isInHeader = false;
1150             currentHeader = headerStack->back();
1151           }
1152         else
1153           currentHeader = NULL;
1154 
1155         if (isCStyle && isInTemplate
1156             && (ch == '<' || ch == '>')
1157             &&  findHeader(line, i, nonAssignmentOperators) == NULL) //;
1158           {
1159             if (ch == '<')
1160               {
1161                 ++templateDepth;
1162               }
1163             else if (ch == '>')
1164               {
1165                 if (--templateDepth <= 0)
1166                   {
1167                     if (isInTemplate)
1168                       ch = ';';
1169                     else
1170                       ch = 't';
1171                     isInTemplate = false;
1172                     templateDepth = 0;
1173                   }
1174 
1175               }
1176           }
1177 
1178         // handle parenthesies
1179         if (ch == '(' || ch == '[' || ch == ')' || ch == ']')
1180           {
1181             if (ch == '(' || ch == '[')
1182               {
1183                 if (parenDepth == 0)
1184                   {
1185                     parenStatementStack->push_back(isInStatement);
1186                     isInStatement = true;
1187                   }
1188                 parenDepth++;
1189 
1190                 inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
1191 
1192                 if (currentHeader != NULL)
1193                   registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true);
1194                 else
1195                   registerInStatementIndent(line, i, spaceTabCount, 0, true);
1196               }
1197             else if (ch == ')' || ch == ']')
1198               {
1199                 parenDepth--;
1200                 if (parenDepth == 0)
1201                   {
1202                     isInStatement = parenStatementStack->back();
1203                     parenStatementStack->pop_back();
1204                     ch = ' ';
1205 
1206                     isInConditional = false;
1207                   }
1208 
1209                 if (!inStatementIndentStackSizeStack->empty())
1210                   {
1211                     unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back();
1212                     inStatementIndentStackSizeStack->pop_back();
1213                     while (previousIndentStackSize < inStatementIndentStack->size())
1214                       inStatementIndentStack->pop_back();
1215 
1216                     if (!parenIndentStack->empty())
1217                       {
1218                         int poppedIndent = parenIndentStack->back();
1219                         parenIndentStack->pop_back();
1220 
1221                         if (i == 0)
1222                           spaceTabCount = poppedIndent;
1223                       }
1224                   }
1225               }
1226 
1227             continue;
1228           }
1229 
1230 
1231         if (ch == '{')
1232           {
1233             bool isBlockOpener = false;
1234 
1235             // first, check if '{' is a block-opener or an static-array opener
1236             isBlockOpener = ( (prevNonSpaceCh == '{' && bracketBlockStateStack->back())
1237                               || prevNonSpaceCh == '}'
1238                               || prevNonSpaceCh == ')'
1239                               || prevNonSpaceCh == ';'
1240                               || isInClassHeader
1241                               || isBlockOpener
1242                               || isImmediatelyAfterConst
1243                               || (isInDefine &&
1244                                   (prevNonSpaceCh == '('
1245                                    || prevNonSpaceCh == '_'
1246                                    || isalnum(prevNonSpaceCh))) );
1247 
1248             isInClassHeader = false;
1249             if (!isBlockOpener && currentHeader != NULL)
1250               {
1251                 for (unsigned int n=0; n < nonParenHeaders.size(); n++)
1252                   if (currentHeader == nonParenHeaders[n])
1253                     {
1254                       isBlockOpener = true;
1255                       break;
1256                     }
1257               }
1258             bracketBlockStateStack->push_back(isBlockOpener);
1259             if (!isBlockOpener)
1260               {
1261                 inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
1262                 registerInStatementIndent(line, i, spaceTabCount, 0, true);
1263                 parenDepth++;
1264                 if (i == 0)
1265                   shouldIndentBrackettedLine = false;
1266 
1267                 continue;
1268               }
1269 
1270             // this bracket is a block opener...
1271 
1272             ++lineOpeningBlocksNum;
1273 
1274             if (isInClassHeader)
1275               isInClassHeader = false;
1276             if (isInClassHeaderTab)
1277               {
1278                 isInClassHeaderTab = false;
1279                 tabCount -= 2;
1280               }
1281 
1282             blockParenDepthStack->push_back(parenDepth);
1283             blockStatementStack->push_back(isInStatement);
1284 
1285             inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
1286 
1287             blockTabCount += isInStatement? 1 : 0;
1288             parenDepth = 0;
1289             isInStatement = false;
1290 
1291             tempStacks->push_back(new vector<const string*>);
1292             headerStack->push_back(&AS_OPEN_BRACKET);
1293             lastLineHeader = &AS_OPEN_BRACKET; // <------
1294 
1295             continue;
1296           }
1297 
1298         //check if a header has been reached
1299         if (prevCh == ' ')
1300           {
1301             bool isIndentableHeader = true;
1302             const string *newHeader = findHeader(line, i, headers);
1303             if (newHeader != NULL)
1304               {
1305                 // if we reached here, then this is a header...
1306                 isInHeader = true;
1307 
1308                 vector<const string*> *lastTempStack;
1309                 if (tempStacks->empty())
1310                   lastTempStack = NULL;
1311                 else
1312                   lastTempStack = tempStacks->back();
1313 
1314                 // if a new block is opened, push a new stack into tempStacks to hold the
1315                 // future list of headers in the new block.
1316 
1317                 // take care of the special case: 'else if (...)'
1318                 if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE)
1319                   {
1320                     //spaceTabCount += indentLength; // to counter the opposite addition that occurs when the 'if' is registered below...
1321                     headerStack->pop_back();
1322                   }
1323 
1324                 // take care of 'else'
1325                 else if (newHeader == &AS_ELSE)
1326                   {
1327                     if (lastTempStack != NULL)
1328                       {
1329                         int indexOfIf = indexOf(*lastTempStack, &AS_IF); // <---
1330                         if (indexOfIf != -1)
1331                           {
1332                             // recreate the header list in headerStack up to the previous 'if'
1333                             // from the temporary snapshot stored in lastTempStack.
1334                             int restackSize = lastTempStack->size() - indexOfIf - 1;
1335                             for (int r=0; r<restackSize; r++)
1336                               {
1337                                 headerStack->push_back(lastTempStack->back());
1338                                 lastTempStack->pop_back();
1339                               }
1340                             if (!closingBracketReached)
1341                               tabCount += restackSize;
1342                           }
1343                         /*
1344                          * If the above if is not true, i.e. no 'if' before the 'else',
1345                          * then nothing beautiful will come out of this...
1346                          * I should think about inserting an Exception here to notify the caller of this...
1347                          */
1348                       }
1349                   }
1350 
1351                 // check if 'while' closes a previous 'do'
1352                 else if (newHeader == &AS_WHILE)
1353                   {
1354                     if (lastTempStack != NULL)
1355                       {
1356                         int indexOfDo = indexOf(*lastTempStack, &AS_DO); // <---
1357                         if (indexOfDo != -1)
1358                           {
1359                             // recreate the header list in headerStack up to the previous 'do'
1360                             // from the temporary snapshot stored in lastTempStack.
1361                             int restackSize = lastTempStack->size() - indexOfDo - 1;
1362                             for (int r=0; r<restackSize; r++)
1363                               {
1364                                 headerStack->push_back(lastTempStack->back());
1365                                 lastTempStack->pop_back();
1366                               }
1367                             if (!closingBracketReached)
1368                               tabCount += restackSize;
1369                           }
1370                       }
1371                   }
1372                 // check if 'catch' closes a previous 'try' or 'catch'
1373                 else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY)
1374                   {
1375                     if (lastTempStack != NULL)
1376                       {
1377                         int indexOfTry = indexOf(*lastTempStack, &AS_TRY);
1378                         if (indexOfTry == -1)
1379                           indexOfTry = indexOf(*lastTempStack, &AS_CATCH);
1380                         if (indexOfTry != -1)
1381                           {
1382                             // recreate the header list in headerStack up to the previous 'try'
1383                             // from the temporary snapshot stored in lastTempStack.
1384                             int restackSize = lastTempStack->size() - indexOfTry - 1;
1385                             for (int r=0; r<restackSize; r++)
1386                               {
1387                                 headerStack->push_back(lastTempStack->back());
1388                                 lastTempStack->pop_back();
1389                               }
1390 
1391                             if (!closingBracketReached)
1392                               tabCount += restackSize;
1393                           }
1394                       }
1395                   }
1396                 else if (newHeader == &AS_CASE)
1397                   {
1398                     isInCase = true;
1399                     if (!caseIndent)
1400                       --tabCount;
1401                   }
1402                 else if(newHeader == &AS_DEFAULT)
1403                   {
1404                     isInCase = true;
1405                     if (!caseIndent)
1406                       --tabCount;
1407                   }
1408                 else if (newHeader == &AS_PUBLIC || newHeader == &AS_PROTECTED || newHeader == &AS_PRIVATE)
1409                   {
1410                     if (isCStyle && !isInClassHeader)
1411                       --tabCount;
1412                     isIndentableHeader = false;
1413                   }
1414                 //else if ((newHeader == &STATIC || newHeader == &SYNCHRONIZED) &&
1415                 //         !headerStack->empty() &&
1416                 //         (headerStack->back() == &STATIC || headerStack->back() == &SYNCHRONIZED))
1417                 //{
1418                 //    isIndentableHeader = false;
1419                 //}
1420                 else if (newHeader == &AS_STATIC
1421                          || newHeader == &AS_SYNCHRONIZED
1422                          || (newHeader == &AS_CONST && isCStyle))
1423                   {
1424                     if (!headerStack->empty() &&
1425                         (headerStack->back() == &AS_STATIC
1426                          || headerStack->back() == &AS_SYNCHRONIZED
1427                          || headerStack->back() == &AS_CONST))
1428                       {
1429                         isIndentableHeader = false;
1430                       }
1431                     else
1432                       {
1433                         isIndentableHeader = false;
1434                         probationHeader = newHeader;
1435                       }
1436                   }
1437                 else if (newHeader == &AS_CONST)
1438                   {
1439                     // this will be entered only if NOT in C style
1440                     // since otherwise the CONST would be found to be a probstion header...
1441 
1442                     //if (isCStyle)
1443                     //  isInConst = true;
1444                     isIndentableHeader = false;
1445                   }
1446                 /*
1447                               else if (newHeader == &OPERATOR)
1448                               {
1449                                   if (isCStyle)
1450                                       isInOperator = true;
1451                                   isIndentableHeader = false;
1452                               }
1453                 */
1454                 else if (newHeader == &AS_TEMPLATE)
1455                   {
1456                     if (isCStyle)
1457                       isInTemplate = true;
1458                     isIndentableHeader = false;
1459                   }
1460 
1461 
1462                 if (isIndentableHeader)
1463                   {
1464                     // 3.2.99
1465                     //spaceTabCount-=indentLength;
1466                     headerStack->push_back(newHeader);
1467                     isInStatement = false;
1468                     if (indexOf(nonParenHeaders, newHeader) == -1)
1469                       {
1470                         isInConditional = true;
1471                       }
1472                     lastLineHeader = newHeader;
1473                   }
1474                 else
1475                   isInHeader = false;
1476 
1477                 //lastLineHeader = newHeader;
1478 
1479                 outBuffer.append(newHeader->substr(1));
1480                 i += newHeader->length() - 1;
1481 
1482                 continue;
1483               }
1484           }
1485 
1486         if (isCStyle && !isalpha(prevCh)
1487             && line.COMPARE(i, 8, AS_OPERATOR) == 0 && !isalnum(line[i+8]))
1488           {
1489             isInOperator = true;
1490             outBuffer.append(AS_OPERATOR.substr(1));
1491             i += 7;
1492             continue;
1493           }
1494 
1495         if (ch == '?')
1496           isInQuestion = true;
1497 
1498 
1499         // special handling of 'case' statements
1500         if (ch == ':')
1501           {
1502             if (line.length() > i+1 && line[i+1] == ':') // look for ::
1503               {
1504                 ++i;
1505                 outBuffer.append(1, ':');
1506                 ch = ' ';
1507                 continue;
1508               }
1509 
1510             else if (isCStyle && isInClass && prevNonSpaceCh != ')')
1511               {
1512               // BEGIN Content of ASBeautifier.cpp.BITFIELD.patch:
1513 
1514                 unsigned int chIndex;
1515    			    char nextCh = 0;
1516                 for (chIndex = i+1; chIndex < line.length(); chIndex++)
1517             		if (!isWhiteSpace(line[chIndex]))
1518 						break;
1519 					if (chIndex< line.length())
1520        					nextCh = line[chIndex];
1521 				int nWord =0;
1522     			for (chIndex = 0; chIndex < i; chIndex++)
1523 				{
1524 					if (!isWhiteSpace(line[chIndex]))
1525 					{
1526 						nWord ++;
1527 						while (!isWhiteSpace(line[++chIndex]));
1528 					}
1529 				}
1530 				if ((nextCh >= '0' && nextCh <= '9') || (nWord >1))
1531 					continue;
1532               // END Content of ASBeautifier.cpp.BITFIELD.patch:
1533 
1534                 --tabCount;
1535                 // found a 'private:' or 'public:' inside a class definition
1536                 // so do nothing special
1537               }
1538 
1539             else if (isCStyle && isInClassHeader)
1540               {
1541 
1542                 // found a 'class A : public B' definition
1543                 // so do nothing special
1544               }
1545 
1546             else if (isInQuestion)
1547               {
1548                 isInQuestion = false;
1549               }
1550             else if (isCStyle && prevNonSpaceCh == ')')
1551               {
1552                 isInClassHeader = true;
1553                 if (i==0)
1554                   tabCount += 2;
1555               }
1556             else
1557               {
1558                 currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers
1559                 if (isInCase)
1560                   {
1561                     isInCase = false;
1562                     ch = ';'; // from here on, treat char as ';'
1563                   }
1564               // BEGIN content of ASBeautifier.cpp.BITFIELD.patch.bz2
1565               else // bitfield or labels
1566 								{
1567 				unsigned int chIndex;
1568 				char nextCh = 0;
1569 				for (chIndex = i+1; (isCStyle && chIndex < line.length()); chIndex++)
1570 					if (!isWhiteSpace(line[chIndex]))
1571 						break;
1572 				if (chIndex< line.length())
1573 					nextCh = line[chIndex];
1574 
1575      			int nWord =0;
1576  				for (chIndex = 0; chIndex < i; chIndex++)
1577 				{
1578 					if (!isWhiteSpace(line[chIndex]))
1579 					{
1580 						nWord ++;
1581 						while (!isWhiteSpace(line[++chIndex]));
1582 					}
1583 				}
1584          		if (isCStyle &&  (nextCh >= '0' && nextCh <= '9') || (nWord >1))
1585 				{
1586 					continue;
1587 				}
1588                 // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2
1589 
1590                 else // is in a label (e.g. 'label1:')
1591                   {
1592                     if (labelIndent)
1593                       --tabCount; // unindent label by one indent
1594                     else
1595                       tabCount = 0; // completely flush indent to left
1596                   }
1597 
1598               // BEGIN content of ASASBeautifier.cpp.BITFIELD.patch.bz2
1599                 }
1600             // END content of ASASBeautifier.cpp.BITFIELD.patch.bz2
1601 
1602               }
1603           }
1604 
1605         if ((ch == ';'  || (parenDepth>0 && ch == ','))  && !inStatementIndentStackSizeStack->empty())
1606           while ((unsigned int)inStatementIndentStackSizeStack->back() + (parenDepth>0 ? 1 : 0)  < inStatementIndentStack->size())
1607             inStatementIndentStack->pop_back();
1608 
1609 
1610         // handle ends of statements
1611         if ( (ch == ';' && parenDepth == 0) || ch == '}'/* || (ch == ',' && parenDepth == 0)*/)
1612           {
1613             if (ch == '}')
1614               {
1615                 // first check if this '}' closes a previous block, or a static array...
1616                 if (!bracketBlockStateStack->empty())
1617                   {
1618                     bool bracketBlockState = bracketBlockStateStack->back();
1619                     bracketBlockStateStack->pop_back();
1620                     if (!bracketBlockState)
1621                       {
1622                         if (!inStatementIndentStackSizeStack->empty())
1623                           {
1624                             // this bracket is a static array
1625 
1626                             unsigned int previousIndentStackSize = inStatementIndentStackSizeStack->back();
1627                             inStatementIndentStackSizeStack->pop_back();
1628                             while (previousIndentStackSize < inStatementIndentStack->size())
1629                               inStatementIndentStack->pop_back();
1630                             parenDepth--;
1631                             if (i == 0)
1632                               shouldIndentBrackettedLine = false;
1633 
1634                             if (!parenIndentStack->empty())
1635                               {
1636                                 int poppedIndent = parenIndentStack->back();
1637                                 parenIndentStack->pop_back();
1638                                 if (i == 0)
1639                                   spaceTabCount = poppedIndent;
1640                               }
1641                           }
1642                         continue;
1643                       }
1644                   }
1645 
1646                 // this bracket is block closer...
1647 
1648                 ++lineClosingBlocksNum;
1649 
1650                 if(!inStatementIndentStackSizeStack->empty())
1651                   inStatementIndentStackSizeStack->pop_back();
1652 
1653                 if (!blockParenDepthStack->empty())
1654                   {
1655                     parenDepth = blockParenDepthStack->back();
1656                     blockParenDepthStack->pop_back();
1657                     isInStatement = blockStatementStack->back();
1658                     blockStatementStack->pop_back();
1659 
1660                     if (isInStatement)
1661                       blockTabCount--;
1662                   }
1663 
1664                 closingBracketReached = true;
1665                 int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET); // <---
1666                 if (headerPlace != -1)
1667                   {
1668                     const string *popped = headerStack->back();
1669                     while (popped != &AS_OPEN_BRACKET)
1670                       {
1671                         headerStack->pop_back();
1672                         popped = headerStack->back();
1673                       }
1674                     headerStack->pop_back();
1675 
1676                     if (!tempStacks->empty())
1677                       {
1678                         vector<const string*> *temp =  tempStacks->back();
1679                         tempStacks->pop_back();
1680                         delete temp;
1681                       }
1682                   }
1683 
1684 
1685                 ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified...
1686               }
1687 
1688             /*
1689              * Create a temporary snapshot of the current block's header-list in the
1690              * uppermost inner stack in tempStacks, and clear the headerStack up to
1691              * the begining of the block.
1692              * Thus, the next future statement will think it comes one indent past
1693              * the block's '{' unless it specifically checks for a companion-header
1694              * (such as a previous 'if' for an 'else' header) within the tempStacks,
1695              * and recreates the temporary snapshot by manipulating the tempStacks.
1696              */
1697             if (!tempStacks->back()->empty())
1698               while (!tempStacks->back()->empty())
1699                 tempStacks->back()->pop_back();
1700             while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET)
1701               {
1702                 tempStacks->back()->push_back(headerStack->back());
1703                 headerStack->pop_back();
1704               }
1705 
1706             if (parenDepth == 0 && ch == ';')
1707               isInStatement=false;
1708 
1709             isInClassHeader = false;
1710 
1711             continue;
1712           }
1713 
1714 
1715         // check for preBlockStatements ONLY if not within parenthesies
1716         // (otherwise 'struct XXX' statements would be wrongly interpreted...)
1717         if (prevCh == ' ' && !isInTemplate && parenDepth == 0)
1718           {
1719             const string *newHeader = findHeader(line, i, preBlockStatements);
1720             if (newHeader != NULL)
1721               {
1722                 isInClassHeader = true;
1723                 outBuffer.append(newHeader->substr(1));
1724                 i += newHeader->length() - 1;
1725                 //if (isCStyle)
1726                 headerStack->push_back(newHeader);
1727               }
1728           }
1729 
1730         // Handle operators
1731         //
1732 
1733         ////        // PRECHECK if a '==' or '--' or '++' operator was reached.
1734         ////        // If not, then register an indent IF an assignment operator was reached.
1735         ////        // The precheck is important, so that statements such as 'i--==2' are not recognized
1736         ////        // to have assignment operators (here, '-=') in them . . .
1737 
1738         const string *foundAssignmentOp = NULL;
1739         const string *foundNonAssignmentOp = NULL;
1740 
1741         immediatelyPreviousAssignmentOp = NULL;
1742 
1743         // Check if an operator has been reached.
1744         foundAssignmentOp = findHeader(line, i, assignmentOperators, false);
1745         foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false);
1746 
1747         // Since findHeader's boundry checking was not used above, it is possible
1748         // that both an assignment op and a non-assignment op where found,
1749         // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
1750         // found operator.
1751         if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
1752           if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
1753             foundAssignmentOp = NULL;
1754           else
1755             foundNonAssignmentOp = NULL;
1756 
1757         if (foundNonAssignmentOp != NULL)
1758           {
1759             if (foundNonAssignmentOp->length() > 1)
1760               {
1761                 outBuffer.append(foundNonAssignmentOp->substr(1));
1762                 i += foundNonAssignmentOp->length() - 1;
1763               }
1764           }
1765 
1766         else if (foundAssignmentOp != NULL)
1767 
1768           {
1769             if (foundAssignmentOp->length() > 1)
1770               {
1771                 outBuffer.append(foundAssignmentOp->substr(1));
1772                 i += foundAssignmentOp->length() - 1;
1773               }
1774 
1775             if (!isInOperator && !isInTemplate)
1776               {
1777                 registerInStatementIndent(line, i, spaceTabCount, 0, false);
1778                 immediatelyPreviousAssignmentOp = foundAssignmentOp;
1779                 isInStatement = true;
1780               }
1781           }
1782 
1783         /*
1784                 immediatelyPreviousAssignmentOp = NULL;
1785                 bool isNonAssingmentOperator = false;
1786                 for (int n = 0; n < nonAssignmentOperators.size(); n++)
1787                     if (line.COMPARE(i, nonAssignmentOperators[n]->length(), *(nonAssignmentOperators[n])) == 0)
1788                     {
1789                         if (nonAssignmentOperators[n]->length() > 1)
1790                         {
1791                             outBuffer.append(nonAssignmentOperators[n]->substr(1));
1792                             i += nonAssignmentOperators[n]->length() - 1;
1793                         }
1794                         isNonAssingmentOperator = true;
1795                         break;
1796                     }
1797                 if (!isNonAssingmentOperator)
1798                 {
1799                     for (int a = 0; a < assignmentOperators.size(); a++)
1800                         if (line.COMPARE(i, assignmentOperators[a]->length(), *(assignmentOperators[a])) == 0)
1801                         {
1802                             if (assignmentOperators[a]->length() > 1)
1803                             {
1804                                 outBuffer.append(assignmentOperators[a]->substr(1));
1805                                 i += assignmentOperators[a]->length() - 1;
1806                             }
1807 
1808                             if (!isInOperator && !isInTemplate)
1809                             {
1810                                 registerInStatementIndent(line, i, spaceTabCount, 0, false);
1811                                 immediatelyPreviousAssignmentOp = assignmentOperators[a];
1812                                 isInStatement = true;
1813                             }
1814                             break;
1815                         }
1816                 }
1817         */
1818 
1819         if (isInOperator)
1820           isInOperator = false;
1821       }
1822 
1823     // handle special cases of unindentation:
1824 
1825     /*
1826      * if '{' doesn't follow an immediately previous '{' in the headerStack
1827      * (but rather another header such as "for" or "if", then unindent it
1828      * by one indentation relative to its block.
1829      */
1830     //    cerr << endl << lineOpeningBlocksNum << " " <<  lineClosingBlocksNum << " " <<  previousLastLineHeader << endl;
1831 
1832     // indent #define lines with one less tab
1833     //if (isInDefine)
1834     //    tabCount -= defineTabCount-1;
1835 
1836 
1837     if (!lineStartsInComment
1838         && !blockIndent
1839         && outBuffer.length()>0
1840         && outBuffer[0]=='{'
1841         && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum)
1842         && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET)
1843         && shouldIndentBrackettedLine)
1844       --tabCount;
1845 
1846     else if (!lineStartsInComment
1847              && outBuffer.length()>0
1848              && outBuffer[0]=='}'
1849              && shouldIndentBrackettedLine )
1850       --tabCount;
1851 
1852     // correctly indent one-line-blocks...
1853     else if (!lineStartsInComment
1854              && outBuffer.length()>0
1855              && lineOpeningBlocksNum > 0
1856              && lineOpeningBlocksNum == lineClosingBlocksNum
1857              && previousLastLineHeader != NULL
1858              && previousLastLineHeader != &AS_OPEN_BRACKET)
1859       tabCount -= 1; //lineOpeningBlocksNum - (blockIndent ? 1 : 0);
1860 
1861     if (tabCount < 0)
1862       tabCount = 0;
1863 
1864     // take care of extra bracket indentatation option...
1865     if (bracketIndent && outBuffer.length()>0 && shouldIndentBrackettedLine)
1866       if (outBuffer[0]=='{' || outBuffer[0]=='}')
1867         tabCount++;
1868 
1869 
1870     if (isInDefine)
1871       {
1872         if (outBuffer[0] == '#')
1873           {
1874             string preproc = trim(string(outBuffer.c_str() + 1));
1875             if (preproc.COMPARE(0, 6, string("define")) == 0)
1876               {
1877                 if (!inStatementIndentStack->empty()
1878                     && inStatementIndentStack->back() > 0)
1879                   {
1880                     defineTabCount = tabCount;
1881                   }
1882                 else
1883                   {
1884                     defineTabCount = tabCount - 1;
1885                     tabCount--;
1886                   }
1887               }
1888           }
1889 
1890         tabCount -= defineTabCount;
1891       }
1892 
1893     if (tabCount < 0)
1894       tabCount = 0;
1895 
1896 
1897     // finally, insert indentations into begining of line
1898 
1899     prevFinalLineSpaceTabCount = spaceTabCount;
1900     prevFinalLineTabCount = tabCount;
1901 
1902     if (shouldForceTabIndentation)
1903       {
1904         tabCount += spaceTabCount / indentLength;
1905         spaceTabCount = spaceTabCount % indentLength;
1906       }
1907 
1908     outBuffer = preLineWS(spaceTabCount,tabCount) + outBuffer;
1909 
1910     if (lastLineHeader != NULL)
1911       previousLastLineHeader = lastLineHeader;
1912 
1913     return outBuffer;
1914   }
1915 
1916 
preLineWS(int spaceTabCount,int tabCount)1917   string ASBeautifier::preLineWS(int spaceTabCount, int tabCount)
1918   {
1919     string ws;
1920 
1921     for (int i=0; i<tabCount; i++)
1922       ws += indentString;
1923 
1924     while ((spaceTabCount--) > 0)
1925       ws += string(" ");
1926 
1927     return ws;
1928 
1929   }
1930 
1931   /**
1932    * register an in-statement indent.
1933    */
registerInStatementIndent(const string & line,int i,int spaceTabCount,int minIndent,bool updateParenStack)1934   void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount,
1935       int minIndent, bool updateParenStack)
1936   {
1937     int inStatementIndent;
1938     int remainingCharNum = line.length() - i;
1939     int nextNonWSChar = 1;
1940 
1941     nextNonWSChar = getNextProgramCharDistance(line, i);
1942 
1943     // if indent is around the last char in the line, indent instead 2 spaces from the previous indent
1944     if (nextNonWSChar == remainingCharNum)
1945       {
1946         int previousIndent = spaceTabCount;
1947         if (!inStatementIndentStack->empty())
1948           previousIndent = inStatementIndentStack->back();
1949 
1950         inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent );
1951         if (updateParenStack)
1952           parenIndentStack->push_back( previousIndent );
1953         return;
1954       }
1955 
1956     if (updateParenStack)
1957       parenIndentStack->push_back(i+spaceTabCount);
1958 
1959     inStatementIndent = i + nextNonWSChar + spaceTabCount;
1960 
1961     if (i + nextNonWSChar < minIndent)
1962       inStatementIndent = minIndent + spaceTabCount;
1963 
1964     if (i + nextNonWSChar > maxInStatementIndent)
1965       inStatementIndent =  indentLength*2 + spaceTabCount;
1966 
1967 
1968 
1969     if (!inStatementIndentStack->empty() &&
1970         inStatementIndent < inStatementIndentStack->back())
1971       inStatementIndent = inStatementIndentStack->back();
1972 
1973     inStatementIndentStack->push_back(inStatementIndent);
1974   }
1975 
1976   /**
1977    * get distance to the next non-white sspace, non-comment character in the line.
1978    * if no such character exists, return the length remaining to the end of the line.
1979    */
getNextProgramCharDistance(const string & line,int i)1980   int ASBeautifier::getNextProgramCharDistance(const string &line, int i)
1981   {
1982     bool inComment = false;
1983     int remainingCharNum = line.length() - i;
1984     int charDistance = 1;
1985     int ch;
1986 
1987     for (charDistance = 1; charDistance < remainingCharNum; charDistance++)
1988       {
1989         ch = line[i + charDistance];
1990         if (inComment)
1991           {
1992             if (line.COMPARE(i + charDistance, 2, AS_CLOSE_COMMENT) == 0)
1993               {
1994                 charDistance++;
1995                 inComment = false;
1996               }
1997             continue;
1998           }
1999         else if (isWhiteSpace(ch))
2000           continue;
2001         else if (ch == '/')
2002           {
2003             if (line.COMPARE(i + charDistance, 2, AS_OPEN_LINE_COMMENT) == 0)
2004               return remainingCharNum;
2005             else if (line.COMPARE(i + charDistance, 2, AS_OPEN_COMMENT) == 0)
2006               {
2007                 charDistance++;
2008                 inComment = true;
2009               }
2010           }
2011         else
2012           return charDistance;
2013       }
2014 
2015     return charDistance;
2016   }
2017 
2018 
2019   /**
2020    * check if a specific character can be used in a legal variable/method/class name
2021    *
2022    * @return          legality of the char.
2023    * @param ch        the character to be checked.
2024    */
isLegalNameChar(char ch) const2025   bool ASBeautifier::isLegalNameChar(char ch) const
2026     {
2027       return (isalnum(ch) //(ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9') ||
2028               || ch=='.' || ch=='_' || (!isCStyle && ch=='$') || (isCStyle && ch=='~'));
2029     }
2030 
2031 
2032   /**
2033    * check if a specific line position contains a header, out of several possible headers.
2034    *
2035    * @return    a pointer to the found header. if no header was found then return NULL.
2036    */
findHeader(const string & line,int i,const vector<const string * > & possibleHeaders,bool checkBoundry)2037   const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry)
2038   {
2039     int maxHeaders = possibleHeaders.size();
2040     const string *header = NULL;
2041     int p;
2042 
2043     for (p=0; p < maxHeaders; p++)
2044       {
2045         header = possibleHeaders[p];
2046 
2047         if (line.COMPARE(i, header->length(), *header) == 0)
2048           {
2049             // check that this is a header and not a part of a longer word
2050             // (e.g. not at its begining, not at its middle...)
2051 
2052             int lineLength = line.length();
2053             int headerEnd = i + header->length();
2054             char startCh = (*header)[0];   // first char of header
2055             char endCh = 0;                // char just after header
2056             char prevCh = 0;               // char just before header
2057 
2058             if (headerEnd < lineLength)
2059               {
2060                 endCh = line[headerEnd];
2061               }
2062             if (i > 0)
2063               {
2064                 prevCh = line[i-1];
2065               }
2066 
2067             if (!checkBoundry)
2068               {
2069                 return header;
2070               }
2071             else if (prevCh != 0
2072                      && isLegalNameChar(startCh)
2073                      && isLegalNameChar(prevCh))
2074               {
2075                 return NULL;
2076               }
2077             else if (headerEnd >= lineLength
2078                      || !isLegalNameChar(startCh)
2079                      || !isLegalNameChar(endCh))
2080               {
2081                 return header;
2082               }
2083             else
2084               {
2085                 return NULL;
2086               }
2087           }
2088       }
2089 
2090     return NULL;
2091   }
2092 
2093 
2094   /**
2095    * check if a specific character can be used in a legal variable/method/class name
2096    *
2097    * @return          legality of the char.
2098    * @param ch        the character to be checked.
2099    */
isWhiteSpace(char ch) const2100   bool ASBeautifier::isWhiteSpace(char ch) const
2101     {
2102       return (ch == ' ' || ch == '\t');
2103     }
2104 
2105   /**
2106    * find the index number of a string element in a container of strings
2107    *
2108    * @return              the index number of element in the ocntainer. -1 if element not found.
2109    * @param container     a vector of strings.
2110    * @param element       the element to find .
2111    */
indexOf(vector<const string * > & container,const string * element)2112   int ASBeautifier::indexOf(vector<const string*> &container, const string *element)
2113   {
2114     vector<const string*>::const_iterator where;
2115 
2116     where= find(container.begin(), container.end(), element);
2117     if (where == container.end())
2118       return -1;
2119     else
2120       return where - container.begin();
2121   }
2122 
2123   /**
2124    * trim removes the white space surrounding a line.
2125    *
2126    * @return          the trimmed line.
2127    * @param str       the line to trim.
2128    */
trim(const string & str)2129   string ASBeautifier::trim(const string &str)
2130   {
2131 
2132     int start = 0;
2133     int end = str.length() - 1;
2134 
2135     while (start < end && isWhiteSpace(str[start]))
2136       start++;
2137 
2138     while (start <= end && isWhiteSpace(str[end]))
2139       end--;
2140 
2141     string returnStr(str, start, end+1-start);
2142     return returnStr;
2143   }
2144 
2145 #ifdef USES_NAMESPACE
2146 }
2147 #endif
2148 /*
2149  * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
2150  *
2151  * compiler_defines.h   (1 January 1999)
2152  * by Tal Davidson (davidsont@bigfoot.com)
2153  * This file is a part of "Artistic Style" - an indentater and reformatter
2154  * of C, C++, C# and Java source files.
2155  *
2156  * The "Artistic Style" project, including all files needed to compile it,
2157  * is free software; you can redistribute it and/or use it and/or modify it
2158  * under the terms of the GNU General Public License as published
2159  * by the Free Software Foundation; either version 2 of the License,
2160  * or (at your option) any later version.
2161  *
2162  * This program is distributed in the hope that it will be useful,
2163  * but WITHOUT ANY WARRANTY; without even the implied warranty of
2164  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
2165  *
2166  * You should have received a copy of the GNU General Public
2167  * License along with this program.
2168  */
2169 
2170 
2171 #ifndef ASBEAUTIFIER_H
2172 #define ASBEAUTIFIER_H
2173 
2174 #include "ASResource.h"
2175 #include "compiler_defines.h"
2176 #include "ASSourceIterator.h"
2177 
2178 #include <string>
2179 #include <vector>
2180 
2181 
2182 using namespace std;
2183 
2184 namespace astyle
2185   {
2186 
2187   enum BracketMode   { NONE_MODE, ATTACH_MODE, BREAK_MODE, BDAC_MODE };
2188   enum BracketType   { NULL_TYPE = 0,
2189                        DEFINITION_TYPE = 1,
2190                        COMMAND_TYPE = 2,
2191                        ARRAY_TYPE  = 4,
2192                        SINGLE_LINE_TYPE = 8};
2193 
2194 
2195   class ASBeautifier : protected ASResource
2196     {
2197     public:
2198       ASBeautifier();
2199       virtual ~ASBeautifier();
2200       virtual void init(ASSourceIterator* iter); // pointer to dynamically created iterator.
2201       virtual void init();
2202       virtual bool hasMoreLines() const;
2203       virtual string nextLine();
2204       virtual string beautify(const string &line);
2205       void setTabIndentation(int length = 4, bool forceTabs = false);
2206       void setSpaceIndentation(int length = 4);
2207       void setMaxInStatementIndentLength(int max);
2208       void setMinConditionalIndentLength(int min);
2209       void setClassIndent(bool state);
2210       void setSwitchIndent(bool state);
2211       void setCaseIndent(bool state);
2212       void setBracketIndent(bool state);
2213       void setBlockIndent(bool state);
2214       void setNamespaceIndent(bool state);
2215       void setLabelIndent(bool state);
2216       void setCStyle();
2217       void setJavaStyle();
2218       void setEmptyLineFill(bool state);
2219       void setPreprocessorIndent(bool state);
2220 
2221 
2222     protected:
2223       int getNextProgramCharDistance(const string &line, int i);
2224       bool isLegalNameChar(char ch) const;
2225       bool isWhiteSpace(char ch) const;
2226       const string *findHeader(const string &line, int i,
2227                                const vector<const string*> &possibleHeaders,
2228                                bool checkBoundry = true);
2229       string trim(const string &str);
2230       int indexOf(vector<const string*> &container, const string *element);
2231 
2232     private:
2233       ASBeautifier(const ASBeautifier &copy);
2234       void operator=(ASBeautifier&); // not to be implemented
2235 
2236       void initStatic();
2237       void registerInStatementIndent(const string &line, int i, int spaceTabCount,
2238                                      int minIndent, bool updateParenStack);
2239       string preLineWS(int spaceTabCount, int tabCount);
2240 
2241       static vector<const string*> headers;
2242       static vector<const string*> nonParenHeaders;
2243       static vector<const string*> preprocessorHeaders;
2244       static vector<const string*> preBlockStatements;
2245       static vector<const string*> assignmentOperators;
2246       static vector<const string*> nonAssignmentOperators;
2247 
2248       static bool calledInitStatic;
2249 
2250       ASSourceIterator *sourceIterator;
2251       vector<ASBeautifier*> *waitingBeautifierStack;
2252       vector<ASBeautifier*> *activeBeautifierStack;
2253       vector<int> *waitingBeautifierStackLengthStack;
2254       vector<int> *activeBeautifierStackLengthStack;
2255       vector<const string*> *headerStack;
2256       vector< vector<const string*>* > *tempStacks;
2257       vector<int> *blockParenDepthStack;
2258       vector<bool> *blockStatementStack;
2259       vector<bool> *parenStatementStack;
2260       vector<int> *inStatementIndentStack;
2261       vector<int> *inStatementIndentStackSizeStack;
2262       vector<int> *parenIndentStack;
2263       vector<bool> *bracketBlockStateStack;
2264       string indentString;
2265       const string *currentHeader;
2266       const string *previousLastLineHeader;
2267       const string *immediatelyPreviousAssignmentOp;
2268       const string *probationHeader;
2269       bool isInQuote;
2270       bool isInComment;
2271       bool isInCase;
2272       bool isInQuestion;
2273       bool isInStatement;
2274       bool isInHeader;
2275       bool isCStyle;
2276       bool isInOperator;
2277       bool isInTemplate;
2278       bool isInConst;
2279       bool isInDefine;
2280       bool isInDefineDefinition;
2281       bool classIndent;
2282       bool isInClassHeader;
2283       bool isInClassHeaderTab;
2284       bool switchIndent;
2285       bool caseIndent;
2286       bool namespaceIndent;
2287       bool bracketIndent;
2288       bool blockIndent;
2289       bool labelIndent;
2290       bool preprocessorIndent;
2291       bool isInConditional;
2292       bool isMinimalConditinalIndentSet;
2293       bool shouldForceTabIndentation;
2294       int minConditionalIndent;
2295       int parenDepth;
2296       int indentLength;
2297       int blockTabCount;
2298       unsigned int leadingWhiteSpaces;
2299       int maxInStatementIndent;
2300       int templateDepth;
2301       char quoteChar;
2302       char prevNonSpaceCh;
2303       char currentNonSpaceCh;
2304       char currentNonLegalCh;
2305       char prevNonLegalCh;
2306       int prevFinalLineSpaceTabCount;
2307       int prevFinalLineTabCount;
2308       bool emptyLineFill;
2309       bool backslashEndsPrevLine;
2310       int defineTabCount;
2311     };
2312 }
2313 
2314 #endif
2315 /*
2316  * Copyright (c) 1998,1999,2000,2001,2002 Tal Davidson. All rights reserved.
2317  *
2318  * ASFormatter.cpp
2319  * by Tal Davidson (davidsont@bigfoot.com)
2320  * This file is a part of "Artistic Style" - an indentater and reformatter
2321  * of C, C++, C# and Java source files.
2322  *
2323  * The "Artistic Style" project, including all files needed to compile it,
2324  * is free software; you can redistribute it and/or use it and/or modify it
2325  * under the terms of the GNU General Public License as published
2326  * by the Free Software Foundation; either version 2 of the License,
2327  * or (at your option) any later version.
2328  *
2329  * This program is distributed in the hope that it will be useful,
2330  * but WITHOUT ANY WARRANTY; without even the implied warranty of
2331  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
2332  *
2333  * You should have received a copy of the GNU General Public
2334  * License along with this program.
2335  *
2336  *
2337  * Patches:
2338  * 26 November 1998 - Richard Bullington -
2339  *        A correction of line-breaking in headers following '}',
2340 
2341  *        was created using a variation of a  patch by Richard Bullington.
2342  * 08 May 2004
2343  *        applied   ASFormatter450670.patch.bz2, ASFormatter.cpp.patch.bz2,
2344  *                  patch1_ssvb_patch.tar.gz
2345  */
2346 
2347 #include "compiler_defines.h"
2348 #include "ASFormatter.h"
2349 
2350 
2351 #include <string>
2352 #include <cctype>
2353 #include <vector>
2354 #include <algorithm>
2355 #include <iostream>
2356 
2357 
2358 #define INIT_CONTAINER(container, value)     {if ( (container) != NULL ) delete (container); (container) = (value); }
2359 #define DELETE_CONTAINER(container)          {if ( (container) != NULL ) delete (container) ; }
2360 #define IS_A(a,b)                            ( ((a) & (b)) == (b))
2361 #ifdef USES_NAMESPACE
2362 using namespace std;
2363 
2364