~ubuntu-branches/ubuntu/lucid/codelite/lucid

« back to all changes in this revision

Viewing changes to CodeFormatter/ASBeautifier.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Chow Loong Jin
  • Date: 2009-01-12 15:46:55 UTC
  • Revision ID: james.westby@ubuntu.com-20090112154655-sdynrljcb6u167yw
Tags: upstream-1.0.2674+dfsg
ImportĀ upstreamĀ versionĀ 1.0.2674+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
2
 *
 
3
 *   ASBeautifier.cpp
 
4
 *
 
5
 *   This file is a part of "Artistic Style" - an indentation and
 
6
 *   reformatting tool for C, C++, C# and Java source files.
 
7
 *   http://astyle.sourceforge.net
 
8
 * 
 
9
 *   The "Artistic Style" project, including all files needed to
 
10
 *   compile it, is free software; you can redistribute it and/or
 
11
 *   modify it under the terms of the GNU Lesser General Public
 
12
 *   License as published by the Free Software Foundation; either
 
13
 *   version 2.1 of the License, or (at your option) any later
 
14
 *   version.
 
15
 *
 
16
 *   This program is distributed in the hope that it will be useful,
 
17
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 *   GNU Lesser General Public License for more details.
 
20
 *
 
21
 *   You should have received a copy of the GNU Lesser General Public
 
22
 *   License along with this project; if not, write to the
 
23
 *   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
24
 *   Boston, MA  02110-1301, USA.
 
25
 *
 
26
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
27
 */
 
28
 
 
29
#include "astyle.h"
 
30
 
 
31
#include <algorithm>
 
32
#include <iostream>
 
33
 
 
34
#define INIT_CONTAINER(container, value)     {if ( (container) != NULL ) delete (container); (container) = (value); }
 
35
#define DELETE_CONTAINER(container)          {if ( (container) != NULL ) delete (container); }
 
36
 
 
37
 
 
38
namespace astyle
 
