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 ©);
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