39
{
 
40
vector<const string*> ASBeautifier::headers;
 
41
vector<const string*> ASBeautifier::nonParenHeaders;
 
42
vector<const string*> ASBeautifier::preBlockStatements;
 
43
vector<const string*> ASBeautifier::assignmentOperators;
 
44
vector<const string*> ASBeautifier::nonAssignmentOperators;
 
45
 
 
46
 
 
47
/*
 
48
 * initialize the static vars
 
49
 */
 
50
void ASBeautifier::initStatic()
 
51
{
 
52
        static int beautifierFileType = 9;     // initialized with an invalid type
 
53
 
 
54
        if (fileType == beautifierFileType)    // don't build unless necessary
 
55
                return;
 
56
 
 
57
        beautifierFileType = fileType;
 
58
 
 
59
        headers.clear();
 
60
        nonParenHeaders.clear();
 
61
        assignmentOperators.clear();
 
62
        nonAssignmentOperators.clear();
 
63
        preBlockStatements.clear();
 
64
 
 
65
        ASResource::buildHeaders(headers, fileType, true);
 
66
        ASResource::buildNonParenHeaders(nonParenHeaders, fileType, true);
 
67
        ASResource::buildAssignmentOperators(assignmentOperators);
 
68
        ASResource::buildNonAssignmentOperators(nonAssignmentOperators);
 
69
        ASResource::buildPreBlockStatements(preBlockStatements);
 
70
 
 
71
//      cout << "beaut" << endl;
 
72
}
 
73
 
 
74
/**
 
75
 * ASBeautifier's constructor
 
76
 */
 
77
ASBeautifier::ASBeautifier()
 
78
{
 
79
        waitingBeautifierStack = NULL;
 
80
        activeBeautifierStack = NULL;
 
81
        waitingBeautifierStackLengthStack = NULL;
 
82
        activeBeautifierStackLengthStack = NULL;
 
83
 
 
84
        headerStack  = NULL;
 
85
        tempStacks = NULL;
 
86
        blockParenDepthStack = NULL;
 
87
        blockStatementStack = NULL;
 
88
        parenStatementStack = NULL;
 
89
        bracketBlockStateStack = NULL;
 
90
        inStatementIndentStack = NULL;
 
91
        inStatementIndentStackSizeStack = NULL;
 
92
        parenIndentStack = NULL;
 
93
        sourceIterator = NULL;
 
94
 
 
95
        isMinimalConditinalIndentSet = false;
 
96
        shouldForceTabIndentation = false;
 
97
 
 
98
        setSpaceIndentation(4);
 
99
        setMaxInStatementIndentLength(40);
 
100
        setClassIndent(false);
 
101
        setSwitchIndent(false);
 
102
        setCaseIndent(false);
 
103
        setBlockIndent(false);
 
104
        setBracketIndent(false);
 
105
        setNamespaceIndent(false);
 
106
        setLabelIndent(false);
 
107
        setEmptyLineFill(false);
 
108
        fileType = C_TYPE;
 
109
        setCStyle();
 
110
        setPreprocessorIndent(false);
 
111
}
 
112
 
 
113
/**
 
114
 * ASBeautifier's copy constructor
 
115
 */
 
116
ASBeautifier::ASBeautifier(const ASBeautifier &other)
 
117
{
 
118
        waitingBeautifierStack = NULL;
 
119
        activeBeautifierStack = NULL;
 
120
        waitingBeautifierStackLengthStack = NULL;
 
121
        activeBeautifierStackLengthStack = NULL;
 
122
 
 
123
        headerStack  = new vector<const string*>;
 
124
        *headerStack = *other.headerStack;
 
125
 
 
126
        tempStacks = new vector<vector<const string*>*>;
 
127
        vector<vector<const string*>*>::iterator iter;
 
128
        for (iter = other.tempStacks->begin();
 
129
                iter != other.tempStacks->end();
 
130
                ++iter)
 
131
        {
 
132
                vector<const string*> *newVec = new vector<const string*>;
 
133
                *newVec = **iter;
 
134
                tempStacks->push_back(newVec);
 
135
        }
 
136
        blockParenDepthStack = new vector<int>;
 
137
        *blockParenDepthStack = *other.blockParenDepthStack;
 
138
 
 
139
        blockStatementStack = new vector<bool>;
 
140
        *blockStatementStack = *other.blockStatementStack;
 
141
 
 
142
        parenStatementStack =  new vector<bool>;
 
143
        *parenStatementStack = *other.parenStatementStack;
 
144
 
 
145
        bracketBlockStateStack = new vector<bool>;
 
146
        *bracketBlockStateStack = *other.bracketBlockStateStack;
 
147
 
 
148
        inStatementIndentStack = new vector<int>;
 
149
        *inStatementIndentStack = *other.inStatementIndentStack;
 
150
 
 
151
        inStatementIndentStackSizeStack = new vector<int>;
 
152
        *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack;
 
153
 
 
154
        parenIndentStack = new vector<int>;
 
155
        *parenIndentStack = *other.parenIndentStack;
 
156
 
 
157
        sourceIterator = other.sourceIterator;
 
158
 
 
159
        // protected variables
 
160
        fileType = other.fileType;
 
161
        isCStyle = other.isCStyle;
 
162
        isJavaStyle = other.isJavaStyle;
 
163
        isSharpStyle = other.isSharpStyle;
 
164
 
 
165
        // variables set by ASFormatter
 
166
        // must also be updated in preprocessor
 
167
        inLineNumber = other.inLineNumber;
 
168
        outLineNumber = other.outLineNumber;
 
169
        lineCommentNoBeautify = other.lineCommentNoBeautify;
 
170
        isNonInStatementArray = other.isNonInStatementArray;
 
171
 
 
172
        // private variables
 
173
        indentString = other.indentString;
 
174
        currentHeader = other.currentHeader;
 
175
        previousLastLineHeader = other.previousLastLineHeader;
 
176
        immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp;
 
177
        probationHeader = other.probationHeader;
 
178
        isInQuote = other.isInQuote;
 
179
        isInComment = other.isInComment;
 
180
        isInCase = other.isInCase;
 
181
        isInQuestion = other.isInQuestion;
 
182
        isInStatement = other.isInStatement;
 
183
        isInHeader = other.isInHeader;
 
184
        isInOperator = other.isInOperator;
 
185
        isInTemplate = other.isInTemplate;
 
186
        isInDefine = other.isInDefine;
 
187
        isInDefineDefinition = other.isInDefineDefinition;
 
188
        classIndent = other.classIndent;
 
189
        isInClassHeader = other.isInClassHeader;
 
190
        isInClassHeaderTab = other.isInClassHeaderTab;
 
191
        switchIndent = other.switchIndent;
 
192
        caseIndent = other.caseIndent;
 
193
        namespaceIndent = other.namespaceIndent;
 
194
        bracketIndent = other.bracketIndent;
 
195
        blockIndent = other.blockIndent;
 
196
        labelIndent = other.labelIndent;
 
197
        preprocessorIndent = other.preprocessorIndent;
 
198
        isInConditional = other.isInConditional;
 
199
        isMinimalConditinalIndentSet = other.isMinimalConditinalIndentSet;
 
200
        shouldForceTabIndentation = other.shouldForceTabIndentation;
 
201
        emptyLineFill = other.emptyLineFill;
 
202
        backslashEndsPrevLine = other.backslashEndsPrevLine;
 
203
        blockCommentNoIndent = other.blockCommentNoIndent;
 
204
        blockCommentNoBeautify = other.blockCommentNoBeautify;
 
205
        previousLineProbationTab = other.previousLineProbationTab;
 
206
        minConditionalIndent = other.minConditionalIndent;
 
207
        parenDepth = other.parenDepth;
 
208
        indentLength = other.indentLength;
 
209
        blockTabCount = other.blockTabCount;
 
210
        leadingWhiteSpaces = other.leadingWhiteSpaces;
 
211
        maxInStatementIndent = other.maxInStatementIndent;
 
212
        templateDepth = other.templateDepth;
 
213
        prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount;
 
214
        prevFinalLineTabCount = other.prevFinalLineTabCount;
 
215
        defineTabCount = other.defineTabCount;
 
216
        quoteChar = other.quoteChar;
 
217
        prevNonSpaceCh = other.prevNonSpaceCh;
 
218
        currentNonSpaceCh = other.currentNonSpaceCh;
 
219
        currentNonLegalCh = other.currentNonLegalCh;
 
220
        prevNonLegalCh = other.prevNonLegalCh;
 
221
}
 
222
 
 
223
/**
 
224
 * ASBeautifier's destructor
 
225
 */
 
226
ASBeautifier::~ASBeautifier()
 
227
{
 
228
        DELETE_CONTAINER(headerStack);
 
229
        DELETE_CONTAINER(blockParenDepthStack);
 
230
        DELETE_CONTAINER(blockStatementStack);
 
231
        DELETE_CONTAINER(parenStatementStack);
 
232
        DELETE_CONTAINER(bracketBlockStateStack);
 
233
        DELETE_CONTAINER(inStatementIndentStack);
 
234
        DELETE_CONTAINER(inStatementIndentStackSizeStack);
 
235
        DELETE_CONTAINER(parenIndentStack);
 
236
        DELETE_CONTAINER(waitingBeautifierStackLengthStack);
 
237
        DELETE_CONTAINER(activeBeautifierStackLengthStack);
 
238
 
 
239
        if(tempStacks){
 
240
                vector< vector<const string*>* >::iterator iter = tempStacks->begin();
 
241
                for(; iter != tempStacks->end(); iter++){
 
242
                        delete *iter;
 
243
                }
 
244
                tempStacks->clear();
 
245
                delete tempStacks;
 
246
                tempStacks = NULL;
 
247
        }
 
248
 
 
249
        if(waitingBeautifierStack){
 
250
                vector<ASBeautifier*>::iterator iter = waitingBeautifierStack->begin();
 
251
                for(; iter != waitingBeautifierStack->end(); iter++){
 
252
                        delete *iter;
 
253
                }
 
254
                waitingBeautifierStack->clear();
 
255
                delete waitingBeautifierStack;
 
256
                waitingBeautifierStack = NULL;
 
257
        }
 
258
 
 
259
        if(activeBeautifierStack){
 
260
                vector<ASBeautifier*>::iterator iter = activeBeautifierStack->begin();
 
261
                for(; iter != activeBeautifierStack->end(); iter++){
 
262
                        delete *iter;
 
263
                }
 
264
                activeBeautifierStack->clear();
 
265
                delete activeBeautifierStack;
 
266
                activeBeautifierStack = NULL;
 
267
        }
 
268
}
 
269
 
 
270
/**
 
271
 * initialize the ASBeautifier.
 
272
 *
 
273
 * init() should be called every time a ABeautifier object is to start
 
274
 * beautifying a NEW source file.
 
275
 * init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
 
276
 * that will be used to iterate through the source code. This object will be
 
277
 * deleted during the ASBeautifier's destruction, and thus should not be
 
278
 * deleted elsewhere.
 
279
 *
 
280
 * @param iter     a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
 
281
 */
 
282
void ASBeautifier::init(ASSourceIterator *iter)
 
283
{
 
284
        sourceIterator = iter;
 
285
        init();
 
286
}
 
287
 
 
288
/**
 
289
 * initialize the ASBeautifier.
 
290
 */
 
291
void ASBeautifier::init()
 
292
{
 
293
        initStatic();
 
294
 
 
295
        INIT_CONTAINER(waitingBeautifierStack,  new vector<ASBeautifier*>);
 
296
        INIT_CONTAINER(activeBeautifierStack,  new vector<ASBeautifier*>);
 
297
 
 
298
        INIT_CONTAINER(waitingBeautifierStackLengthStack, new vector<int>);
 
299
        INIT_CONTAINER(activeBeautifierStackLengthStack, new vector<int>);
 
300
 
 
301
        INIT_CONTAINER(headerStack,  new vector<const string*>);
 
302
        INIT_CONTAINER(tempStacks, new vector<vector<const string*>*>);
 
303
        tempStacks->push_back(new vector<const string*>);
 
304
 
 
305
        INIT_CONTAINER(blockParenDepthStack, new vector<int>);
 
306
        INIT_CONTAINER(blockStatementStack, new vector<bool>);
 
307
        INIT_CONTAINER(parenStatementStack, new vector<bool>);
 
308
 
 
309
        INIT_CONTAINER(bracketBlockStateStack, new vector<bool>);
 
310
        bracketBlockStateStack->push_back(true);
 
311
 
 
312
        INIT_CONTAINER(inStatementIndentStack, new vector<int>);
 
313
        INIT_CONTAINER(inStatementIndentStackSizeStack, new vector<int>);
 
314
        inStatementIndentStackSizeStack->push_back(0);
 
315
        INIT_CONTAINER(parenIndentStack, new vector<int>);
 
316
 
 
317
        immediatelyPreviousAssignmentOp = NULL;
 
318
        previousLastLineHeader = NULL;
 
319
        currentHeader = NULL;
 
320
 
 
321
        isInQuote = false;
 
322
        isInComment = false;
 
323
        isInStatement = false;
 
324
        isInCase = false;
 
325
        isInQuestion = false;
 
326
        isInClassHeader = false;
 
327
        isInClassHeaderTab = false;
 
328
        isInHeader = false;
 
329
        isInOperator = false;
 
330
        isInTemplate = false;
 
331
        isInConditional = false;
 
332
        templateDepth = 0;
 
333
        parenDepth = 0;
 
334
        blockTabCount = 0;
 
335
        leadingWhiteSpaces = 0;
 
336
        prevNonSpaceCh = '{';
 
337
        currentNonSpaceCh = '{';
 
338
        prevNonLegalCh = '{';
 
339
        currentNonLegalCh = '{';
 
340
        quoteChar = ' ';
 
341
        prevFinalLineSpaceTabCount = 0;
 
342
        prevFinalLineTabCount = 0;
 
343
        probationHeader = NULL;
 
344
        backslashEndsPrevLine = false;
 
345
        isInDefine = false;
 
346
        isInDefineDefinition = false;
 
347
        defineTabCount = 0;
 
348
        lineCommentNoBeautify = false;
 
349
        blockCommentNoIndent = false;
 
350
        blockCommentNoBeautify = false;
 
351
        previousLineProbationTab = false;
 
352
        isNonInStatementArray = false;
 
353
        inLineNumber = -1;           // for debugging
 
354
        outLineNumber = 0;           // for debugging
 
355
}
 
356
 
 
357
/**
 
358
 * set indentation style to C/C++.
 
359
 */
 
360
void ASBeautifier::setCStyle()
 
361
{
 
362
        fileType = C_TYPE;
 
363
        isCStyle     = true;
 
364
        isJavaStyle  = false;
 
365
        isSharpStyle = false;
 
366
}
 
367
 
 
368
/**
 
369
 * set indentation style to Java.
 
370
 */
 
371
void ASBeautifier::setJavaStyle()
 
372
{
 
373
        fileType = JAVA_TYPE;
 
374
        isJavaStyle  = true;
 
375
        isCStyle     = false;
 
376
        isSharpStyle = false;
 
377
}
 
378
 
 
379
/**
 
380
 * set indentation style to C#.
 
381
 */
 
382
void ASBeautifier::setSharpStyle()
 
383
{
 
384
        fileType = SHARP_TYPE;
 
385
        isSharpStyle = true;
 
386
        isCStyle     = false;
 
387
        isJavaStyle  = false;
 
388
}
 
389
 
 
390
/**
 
391
 * indent using one tab per indentation
 
392
 */
 
393
void ASBeautifier::setTabIndentation(int length, bool forceTabs)
 
394
{
 
395
        indentString = "\t";
 
396
        indentLength = length;
 
397
        shouldForceTabIndentation = forceTabs;
 
398
 
 
399
        if (!isMinimalConditinalIndentSet)
 
400
                minConditionalIndent = indentLength * 2;
 
401
}
 
402
 
 
403
/**
 
404
 * indent using a number of spaces per indentation.
 
405
 *
 
406
 * @param   length     number of spaces per indent.
 
407
 */
 
408
void ASBeautifier::setSpaceIndentation(int length)
 
409
{
 
410
        indentString = string(length, ' ');
 
411
        indentLength = length;
 
412
 
 
413
        if (!isMinimalConditinalIndentSet)
 
414
                minConditionalIndent = indentLength * 2;
 
415
}
 
416
 
 
417
/**
 
418
 * set the maximum indentation between two lines in a multi-line statement.
 
419
 *
 
420
 * @param   max     maximum indentation length.
 
421
 */
 
422
void ASBeautifier::setMaxInStatementIndentLength(int max)
 
423
{
 
424
        maxInStatementIndent = max;
 
425
}
 
426
 
 
427
/**
 
428
 * set the minimum indentation between two lines in a multi-line condition.
 
429
 *
 
430
 * @param   min     minimal indentation length.
 
431
 */
 
432
void ASBeautifier::setMinConditionalIndentLength(int min)
 
433
{
 
434
        minConditionalIndent = min;
 
435
        isMinimalConditinalIndentSet = true;
 
436
}
 
437
 
 
438
/**
 
439
 * set the state of the bracket indentation option. If true, brackets will
 
440
 * be indented one additional indent.
 
441
 *
 
442
 * @param   state             state of option.
 
443
 */
 
444
void ASBeautifier::setBracketIndent(bool state)
 
445
{
 
446
        bracketIndent = state;
 
447
}
 
448
 
 
449
/**
 
450
 * set the state of the block indentation option. If true, entire blocks
 
451
 * will be indented one additional indent, similar to the GNU indent style.
 
452
 *
 
453
 * @param   state             state of option.
 
454
 */
 
455
void ASBeautifier::setBlockIndent(bool state)
 
456
{
 
457
        if (state)
 
458
                setBracketIndent(false); // so that we don't have both bracket and block indent
 
459
        blockIndent = state;
 
460
}
 
461
 
 
462
/**
 
463
 * set the state of the class indentation option. If true, C++ class
 
464
 * definitions will be indented one additional indent.
 
465
 *
 
466
 * @param   state             state of option.
 
467
 */
 
468
void ASBeautifier::setClassIndent(bool state)
 
469
{
 
470
        classIndent = state;
 
471
}
 
472
 
 
473
/**
 
474
 * set the state of the switch indentation option. If true, blocks of 'switch'
 
475
 * statements will be indented one additional indent.
 
476
 *
 
477
 * @param   state             state of option.
 
478
 */
 
479
void ASBeautifier::setSwitchIndent(bool state)
 
480
{
 
481
        switchIndent = state;
 
482
}
 
483
 
 
484
/**
 
485
 * set the state of the case indentation option. If true, lines of 'case'
 
486
 * statements will be indented one additional indent.
 
487
 *
 
488
 * @param   state             state of option.
 
489
 */
 
490
void ASBeautifier::setCaseIndent(bool state)
 
491
{
 
492
        caseIndent = state;
 
493
}
 
494
 
 
495
/**
 
496
 * set the state of the namespace indentation option.
 
497
 * If true, blocks of 'namespace' statements will be indented one
 
498
 * additional indent. Otherwise, NO indentation will be added.
 
499
 *
 
500
 * @param   state             state of option.
 
501
 */
 
502
void ASBeautifier::setNamespaceIndent(bool state)
 
503
{
 
504
        namespaceIndent = state;
 
505
}
 
506
 
 
507
/**
 
508
 * set the state of the label indentation option.
 
509
 * If true, labels will be indented one indent LESS than the
 
510
 * current indentation level.
 
511
 * If false, labels will be flushed to the left with NO
 
512
 * indent at all.
 
513
 *
 
514
 * @param   state             state of option.
 
515
 */
 
516
void ASBeautifier::setLabelIndent(bool state)
 
517
{
 
518
        labelIndent = state;
 
519
}
 
520
 
 
521
/**
 
522
 * set the state of the preprocessor indentation option.
 
523
 * If true, multiline #define statements will be indented.
 
524
 *
 
525
 * @param   state             state of option.
 
526
 */
 
527
void ASBeautifier::setPreprocessorIndent(bool state)
 
528
{
 
529
        preprocessorIndent = state;
 
530
}
 
531
 
 
532
/**
 
533
 * set the state of the empty line fill option.
 
534
 * If true, empty lines will be filled with the whitespace.
 
535
 * of their previous lines.
 
536
 * If false, these lines will remain empty.
 
537
 *
 
538
 * @param   state             state of option.
 
539
 */
 
540
void ASBeautifier::setEmptyLineFill(bool state)
 
541
{
 
542
        emptyLineFill = state;
 
543
}
 
544
 
 
545
/**
 
546
 * get the number of spaces per indent
 
547
 *
 
548
 * @return   value of indentLength option.
 
549
*/
 
550
int ASBeautifier::getIndentLength(void)
 
551
{
 
552
        return indentLength;
 
553
}
 
554
 
 
555
/**
 
556
 * get the char used for indentation, space or tab
 
557
  *
 
558
 * @return   the char used for indentation.
 
559
 */
 
560
string ASBeautifier::getIndentString(void)
 
561
{
 
562
        return indentString;
 
563
}
 
564
 
 
565
/**
 
566
 * get the state of the case indentation option. If true, lines of 'case'
 
567
 * statements will be indented one additional indent.
 
568
 *
 
569
 * @return   state of caseIndent option.
 
570
 */
 
571
bool ASBeautifier::getCaseIndent(void)
 
572
{
 
573
        return caseIndent;
 
574
}
 
575
 
 
576
/**
 
577
 * get C style identifier.
 
578
 * If true, a C source is being indented.
 
579
 *
 
580
 * @return   state of isCStyle option.
 
581
 */
 
582
bool ASBeautifier::getCStyle(void)
 
583
{
 
584
        return isCStyle;
 
585
}
 
586
 
 
587
/**
 
588
 * get Java style identifier.
 
589
 * If true, a Java source is being indented.
 
590
 *
 
591
 * @return   state of isJavaStyle option.
 
592
 */
 
593
bool ASBeautifier::getJavaStyle(void)
 
594
{
 
595
        return isJavaStyle;
 
596
}
 
597
 
 
598
/**
 
599
 * get C# style identifier.
 
600
 * If true, a C# source is being indented.
 
601
 *
 
602
 * @return   state of isSharpStyle option.
 
603
 */
 
604
bool ASBeautifier::getSharpStyle(void)
 
605
{
 
606
        return isSharpStyle;
 
607
}
 
608
 
 
609
/**
 
610
 * get the state of the empty line fill option.
 
611
 * If true, empty lines will be filled with the whitespace.
 
612
 * of their previous lines.
 
613
 * If false, these lines will remain empty.
 
614
 *
 
615
 * @return   state of emptyLineFill option.
 
616
 */
 
617
bool ASBeautifier::getEmptyLineFill(void)
 
618
{
 
619
        return emptyLineFill;
 
620
}
 
621
 
 
622
/**
 
623
 * check if there are any indented lines ready to be read by nextLine()
 
624
 *
 
625
 * @return    are there any indented lines ready?
 
626
 */
 
627
bool ASBeautifier::hasMoreLines() const
 
628
{
 
629
        return sourceIterator->hasMoreLines();
 
630
}
 
631
 
 
632
/**
 
633
 * get the next indented line.
 
634
 *
 
635
 * @return    indented line.
 
636
 */
 
637
string ASBeautifier::nextLine()
 
638
{
 
639
        return beautify(sourceIterator->nextLine());
 
640
}
 
641
 
 
642
/**
 
643
 * beautify a line of source code.
 
644
 * every line of source code in a source code file should be sent
 
645
 * one after the other to the beautify method.
 
646
 *
 
647
 * @return      the indented line.
 
648
 * @param originalLine       the original unindented line.
 
649
 */
 
650
string ASBeautifier::beautify(const string &originalLine)
 
651
{
 
652
        string line;
 
653
        bool isInLineComment = false;
 
654
        bool lineStartsInComment = false;
 
655
        bool isInClass = false;
 
656
        bool isInSwitch = false;
 
657
        bool isImmediatelyAfterConst = false;
 
658
        bool isSpecialChar = false;
 
659
        char ch = ' ';
 
660
        char prevCh;
 
661
        string outBuffer; // the newly idented line is bufferd here
 
662
        int tabCount = 0;
 
663
        const string *lastLineHeader = NULL;
 
664
        bool closingBracketReached = false;
 
665
        int spaceTabCount = 0;
 
666
        char tempCh;
 
667
        size_t headerStackSize = headerStack->size();
 
668
        bool shouldIndentBrackettedLine = true;
 
669
        int lineOpeningBlocksNum = 0;
 
670
        int lineClosingBlocksNum = 0;
 
671
        bool previousLineProbation = (probationHeader != NULL);
 
672
        int i;
 
673
 
 
674
        currentHeader = NULL;
 
675
        lineStartsInComment = isInComment;
 
676
        blockCommentNoBeautify = blockCommentNoIndent;
 
677
        previousLineProbationTab = false;
 
678
        outLineNumber++;
 
679
 
 
680
        // handle and remove white spaces around the line:
 
681
        // If not in comment, first find out size of white space before line,
 
682
        // so that possible comments starting in the line continue in
 
683
        // relation to the preliminary white-space.
 
684
        if (!isInComment)
 
685
        {
 
686
                int strlen = originalLine.length();
 
687
                leadingWhiteSpaces = 0;
 
688
 
 
689
                for (int j = 0; j < strlen && isWhiteSpace(originalLine[j]); j++)
 
690
                {
 
691
                        if (originalLine[j] == '\t')
 
692
                                leadingWhiteSpaces += indentLength;
 
693
                        else
 
694
                                leadingWhiteSpaces++;
 
695
                }
 
696
                line = trim(originalLine);
 
697
        }
 
698
        else
 
699
        {
 
700
                // convert leading tabs to spaces
 
701
                string spaceTabs(indentLength, ' ');
 
702
                string newLine = originalLine;
 
703
                int strlen = newLine.length();
 
704
 
 
705
                for (int j=0; j < leadingWhiteSpaces && j < strlen; j++)
 
706
                {
 
707
                        if (newLine[j] == '\t')
 
708
                        {
 
709
                                newLine.replace(j, 1, spaceTabs);
 
710
                                strlen = newLine.length();
 
711
                        }
 
712
                }
 
713
 
 
714
                // trim the comment leaving the new leading whitespace
 
715
                int trimSize = 0;
 
716
                strlen = newLine.length();
 
717
 
 
718
                while (trimSize < strlen
 
719
                        && trimSize < leadingWhiteSpaces
 
720
                        && isWhiteSpace(newLine[trimSize]))
 
721
                        trimSize++;
 
722
 
 
723
 
 
724
                while (trimSize < strlen && isWhiteSpace(newLine[strlen-1]))
 
725
                        strlen--;
 
726
 
 
727
                line = newLine.substr(trimSize, strlen);
 
728
                size_t trimEnd = line.find_last_not_of(" \t");
 
729
                if (trimEnd != string::npos)
 
730
                {
 
731
                        int spacesToDelete = line.length() - 1 - trimEnd;
 
732
                        if (spacesToDelete > 0)
 
733
                                line.erase(trimEnd + 1, spacesToDelete);
 
734
                }
 
735
        }
 
736
 
 
737
 
 
738
        if (line.length() == 0)
 
739
        {
 
740
                if (backslashEndsPrevLine)      // must continue to clear variables
 
741
                        line = ' ';
 
742
                else if (emptyLineFill)
 
743
                        return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount);
 
744
                else
 
745
                        return line;
 
746
        }
 
747
 
 
748
        // handle preprocessor commands
 
749
 
 
750
        if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine))
 
751
        {
 
752
                if (line[0] == '#')
 
753
                {
 
754
                        string preproc = trim(string(line.c_str() + 1));
 
755
 
 
756
                        // When finding a multi-lined #define statement, the original beautifier
 
757
                        // 1. sets its isInDefineDefinition flag
 
758
                        // 2. clones a new beautifier that will be used for the actual indentation
 
759
                        //    of the #define. This clone is put into the activeBeautifierStack in order
 
760
                        //    to be called for the actual indentation.
 
761
                        // The original beautifier will have isInDefineDefinition = true, isInDefine = false
 
762
                        // The cloned beautifier will have   isInDefineDefinition = true, isInDefine = true
 
763
                        if (preprocessorIndent && preproc.compare(0, 6, "define") == 0 &&  line[line.length() - 1] == '\\')
 
764
                        {
 
765
                                if (!isInDefineDefinition)
 
766
                                {
 
767
                                        ASBeautifier *defineBeautifier;
 
768
 
 
769
                                        // this is the original beautifier
 
770
                                        isInDefineDefinition = true;
 
771
 
 
772
                                        // push a new beautifier into the active stack
 
773
                                        // this beautifier will be used for the indentation of this define
 
774
                                        defineBeautifier = new ASBeautifier(*this);
 
775
                                        activeBeautifierStack->push_back(defineBeautifier);
 
776
                                }
 
777
                                else
 
778
                                {
 
779
                                        // the is the cloned beautifier that is in charge of indenting the #define.
 
780
                                        isInDefine = true;
 
781
                                }
 
782
                        }
 
783
                        else if (preproc.compare(0, 2, "if") == 0)
 
784
                        {
 
785
                                // push a new beautifier into the stack
 
786
                                waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size());
 
787
                                activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size());
 
788
                                waitingBeautifierStack->push_back(new ASBeautifier(*this));
 
789
                        }
 
790
                        else if (preproc.compare(0, 4/*2*/, "else") == 0)
 
791
                        {
 
792
                                if (waitingBeautifierStack && !waitingBeautifierStack->empty())
 
793
                                {
 
794
                                        // MOVE current waiting beautifier to active stack.
 
795
                                        activeBeautifierStack->push_back(waitingBeautifierStack->back());
 
796
                                        waitingBeautifierStack->pop_back();
 
797
                                }
 
798
                        }
 
799
                        else if (preproc.compare(0, 4, "elif") == 0)
 
800
                        {
 
801
                                if (waitingBeautifierStack && !waitingBeautifierStack->empty())
 
802
                                {
 
803
                                        // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original.
 
804
                                        activeBeautifierStack->push_back(new ASBeautifier(*(waitingBeautifierStack->back())));
 
805
                                }
 
806
                        }
 
807
                        else if (preproc.compare(0, 5, "endif") == 0)
 
808
                        {
 
809
                                int stackLength;
 
810
                                ASBeautifier *beautifier;
 
811
 
 
812
                                if (waitingBeautifierStackLengthStack && !waitingBeautifierStackLengthStack->empty())
 
813
                                {
 
814
                                        stackLength = waitingBeautifierStackLengthStack->back();
 
815
                                        waitingBeautifierStackLengthStack->pop_back();
 
816
                                        while ((int) waitingBeautifierStack->size() > stackLength)
 
817
                                        {
 
818
                                                beautifier = waitingBeautifierStack->back();
 
819
                                                waitingBeautifierStack->pop_back();
 
820
                                                delete beautifier;
 
821
                                        }
 
822
                                }
 
823
 
 
824
                                if (!activeBeautifierStackLengthStack->empty())
 
825
                                {
 
826
                                        stackLength = activeBeautifierStackLengthStack->back();
 
827
                                        activeBeautifierStackLengthStack->pop_back();
 
828
                                        while ((int) activeBeautifierStack->size() > stackLength)
 
829
                                        {
 
830
                                                beautifier = activeBeautifierStack->back();
 
831
                                                activeBeautifierStack->pop_back();
 
832
                                                delete beautifier;
 
833
                                        }
 
834
                                }
 
835
                        }
 
836
                }
 
837
 
 
838
                // check if the last char is a backslash
 
839
                if (line.length() > 0)
 
840
                        backslashEndsPrevLine = (line[line.length() - 1] == '\\');
 
841
                else
 
842
                        backslashEndsPrevLine = false;
 
843
 
 
844
                // check if this line ends a multi-line #define
 
845
                // if so, use the #define's cloned beautifier for the line's indentation
 
846
                // and then remove it from the active beautifier stack and delete it.
 
847
                if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine)
 
848
                {
 
849
                        string beautifiedLine;
 
850
                        ASBeautifier *defineBeautifier;
 
851
 
 
852
                        isInDefineDefinition = false;
 
853
                        defineBeautifier = activeBeautifierStack->back();
 
854
                        activeBeautifierStack->pop_back();
 
855
 
 
856
                        beautifiedLine = defineBeautifier->beautify(line);
 
857
                        delete defineBeautifier;
 
858
                        return beautifiedLine;
 
859
                }
 
860
 
 
861
                // unless this is a multi-line #define, return this precompiler line as is.
 
862
                if (!isInDefine && !isInDefineDefinition)
 
863
                        return originalLine;
 
864
        }
 
865
 
 
866
        // if there exists any worker beautifier in the activeBeautifierStack,
 
867
        // then use it instead of me to indent the current line.
 
868
        // variables set by ASFormatter must be updated.
 
869
        if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty())
 
870
        {
 
871
                activeBeautifierStack->back()->inLineNumber = inLineNumber;
 
872
                activeBeautifierStack->back()->outLineNumber = outLineNumber;
 
873
                activeBeautifierStack->back()->lineCommentNoBeautify = lineCommentNoBeautify;
 
874
                activeBeautifierStack->back()->isNonInStatementArray = isNonInStatementArray;
 
875
                return activeBeautifierStack->back()->beautify(line);
 
876
        }
 
877
 
 
878
        // calculate preliminary indentation based on data from past lines
 
879
        if (!inStatementIndentStack->empty())
 
880
                spaceTabCount = inStatementIndentStack->back();
 
881
 
 
882
 
 
883
        for (i = 0; i < (int) headerStackSize; i++)
 
884
        {
 
885
                isInClass = false;
 
886
 
 
887
                if (blockIndent || (!(i > 0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
 
888
                                      && (*headerStack)[i] == &AS_OPEN_BRACKET)))
 
889
                        ++tabCount;
 
890
 
 
891
                if (!isJavaStyle && !namespaceIndent && i >= 1
 
892
                        && (*headerStack)[i-1] == &AS_NAMESPACE
 
893
                        && (*headerStack)[i] == &AS_OPEN_BRACKET)
 
894
                        --tabCount;
 
895
 
 
896
                if (isCStyle && i >= 1
 
897
                        && (*headerStack)[i-1] == &AS_CLASS
 
898
                        && (*headerStack)[i] == &AS_OPEN_BRACKET)
 
899
                {
 
900
                        if (classIndent)
 
901
                                ++tabCount;
 
902
                        isInClass = true;
 
903
                }
 
904
 
 
905
                // is the switchIndent option is on, indent switch statements an additional indent.
 
906
                else if (switchIndent && i > 1 &&
 
907
                         (*headerStack)[i-1] == &AS_SWITCH &&
 
908
                         (*headerStack)[i] == &AS_OPEN_BRACKET
 
909
                        )
 
910
                {
 
911
                        ++tabCount;
 
912
                        isInSwitch = true;
 
913
                }
 
914
 
 
915
        }
 
916
 
 
917
        if (!lineStartsInComment
 
918
                && isCStyle
 
919
                && isInClass
 
920
                && classIndent
 
921
                && headerStackSize >= 2
 
922
                && (*headerStack)[headerStackSize-2] == &AS_CLASS
 
923
                && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
 
924
                && line[0] == '}')
 
925
                --tabCount;
 
926
 
 
927
        else if (!lineStartsInComment
 
928
                 && isInSwitch
 
929
                 && switchIndent
 
930
                 && headerStackSize >= 2
 
931
                 && (*headerStack)[headerStackSize-2] == &AS_SWITCH
 
932
                 && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
 
933
                 && line[0] == '}')
 
934
                --tabCount;
 
935
 
 
936
        if (isInClassHeader)
 
937
        {
 
938
                isInClassHeaderTab = true;
 
939
                tabCount += 2;
 
940
        }
 
941
 
 
942
        if (isInConditional)
 
943
        {
 
944
                --tabCount;
 
945
        }
 
946
 
 
947
 
 
948
        // parse characters in the current line.
 
949
 
 
950
        for (i = 0; i < (int) line.length(); i++)
 
951
        {
 
952
                tempCh = line[i];
 
953
 
 
954
                prevCh = ch;
 
955
                ch = tempCh;
 
956
 
 
957
                outBuffer.append(1, ch);
 
958
 
 
959
                if (isWhiteSpace(ch))
 
960
                        continue;
 
961
 
 
962
                // check for utf8 characters
 
963
                // isalnum() will display an assert message in debug if not bypassed here
 
964
                if (ch < 0)
 
965
                        continue;
 
966
 
 
967
                // handle special characters (i.e. backslash+character such as \n, \t, ...)
 
968
                if (isSpecialChar)
 
969
                {
 
970
                        isSpecialChar = false;
 
971
                        continue;
 
972
                }
 
973
                if (!(isInComment || isInLineComment) && line.compare(i, 2, "\\\\") == 0)
 
974
                {
 
975
                        outBuffer.append(1, '\\');
 
976
                        i++;
 
977
                        continue;
 
978
                }
 
979
                if (!(isInComment || isInLineComment) && ch == '\\')
 
980
                {
 
981
                        isSpecialChar = true;
 
982
                        continue;
 
983
                }
 
984
 
 
985
                // handle quotes (such as 'x' and "Hello Dolly")
 
986
                if (!(isInComment || isInLineComment) && (ch == '"' || ch == '\''))
 
987
                        if (!isInQuote)
 
988
                        {
 
989
                                quoteChar = ch;
 
990
                                isInQuote = true;
 
991
                        }
 
992
                        else if (quoteChar == ch)
 
993
                        {
 
994
                                isInQuote = false;
 
995
                                isInStatement = true;
 
996
                                continue;
 
997
                        }
 
998
                if (isInQuote)
 
999
                        continue;
 
1000
 
 
1001
                // handle comments
 
1002
 
 
1003
                if (!(isInComment || isInLineComment) && line.compare(i, 2, "//") == 0)
 
1004
                {
 
1005
                        isInLineComment = true;
 
1006
                        outBuffer.append(1, '/');
 
1007
                        i++;
 
1008
                        continue;
 
1009
                } 
 
1010
                else if (!(isInComment || isInLineComment) && line.compare(i, 2, "/*") == 0)
 
1011
                { 
 
1012
                        isInComment = true;
 
1013
                        outBuffer.append(1, '*');
 
1014
                        i++;
 
1015
                        size_t j = line.find_first_not_of(" \t");
 
1016
                        if (!line.compare(j, 2, "/*") == 0)     // does line start with comment?
 
1017
                                blockCommentNoIndent = true;    // if no, cannot indent continuation lines
 
1018
                        continue;
 
1019
                }
 
1020
                else if ((isInComment || isInLineComment) && line.compare(i, 2, "*/") == 0)
 
1021
                {
 
1022
                        isInComment = false;
 
1023
                        outBuffer.append(1, '/');
 
1024
                        i++;
 
1025
                        blockCommentNoIndent = false;           // ok to indent next comment
 
1026
                        continue;
 
1027
                }
 
1028
 
 
1029
                if (isInComment || isInLineComment)
 
1030
                        continue;
 
1031
 
 
1032
                // if we have reached this far then we are NOT in a comment or string of special character...
 
1033
 
 
1034
                if (probationHeader != NULL)
 
1035
                {
 
1036
                        if (((probationHeader == &AS_STATIC || probationHeader == &AS_CONST) && ch == '{')
 
1037
                                || (probationHeader == &AS_SYNCHRONIZED && ch == '('))
 
1038
                        {
 
1039
                                // insert the probation header as a new header
 
1040
                                isInHeader = true;
 
1041
                                headerStack->push_back(probationHeader);
 
1042
 
 
1043
                                // handle the specific probation header
 
1044
                                isInConditional = (probationHeader == &AS_SYNCHRONIZED);
 
1045
                                if (probationHeader == &AS_CONST)
 
1046
                                        isImmediatelyAfterConst = true;
 
1047
 
 
1048
                                isInStatement = false;
 
1049
                                // if the probation comes from the previous line, then indent by 1 tab count.
 
1050
                                if (previousLineProbation && ch == '{')
 
1051
                                {
 
1052
                                        tabCount++;
 
1053
                                        previousLineProbationTab = true;
 
1054
                                }
 
1055
                                previousLineProbation = false;
 
1056
                        }
 
1057
 
 
1058
                        // dismiss the probation header
 
1059
                        probationHeader = NULL;
 
1060
                }
 
1061
 
 
1062
                prevNonSpaceCh = currentNonSpaceCh;
 
1063
                currentNonSpaceCh = ch;
 
1064
                if (!isLegalNameChar(ch) && ch != ',' && ch != ';')
 
1065
                {
 
1066
                        prevNonLegalCh = currentNonLegalCh;
 
1067
                        currentNonLegalCh = ch;
 
1068
                }
 
1069
 
 
1070
                if (isInHeader)
 
1071
                {
 
1072
                        isInHeader = false;
 
1073
                        currentHeader = headerStack->back();
 
1074
                }
 
1075
                else
 
1076
                        currentHeader = NULL;
 
1077
 
 
1078
                if (isCStyle && isInTemplate
 
1079
                        && (ch == '<' || ch == '>')
 
1080
                        &&  findHeader(line, i, nonAssignmentOperators) == NULL)
 
1081
                {
 
1082
                        if (ch == '<')
 
1083
                        {
 
1084
                                ++templateDepth;
 
1085
                        }
 
1086
                        else if (ch == '>')
 
1087
                        {
 
1088
                                if (--templateDepth <= 0)
 
1089
                                {
 
1090
                                        if (isInTemplate)
 
1091
                                                ch = ';';
 
1092
                                        else
 
1093
                                                ch = 't';
 
1094
                                        isInTemplate = false;
 
1095
                                        templateDepth = 0;
 
1096
                                }
 
1097
                        }
 
1098
                }
 
1099
 
 
1100
                // handle parenthesies
 
1101
                if (ch == '(' || ch == '[' || ch == ')' || ch == ']')
 
1102
                {
 
1103
                        if (ch == '(' || ch == '[')
 
1104
                        {
 
1105
                                if (parenDepth == 0)
 
1106
                                {
 
1107
                                        parenStatementStack->push_back(isInStatement);
 
1108
                                        isInStatement = true;
 
1109
                                }
 
1110
                                parenDepth++;
 
1111
 
 
1112
                                inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
 
1113
 
 
1114
                                if (currentHeader != NULL)
 
1115
                                        registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true);
 
1116
                                else
 
1117
                                        registerInStatementIndent(line, i, spaceTabCount, 0, true);
 
1118
                        }
 
1119
                        else if (ch == ')' || ch == ']')
 
1120
                        {
 
1121
                                parenDepth--;
 
1122
                                if (parenDepth == 0)
 
1123
                                {
 
1124
                                        isInStatement = parenStatementStack->back();
 
1125
                                        parenStatementStack->pop_back();
 
1126
                                        ch = ' ';
 
1127
 
 
1128
                                        isInConditional = false;
 
1129
                                }
 
1130
 
 
1131
                                if (!inStatementIndentStackSizeStack->empty())
 
1132
                                {
 
1133
                                        int previousIndentStackSize = inStatementIndentStackSizeStack->back();
 
1134
                                        inStatementIndentStackSizeStack->pop_back();
 
1135
                                        while (previousIndentStackSize < (int) inStatementIndentStack->size())
 
1136
                                                inStatementIndentStack->pop_back();
 
1137
 
 
1138
                                        if (!parenIndentStack->empty())
 
1139
                                        {
 
1140
                                                int poppedIndent = parenIndentStack->back();
 
1141
                                                parenIndentStack->pop_back();
 
1142
 
 
1143
                                                if (i == 0)
 
1144
                                                        spaceTabCount = poppedIndent;
 
1145
                                        }
 
1146
                                }
 
1147
                        }
 
1148
 
 
1149
                        continue;
 
1150
                }
 
1151
 
 
1152
 
 
1153
                if (ch == '{')
 
1154
                {
 
1155
                        bool isBlockOpener;
 
1156
                        // first, check if '{' is a block-opener or an static-array opener
 
1157
                        isBlockOpener = ((prevNonSpaceCh == '{' && bracketBlockStateStack->back())
 
1158
                                         || prevNonSpaceCh == '}'
 
1159
                                         || prevNonSpaceCh == ')'
 
1160
                                         || prevNonSpaceCh == ';'
 
1161
                                         || peekNextChar(line, i) == '{'
 
1162
                                         || isNonInStatementArray
 
1163
                                         || isInClassHeader
 
1164
//                                       || isBlockOpener
 
1165
                                         || isImmediatelyAfterConst
 
1166
                                         || (isInDefine &&
 
1167
                                             (prevNonSpaceCh == '('
 
1168
                                              || prevNonSpaceCh == '_'
 
1169
                                              || isalnum(prevNonSpaceCh))));
 
1170
 
 
1171
                        isInClassHeader = false;
 
1172
                        if (!isBlockOpener && currentHeader != NULL)
 
1173
                        {
 
1174
                                for (size_t n = 0; n < nonParenHeaders.size(); n++)
 
1175
                                        if (currentHeader == nonParenHeaders[n])
 
1176
                                        {
 
1177
                                                isBlockOpener = true;
 
1178
                                                break;
 
1179
                                        }
 
1180
                        }
 
1181
                        bracketBlockStateStack->push_back(isBlockOpener);
 
1182
                        if (!isBlockOpener)
 
1183
                        {
 
1184
                                inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
 
1185
                                registerInStatementIndent(line, i, spaceTabCount, 0, true);
 
1186
                                parenDepth++;
 
1187
                                if (i == 0)
 
1188
                                        shouldIndentBrackettedLine = false;
 
1189
 
 
1190
                                continue;
 
1191
                        }
 
1192
 
 
1193
                        // this bracket is a block opener...
 
1194
 
 
1195
                        ++lineOpeningBlocksNum;
 
1196
//                      if (isInClassHeader)
 
1197
//                      isInClassHeader = false;
 
1198
 
 
1199
                        if (isInClassHeaderTab)
 
1200
                        {
 
1201
                                isInClassHeaderTab = false;
 
1202
                                // decrease tab count if bracket is broken
 
1203
                                size_t firstChar = line.find_first_not_of(" \t");
 
1204
                                if (firstChar != string::npos)
 
1205
                                        if (line[firstChar] == '{' && (int) firstChar == i)
 
1206
                                                tabCount -= 2;
 
1207
                        }
 
1208
 
 
1209
                        // do not allow inStatementIndent - should occur for Java files only
 
1210
                        if (inStatementIndentStack->size() > 0)
 
1211
                        {
 
1212
                                spaceTabCount = 0;
 
1213
                                inStatementIndentStack->back() = 0;
 
1214
                        }
 
1215
 
 
1216
                        blockParenDepthStack->push_back(parenDepth);
 
1217
                        blockStatementStack->push_back(isInStatement);
 
1218
 
 
1219
                        inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
 
1220
                        if (inStatementIndentStack->size() > 0)
 
1221
                                inStatementIndentStack->back() = 0;
 
1222
 
 
1223
                        blockTabCount += isInStatement ? 1 : 0;
 
1224
                        parenDepth = 0;
 
1225
                        isInStatement = false;
 
1226
 
 
1227
                        tempStacks->push_back(new vector<const string*>);
 
1228
                        headerStack->push_back(&AS_OPEN_BRACKET);
 
1229
                        lastLineHeader = &AS_OPEN_BRACKET;
 
1230
 
 
1231
                        continue;
 
1232
                }
 
1233
 
 
1234
                //check if a header has been reached
 
1235
                if (isWhiteSpace(prevCh))
 
1236
                {
 
1237
                        bool isIndentableHeader = true;
 
1238
                        const string *newHeader = findHeader(line, i, headers);
 
1239
                        if (newHeader != NULL)
 
1240
                        {
 
1241
                                // if we reached here, then this is a header...
 
1242
                                isInHeader = true;
 
1243
 
 
1244
                                vector<const string*> *lastTempStack;
 
1245
                                if (tempStacks->empty())
 
1246
                                        lastTempStack = NULL;
 
1247
                                else
 
1248
                                        lastTempStack = tempStacks->back();
 
1249
 
 
1250
                                // if a new block is opened, push a new stack into tempStacks to hold the
 
1251
                                // future list of headers in the new block.
 
1252
 
 
1253
                                // take care of the special case: 'else if (...)'
 
1254
                                if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE)
 
1255
                                {
 
1256
                                        headerStack->pop_back();
 
1257
                                }
 
1258
 
 
1259
                                // take care of 'else'
 
1260
                                else if (newHeader == &AS_ELSE)
 
1261
                                {
 
1262
                                        if (lastTempStack != NULL)
 
1263
                                        {
 
1264
                                                int indexOfIf = indexOf(*lastTempStack, &AS_IF);
 
1265
                                                if (indexOfIf != -1)
 
1266
                                                {
 
1267
                                                        // recreate the header list in headerStack up to the previous 'if'
 
1268
                                                        // from the temporary snapshot stored in lastTempStack.
 
1269
                                                        int restackSize = lastTempStack->size() - indexOfIf - 1;
 
1270
                                                        for (int r = 0; r < restackSize; r++)
 
1271
                                                        {
 
1272
                                                                headerStack->push_back(lastTempStack->back());
 
1273
                                                                lastTempStack->pop_back();
 
1274
                                                        }
 
1275
                                                        if (!closingBracketReached)
 
1276
                                                                tabCount += restackSize;
 
1277
                                                }
 
1278
                                                /*
 
1279
                                                 * If the above if is not true, i.e. no 'if' before the 'else',
 
1280
                                                 * then nothing beautiful will come out of this...
 
1281
                                                 * I should think about inserting an Exception here to notify the caller of this...
 
1282
                                                 */
 
1283
                                        }
 
1284
                                }
 
1285
 
 
1286
                                // check if 'while' closes a previous 'do'
 
1287
                                else if (newHeader == &AS_WHILE)
 
1288
                                {
 
1289
                                        if (lastTempStack != NULL)
 
1290
                                        {
 
1291
                                                int indexOfDo = indexOf(*lastTempStack, &AS_DO);
 
1292
                                                if (indexOfDo != -1)
 
1293
                                                {
 
1294
                                                        // recreate the header list in headerStack up to the previous 'do'
 
1295
                                                        // from the temporary snapshot stored in lastTempStack.
 
1296
                                                        int restackSize = lastTempStack->size() - indexOfDo - 1;
 
1297
                                                        for (int r = 0; r < restackSize; r++)
 
1298
                                                        {
 
1299
                                                                headerStack->push_back(lastTempStack->back());
 
1300
                                                                lastTempStack->pop_back();
 
1301
                                                        }
 
1302
                                                        if (!closingBracketReached)
 
1303
                                                                tabCount += restackSize;
 
1304
                                                }
 
1305
                                        }
 
1306
                                }
 
1307
                                // check if 'catch' closes a previous 'try' or 'catch'
 
1308
                                else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY)
 
1309
                                {
 
1310
                                        if (lastTempStack != NULL)
 
1311
                                        {
 
1312
                                                int indexOfTry = indexOf(*lastTempStack, &AS_TRY);
 
1313
                                                if (indexOfTry == -1)
 
1314
                                                        indexOfTry = indexOf(*lastTempStack, &AS_CATCH);
 
1315
                                                if (indexOfTry != -1)
 
1316
                                                {
 
1317
                                                        // recreate the header list in headerStack up to the previous 'try'
 
1318
                                                        // from the temporary snapshot stored in lastTempStack.
 
1319
                                                        int restackSize = lastTempStack->size() - indexOfTry - 1;
 
1320
                                                        for (int r = 0; r < restackSize; r++)
 
1321
                                                        {
 
1322
                                                                headerStack->push_back(lastTempStack->back());
 
1323
                                                                lastTempStack->pop_back();
 
1324
                                                        }
 
1325
 
 
1326
                                                        if (!closingBracketReached)
 
1327
                                                                tabCount += restackSize;
 
1328
                                                }
 
1329
                                        }
 
1330
                                }
 
1331
                                else if (newHeader == &AS_CASE)
 
1332
                                {
 
1333
                                        isInCase = true;
 
1334
                                        --tabCount;
 
1335
                                }
 
1336
                                else if (newHeader == &AS_DEFAULT)
 
1337
                                {
 
1338
                                        isInCase = true;
 
1339
                                        --tabCount;
 
1340
                                }
 
1341
                                else if (newHeader == &AS_STATIC
 
1342
                                         || newHeader == &AS_SYNCHRONIZED
 
1343
                                         || (newHeader == &AS_CONST && isCStyle))
 
1344
                                {
 
1345
                                        if (!headerStack->empty() &&
 
1346
                                                (headerStack->back() == &AS_STATIC
 
1347
                                                 || headerStack->back() == &AS_SYNCHRONIZED
 
1348
                                                 || headerStack->back() == &AS_CONST))
 
1349
                                        {
 
1350
                                                isIndentableHeader = false;
 
1351
                                        }
 
1352
                                        else
 
1353
                                        {
 
1354
                                                isIndentableHeader = false;
 
1355
                                                probationHeader = newHeader;
 
1356
                                        }
 
1357
                                }
 
1358
                                else if (newHeader == &AS_CONST)
 
1359
                                {
 
1360
                                        isIndentableHeader = false;
 
1361
                                }
 
1362
                                else if (newHeader == &AS_TEMPLATE)
 
1363
                                {
 
1364
                                        if (isCStyle)
 
1365
                                                isInTemplate = true;
 
1366
                                        isIndentableHeader = false;
 
1367
                                }
 
1368
 
 
1369
 
 
1370
                                if (isIndentableHeader)
 
1371
                                {
 
1372
                                        headerStack->push_back(newHeader);
 
1373
                                        isInStatement = false;
 
1374
                                        if (indexOf(nonParenHeaders, newHeader) == -1)
 
1375
                                        {
 
1376
                                                isInConditional = true;
 
1377
                                        }
 
1378
                                        lastLineHeader = newHeader;
 
1379
                                }
 
1380
                                else
 
1381
                                        isInHeader = false;
 
1382
 
 
1383
                                outBuffer.append(newHeader->substr(1));
 
1384
                                i += newHeader->length() - 1;
 
1385
 
 
1386
                                continue;
 
1387
                        }
 
1388
                }
 
1389
 
 
1390
                if (isCStyle && !isalpha(prevCh)
 
1391
                        && line.compare(i, 8, "operator") == 0 && !isalnum(line[i+8]))
 
1392
                {
 
1393
                        isInOperator = true;
 
1394
                        outBuffer.append(AS_OPERATOR.substr(1));
 
1395
                        i += 7;
 
1396
                        continue;
 
1397
                }
 
1398
 
 
1399
                // "new" operator is a pointer, not a calculation
 
1400
                if (!isalpha(prevCh)
 
1401
                        && line.compare(i, 3, "new") == 0 && !isalnum(line[i+3]))
 
1402
                {
 
1403
                        if (prevNonSpaceCh == '=' && isInStatement && !inStatementIndentStack->empty())
 
1404
                                inStatementIndentStack->back() = 0;
 
1405
                }
 
1406
 
 
1407
                if (ch == '?')
 
1408
                        isInQuestion = true;
 
1409
 
 
1410
 
 
1411
                // special handling of 'case' statements
 
1412
                if (ch == ':')
 
1413
                {
 
1414
                        if ((int) line.length() > i + 1 && line[i+1] == ':') // look for ::
 
1415
                        {
 
1416
                                ++i;
 
1417
                                outBuffer.append(1, ':');
 
1418
                                ch = ' ';
 
1419
                                continue;
 
1420
                        }
 
1421
 
 
1422
                        else if (isInQuestion)
 
1423
                        {
 
1424
                                isInQuestion = false;
 
1425
                        }
 
1426
 
 
1427
                        else if (isCStyle && isInClass && prevNonSpaceCh != ')')
 
1428
                        {
 
1429
                                --tabCount;
 
1430
                                // found a 'private:' or 'public:' inside a class definition
 
1431
                                // so do nothing special
 
1432
                        }
 
1433
 
 
1434
                        else if (!isJavaStyle && isInClassHeader)
 
1435
                        {
 
1436
                                // found a 'class A : public B' definition
 
1437
                                // so do nothing special
 
1438
                        }
 
1439
 
 
1440
                        else if (isJavaStyle && lastLineHeader == &AS_FOR)
 
1441
                        {
 
1442
                                // found a java for-each statement
 
1443
                                // so do nothing special
 
1444
                        }
 
1445
 
 
1446
                        else if (isCStyle && prevNonSpaceCh == ')')
 
1447
                        {
 
1448
                                isInClassHeader = true;
 
1449
                                if (i == 0)
 
1450
                                        tabCount += 2;
 
1451
                        }
 
1452
                        else
 
1453
                        {
 
1454
                                currentNonSpaceCh = ';'; // so that brackets after the ':' will appear as block-openers
 
1455
                                if (isInCase)
 
1456
                                {
 
1457
                                        isInCase = false;
 
1458
                                        ch = ';'; // from here on, treat char as ';'
 
1459
                                }
 
1460
 
 
1461
 
 
1462
                                else // is in a label (e.g. 'label1:')
 
1463
                                {
 
1464
                                        if (labelIndent)
 
1465
                                                --tabCount; // unindent label by one indent
 
1466
                                        else
 
1467
                                                tabCount = 0; // completely flush indent to left
 
1468
                                }
 
1469
 
 
1470
 
 
1471
 
 
1472
                        }
 
1473
                }
 
1474
 
 
1475
                if ((ch == ';'  || (parenDepth > 0 && ch == ','))  && !inStatementIndentStackSizeStack->empty())
 
1476
                        while ((int) inStatementIndentStackSizeStack->back() + (parenDepth > 0 ? 1 : 0)
 
1477
                                < (int) inStatementIndentStack->size())
 
1478
                                inStatementIndentStack->pop_back();
 
1479
 
 
1480
 
 
1481
                // handle ends of statements
 
1482
                if ((ch == ';' && parenDepth == 0) || ch == '}'/* || (ch == ',' && parenDepth == 0)*/)
 
1483
                {
 
1484
                        if (ch == '}')
 
1485
                        {
 
1486
                                // first check if this '}' closes a previous block, or a static array...
 
1487
                                if (!bracketBlockStateStack->empty())
 
1488
                                {
 
1489
                                        bool bracketBlockState = bracketBlockStateStack->back();
 
1490
                                        bracketBlockStateStack->pop_back();
 
1491
                                        if (!bracketBlockState)
 
1492
                                        {
 
1493
                                                if (!inStatementIndentStackSizeStack->empty())
 
1494
                                                {
 
1495
                                                        // this bracket is a static array
 
1496
 
 
1497
                                                        int previousIndentStackSize = inStatementIndentStackSizeStack->back();
 
1498
                                                        inStatementIndentStackSizeStack->pop_back();
 
1499
                                                        while (previousIndentStackSize < (int) inStatementIndentStack->size())
 
1500
                                                                inStatementIndentStack->pop_back();
 
1501
                                                        parenDepth--;
 
1502
                                                        if (i == 0)
 
1503
                                                                shouldIndentBrackettedLine = false;
 
1504
 
 
1505
                                                        if (!parenIndentStack->empty())
 
1506
                                                        {
 
1507
                                                                int poppedIndent = parenIndentStack->back();
 
1508
                                                                parenIndentStack->pop_back();
 
1509
                                                                if (i == 0)
 
1510
                                                                        spaceTabCount = poppedIndent;
 
1511
                                                        }
 
1512
                                                }
 
1513
                                                continue;
 
1514
                                        }
 
1515
                                }
 
1516
 
 
1517
                                // this bracket is block closer...
 
1518
 
 
1519
                                ++lineClosingBlocksNum;
 
1520
 
 
1521
                                if (!inStatementIndentStackSizeStack->empty())
 
1522
                                        inStatementIndentStackSizeStack->pop_back();
 
1523
 
 
1524
                                if (!blockParenDepthStack->empty())
 
1525
                                {
 
1526
                                        parenDepth = blockParenDepthStack->back();
 
1527
                                        blockParenDepthStack->pop_back();
 
1528
                                        isInStatement = blockStatementStack->back();
 
1529
                                        blockStatementStack->pop_back();
 
1530
 
 
1531
                                        if (isInStatement)
 
1532
                                                blockTabCount--;
 
1533
                                }
 
1534
 
 
1535
                                closingBracketReached = true;
 
1536
                                int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET);
 
1537
                                if (headerPlace != -1)
 
1538
                                {
 
1539
                                        const string *popped = headerStack->back();
 
1540
                                        while (popped != &AS_OPEN_BRACKET)
 
1541
                                        {
 
1542
                                                headerStack->pop_back();
 
1543
                                                popped = headerStack->back();
 
1544
                                        }
 
1545
                                        headerStack->pop_back();
 
1546
 
 
1547
                                        if (!tempStacks->empty())
 
1548
                                        {
 
1549
                                                vector<const string*> *temp =  tempStacks->back();
 
1550
                                                tempStacks->pop_back();
 
1551
                                                delete temp;
 
1552
                                        }
 
1553
                                }
 
1554
 
 
1555
 
 
1556
                                ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified...
 
1557
                        }
 
1558
 
 
1559
                        /*
 
1560
                         * Create a temporary snapshot of the current block's header-list in the
 
1561
                         * uppermost inner stack in tempStacks, and clear the headerStack up to
 
1562
                         * the begining of the block.
 
1563
                         * Thus, the next future statement will think it comes one indent past
 
1564
                         * the block's '{' unless it specifically checks for a companion-header
 
1565
                         * (such as a previous 'if' for an 'else' header) within the tempStacks,
 
1566
                         * and recreates the temporary snapshot by manipulating the tempStacks.
 
1567
                         */
 
1568
                        if (!tempStacks->back()->empty())
 
1569
                                while (!tempStacks->back()->empty())
 
1570
                                        tempStacks->back()->pop_back();
 
1571
 
 
1572
                        while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET)
 
1573
                        {
 
1574
                                tempStacks->back()->push_back(headerStack->back());
 
1575
                                headerStack->pop_back();
 
1576
                        }
 
1577
 
 
1578
                        if (parenDepth == 0 && ch == ';')
 
1579
                                isInStatement = false;
 
1580
 
 
1581
                        previousLastLineHeader = NULL;
 
1582
                        isInClassHeader = false;
 
1583
                        isInQuestion = false;
 
1584
 
 
1585
                        continue;
 
1586
                }
 
1587
 
 
1588
 
 
1589
                // check for preBlockStatements ONLY if not within parenthesies
 
1590
                // (otherwise 'struct XXX' statements would be wrongly interpreted...)
 
1591
                if (isWhiteSpace(prevCh) && !isInTemplate && parenDepth == 0)
 
1592
                {
 
1593
                        const string *newHeader = findHeader(line, i, preBlockStatements);
 
1594
                        if (newHeader != NULL)
 
1595
                        {
 
1596
                                isInClassHeader = true;
 
1597
                                outBuffer.append(newHeader->substr(1));
 
1598
                                i += newHeader->length() - 1;
 
1599
                                headerStack->push_back(newHeader);
 
1600
                        }
 
1601
                }
 
1602
 
 
1603
                // Handle operators
 
1604
 
 
1605
                immediatelyPreviousAssignmentOp = NULL;
 
1606
 
 
1607
                // Check if an operator has been reached.
 
1608
                const string *foundAssignmentOp = findHeader(line, i, assignmentOperators, false);
 
1609
                if (foundAssignmentOp == &AS_RETURN)
 
1610
                        foundAssignmentOp = findHeader(line, i, assignmentOperators, true);
 
1611
                const string *foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false);
 
1612
 
 
1613
                // Since findHeader's boundry checking was not used above, it is possible
 
1614
                // that both an assignment op and a non-assignment op where found,
 
1615
                // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
 
1616
                // found operator.
 
1617
                if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
 
1618
                        if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
 
1619
                                foundAssignmentOp = NULL;
 
1620
                        else
 
1621
                                foundNonAssignmentOp = NULL;
 
1622
 
 
1623
                if (foundNonAssignmentOp != NULL)
 
1624
                {
 
1625
                        if (foundNonAssignmentOp->length() > 1)
 
1626
                        {
 
1627
                                outBuffer.append(foundNonAssignmentOp->substr(1));
 
1628
                                i += foundNonAssignmentOp->length() - 1;
 
1629
                        }
 
1630
                }
 
1631
 
 
1632
                else if (foundAssignmentOp != NULL)
 
1633
                {
 
1634
                        if (foundAssignmentOp->length() > 1)
 
1635
                        {
 
1636
                                outBuffer.append(foundAssignmentOp->substr(1));
 
1637
                                i += foundAssignmentOp->length() - 1;
 
1638
                        }
 
1639
 
 
1640
                        if (!isInOperator && !isInTemplate && !isNonInStatementArray)
 
1641
                        {
 
1642
                                registerInStatementIndent(line, i, spaceTabCount, 0, false);
 
1643
                                immediatelyPreviousAssignmentOp = foundAssignmentOp;
 
1644
                                isInStatement = true;
 
1645
                        }
 
1646
                }
 
1647
 
 
1648
                if (isInOperator)
 
1649
                        isInOperator = false;
 
1650
        }
 
1651
 
 
1652
        // handle special cases of unindentation:
 
1653
 
 
1654
        /*
 
1655
         * if '{' doesn't follow an immediately previous '{' in the headerStack
 
1656
         * (but rather another header such as "for" or "if", then unindent it
 
1657
         * by one indentation relative to its block.
 
1658
         */
 
1659
 
 
1660
        if (!lineStartsInComment
 
1661
                && !blockIndent
 
1662
                && outBuffer.length() > 0
 
1663
                && outBuffer[0] == '{'
 
1664
                && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum)
 
1665
                && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET)
 
1666
                && shouldIndentBrackettedLine)
 
1667
                --tabCount;
 
1668
 
 
1669
        else if (!lineStartsInComment
 
1670
                 && outBuffer.length() > 0
 
1671
                 && outBuffer[0] == '}'
 
1672
                 && shouldIndentBrackettedLine)
 
1673
                --tabCount;
 
1674
 
 
1675
        // correctly indent one-line-blocks...
 
1676
        else if (!lineStartsInComment
 
1677
                 && outBuffer.length() > 0
 
1678
                 && lineOpeningBlocksNum > 0
 
1679
                 && lineOpeningBlocksNum == lineClosingBlocksNum
 
1680
                 && previousLineProbationTab)
 
1681
                --tabCount; //lineOpeningBlocksNum - (blockIndent ? 1 : 0);
 
1682
 
 
1683
        if (tabCount < 0)
 
1684
                tabCount = 0;
 
1685
 
 
1686
        // take care of extra bracket indentatation option...
 
1687
        if (bracketIndent && outBuffer.length() > 0 && shouldIndentBrackettedLine)
 
1688
                if (outBuffer[0] == '{' || outBuffer[0] == '}')
 
1689
                        tabCount++;
 
1690
 
 
1691
 
 
1692
        if (isInDefine)
 
1693
        {
 
1694
                if (outBuffer[0] == '#')
 
1695
                {
 
1696
                        string preproc = trim(string(outBuffer.c_str() + 1));
 
1697
                        if (preproc.compare(0, 6, "define") == 0)
 
1698
                        {
 
1699
                                if (!inStatementIndentStack->empty()
 
1700
                                        && inStatementIndentStack->back() > 0)
 
1701
                                {
 
1702
                                        defineTabCount = tabCount;
 
1703
                                }
 
1704
                                else
 
1705
                                {
 
1706
                                        defineTabCount = tabCount - 1;
 
1707
                                        tabCount--;
 
1708
                                }
 
1709
                        }
 
1710
                }
 
1711
 
 
1712
                tabCount -= defineTabCount;
 
1713
        }
 
1714
 
 
1715
        if (tabCount < 0)
 
1716
                tabCount = 0;
 
1717
        if (lineCommentNoBeautify || blockCommentNoBeautify)
 
1718
                tabCount = spaceTabCount = 0;
 
1719
 
 
1720
        // finally, insert indentations into begining of line
 
1721
 
 
1722
        prevFinalLineSpaceTabCount = spaceTabCount;
 
1723
        prevFinalLineTabCount = tabCount;
 
1724
 
 
1725
        if (shouldForceTabIndentation)
 
1726
        {
 
1727
                tabCount += spaceTabCount / indentLength;
 
1728
                spaceTabCount = spaceTabCount % indentLength;
 
1729
        }
 
1730
 
 
1731
        outBuffer = preLineWS(spaceTabCount, tabCount) + outBuffer;
 
1732
 
 
1733
        if (lastLineHeader != NULL)
 
1734
                previousLastLineHeader = lastLineHeader;
 
1735
 
 
1736
        return outBuffer;
 
1737
}
 
1738
 
 
1739
 
 
1740
string ASBeautifier::preLineWS(int spaceTabCount, int tabCount)
 
1741
{
 
1742
        string ws;
 
1743
 
 
1744
        for (int i = 0; i < tabCount; i++)
 
1745
                ws += indentString;
 
1746
 
 
1747
        while ((spaceTabCount--) > 0)
 
1748
                ws += string(" ");
 
1749
 
 
1750
        return ws;
 
1751
 
 
1752
}
 
1753
 
 
1754
/**
 
1755
 * register an in-statement indent.
 
1756
 */
 
1757
void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount,
 
1758
        int minIndent, bool updateParenStack)
 
1759
{
 
1760
        int inStatementIndent;
 
1761
        int remainingCharNum = line.length() - i;
 
1762
        int nextNonWSChar = getNextProgramCharDistance(line, i);
 
1763
 
 
1764
        // if indent is around the last char in the line, indent instead 2 spaces from the previous indent
 
1765
        if (nextNonWSChar == remainingCharNum)
 
1766
        {
 
1767
                int previousIndent = spaceTabCount;
 
1768
                if (!inStatementIndentStack->empty())
 
1769
                        previousIndent = inStatementIndentStack->back();
 
1770
 
 
1771
                inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent);
 
1772
                if (updateParenStack)
 
1773
                        parenIndentStack->push_back(previousIndent);
 
1774
                return;
 
1775
        }
 
1776
 
 
1777
        if (updateParenStack)
 
1778
                parenIndentStack->push_back(i + spaceTabCount);
 
1779
 
 
1780
        inStatementIndent = i + nextNonWSChar + spaceTabCount;
 
1781
 
 
1782
        if (i + nextNonWSChar < minIndent)
 
1783
                inStatementIndent = minIndent + spaceTabCount;
 
1784
 
 
1785
        if (i + nextNonWSChar > maxInStatementIndent)
 
1786
                inStatementIndent =  indentLength * 2 + spaceTabCount;
 
1787
 
 
1788
        if (!inStatementIndentStack->empty() &&
 
1789
                inStatementIndent < inStatementIndentStack->back())
 
1790
                inStatementIndent = inStatementIndentStack->back();
 
1791
 
 
1792
        if (isNonInStatementArray)
 
1793
                inStatementIndent = 0;
 
1794
 
 
1795
        inStatementIndentStack->push_back(inStatementIndent);
 
1796
}
 
1797
 
 
1798
/**
 
1799
 * get distance to the next non-white sspace, non-comment character in the line.
 
1800
 * if no such character exists, return the length remaining to the end of the line.
 
1801
 */
 
1802
int ASBeautifier::getNextProgramCharDistance(const string &line, int i)
 
1803
{
 
1804
        bool inComment = false;
 
1805
        int  remainingCharNum = line.length() - i;
 
1806
        int  charDistance;
 
1807
        char ch;
 
1808
 
 
1809
        for (charDistance = 1; charDistance < remainingCharNum; charDistance++)
 
1810
        {
 
1811
                ch = line[i + charDistance];
 
1812
                if (inComment)
 
1813
                {
 
1814
                        if (line.compare(i + charDistance, 2, "*/") == 0)
 
1815
                        {
 
1816
                                charDistance++;
 
1817
                                inComment = false;
 
1818
                        }
 
1819
                        continue;
 
1820
                }
 
1821
                else if (isWhiteSpace(ch))
 
1822
                        continue;
 
1823
                else if (ch == '/')
 
1824
                {
 
1825
                        if (line.compare(i + charDistance, 2, "//") == 0)
 
1826
                                return remainingCharNum;
 
1827
                        else if (line.compare(i + charDistance, 2, "/*") == 0)
 
1828
                        {
 
1829
                                charDistance++;
 
1830
                                inComment = true;
 
1831
                        }
 
1832
                }
 
1833
                else
 
1834
                        return charDistance;
 
1835
        }
 
1836
 
 
1837
        return charDistance;
 
1838
}
 
1839
 
 
1840
 
 
1841
/**
 
1842
 * check if a specific line position contains a header, out of several possible headers.
 
1843
 *
 
1844
 * @return    a pointer to the found header. if no header was found then return NULL.
 
1845
 */
 
1846
const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry)
 
1847
{
 
1848
        int maxHeaders = possibleHeaders.size();
 
1849
        // const string *header = NULL;
 
1850
        int p;
 
1851
 
 
1852
        for (p = 0; p < maxHeaders; p++)
 
1853
        {
 
1854
                const string *header = possibleHeaders[p];
 
1855
 
 
1856
                if (line.compare(i, header->length(), header->c_str()) == 0)
 
1857
                {
 
1858
                        // check that this is a header and not a part of a longer word
 
1859
                        // (e.g. not at its begining, not at its middle...)
 
1860
 
 
1861
                        int lineLength = line.length();
 
1862
                        int headerEnd = i + header->length();
 
1863
                        char startCh = (*header)[0];   // first char of header
 
1864
                        char endCh = 0;                // char just after header
 
1865
                        char prevCh = 0;               // char just before header
 
1866
 
 
1867
                        if (headerEnd < lineLength)
 
1868
                        {
 
1869
                                endCh = line[headerEnd];
 
1870
                        }
 
1871
                        if (i > 0)
 
1872
                        {
 
1873
                                prevCh = line[i-1];
 
1874
                        }
 
1875
 
 
1876
                        if (!checkBoundry)
 
1877
                        {
 
1878
                                return header;
 
1879
                        }
 
1880
                        else if (prevCh != 0
 
1881
                                 && isLegalNameChar(startCh)
 
1882
                                 && isLegalNameChar(prevCh))
 
1883
                        {
 
1884
                                return NULL;
 
1885
                        }
 
1886
                        else if (headerEnd >= lineLength
 
1887
                                 || !isLegalNameChar(startCh)
 
1888
                                 || !isLegalNameChar(endCh))
 
1889
                        {
 
1890
                                return header;
 
1891
                        }
 
1892
                        else
 
1893
                        {
 
1894
                                return NULL;
 
1895
                        }
 
1896
                }
 
1897
        }
 
1898
 
 
1899
        return NULL;
 
1900
}
 
1901
 
 
1902
/**
 
1903
 * find the index number of a string element in a container of strings
 
1904
 *
 
1905
 * @return              the index number of element in the ocntainer. -1 if element not found.
 
1906
 * @param container     a vector of strings.
 
1907
 * @param element       the element to find .
 
1908
 */
 
1909
int ASBeautifier::indexOf(vector<const string*> &container, const string *element)
 
1910
{
 
1911
        vector<const string*>::const_iterator where;
 
1912
 
 
1913
        where = find(container.begin(), container.end(), element);
 
1914
        if (where == container.end())
 
1915
                return -1;
 
1916
        else
 
1917
                return (int) (where - container.begin());
 
1918
}
 
1919
 
 
1920
/**
 
1921
 * trim removes the white space surrounding a line.
 
1922
 *
 
1923
 * @return          the trimmed line.
 
1924
 * @param str       the line to trim.
 
1925
 */
 
1926
string ASBeautifier::trim(const string &str)
 
1927
{
 
1928
 
 
1929
        int start = 0;
 
1930
        int end = str.length() - 1;
 
1931
 
 
1932
        while (start < end && isWhiteSpace(str[start]))
 
1933
                start++;
 
1934
 
 
1935
        while (start <= end && isWhiteSpace(str[end]))
 
1936
                end--;
 
1937
 
 
1938
        string returnStr(str, start, end + 1 - start);
 
1939
        return returnStr;
 
1940
}
 
1941
 
 
1942
/**
 
1943
* peek at the next unread character.
 
1944
*
 
1945
* @return       the next unread character.
 
1946
* @param line   the line to check.
 
1947
* @param i      the current char position on the line.
 
1948
*/
 
1949
char ASBeautifier::peekNextChar(string &line, int i)
 
1950
{
 
1951
        char ch = ' ';
 
1952
        size_t peekNum = line.find_first_not_of(" \t", i + 1);
 
1953
 
 
1954
        if (peekNum == string::npos)
 
1955
                return ch;
 
1956
 
 
1957
        ch = line[peekNum];
 
1958
 
 
1959
        return ch;
 
1960
}
 
1961
 
 
1962
 
 
1963
}   // end namespace astyle
 
1964