diff options
Diffstat (limited to 'tqtinterface/qt4/tools/designer/editor/yyindent.cpp')
-rw-r--r-- | tqtinterface/qt4/tools/designer/editor/yyindent.cpp | 1170 |
1 files changed, 0 insertions, 1170 deletions
diff --git a/tqtinterface/qt4/tools/designer/editor/yyindent.cpp b/tqtinterface/qt4/tools/designer/editor/yyindent.cpp deleted file mode 100644 index 1942ce8..0000000 --- a/tqtinterface/qt4/tools/designer/editor/yyindent.cpp +++ /dev/null @@ -1,1170 +0,0 @@ -/********************************************************************** -** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved. -** -** This file is part of TQt Designer. -** -** This file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free -** Software Foundation and appearing in the files LICENSE.GPL2 -** and LICENSE.GPL3 included in the packaging of this file. -** Alternatively you may (at your option) use any later version -** of the GNU General Public License if such license has been -** publicly approved by Trolltech ASA (or its successors, if any) -** and the KDE Free TQt Foundation. -** -** Please review the following information to ensure GNU General -** Public Licensing requirements will be met: -** http://trolltech.com/products/qt/licenses/licensing/opensource/. -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://trolltech.com/products/qt/licenses/licensing/licensingoverview -** or contact the sales department at sales@trolltech.com. -** -** Licensees holding valid TQt Commercial licenses may use this file in -** accordance with the TQt Commercial License Agreement provided with -** the Software. -** -** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted -** herein. -** -**********************************************************************/ - -/* - This file is a self-contained interactive indenter for C++ and TQt - Script. - - The general problem of indenting a C++ program is ill posed. On the - one hand, an indenter has to analyze programs written in a - free-form formal language that is best described in terms of - tokens, not characters, not lines. On the other hand, indentation - applies to lines and white space characters matter, and otherwise - the programs to indent are formally invalid in general, as they are - begin edited. - - The approach taken here works line by line. We receive a program - consisting of N lines or more, and we want to compute the - indentation appropriate for the Nth line. Lines beyond the Nth - lines are of no concern to us, so for simplicity we pretend the - program has exactly N lines and we call the Nth line the "bottom - line". Typically, we have to indent the bottom line when it's still - empty, so we concentrate our analysis on the N - 1 lines that - precede. - - By inspecting the (N - 1)-th line, the (N - 2)-th line, ... - backwards, we determine the kind of the bottom line and indent it - accordingly. - - * The bottom line is a comment line. See - bottomLineStartsInCComment() and - indentWhenBottomLineStartsInCComment(). - * The bottom line is a continuation line. See isContinuationLine() - and indentForContinuationLine(). - * The bottom line is a standalone line. See - indentForStandaloneLine(). - - Certain tokens that influence the indentation, notably braces, are - looked for in the lines. This is done by simple string comparison, - without a real tokenizer. Confusing constructs such as comments and - string literals are removed beforehand. -*/ - -#include <tqregexp.h> - -/* qmake ignore TQ_OBJECT */ - -/* - The indenter avoids getting stuck in almost infinite loops by - imposing arbitrary limits on the number of lines it analyzes when - looking for a construct. - - For example, the indenter never considers more than BigRoof lines - backwards when looking for the start of a C-style comment. -*/ -static const int SmallRoof = 40; -static const int BigRoof = 400; - -/* - The indenter supports a few parameters: - - * ppHardwareTabSize is the size of a '\t' in your favorite editor. - * ppIndentSize is the size of an indentation, or software tab - size. - * ppContinuationIndentSize is the extra indent for a continuation - line, when there is nothing to align against on the previous - line. - * ppCommentOffset is the indentation within a C-style comment, - when it cannot be picked up. -*/ - -static int ppHardwareTabSize = 8; -static int ppIndentSize = 4; -static int ppContinuationIndentSize = 8; - -static const int ppCommentOffset = 2; - -void setTabSize( int size ) -{ - ppHardwareTabSize = size; -} - -void setIndentSize( int size ) -{ - ppIndentSize = size; - ppContinuationIndentSize = 2 * size; -} - -static TQRegExp *literal = 0; -static TQRegExp *label = 0; -static TQRegExp *inlineCComment = 0; -static TQRegExp *braceX = 0; -static TQRegExp *iflikeKeyword = 0; - -/* - Returns the first non-space character in the string t, or - TQChar::null if the string is made only of white space. -*/ -static TQChar firstNonWhiteSpace( const TQString& t ) -{ - int i = 0; - while ( i < (int) t.length() ) { - if ( !t[i].isSpace() ) - return t[i]; - i++; - } - return TQChar::null; -} - -/* - Returns TRUE if string t is made only of white space; otherwise - returns FALSE. -*/ -static bool isOnlyWhiteSpace( const TQString& t ) -{ - return firstNonWhiteSpace( t ).isNull(); -} - -/* - Assuming string t is a line, returns the column number of a given - index. Column numbers and index are identical for strings that don't - contain '\t's. -*/ -int columnForIndex( const TQString& t, int index ) -{ - int col = 0; - if ( index > (int) t.length() ) - index = t.length(); - - for ( int i = 0; i < index; i++ ) { - if ( t[i] == TQChar('\t') ) { - col = ( (col / ppHardwareTabSize) + 1 ) * ppHardwareTabSize; - } else { - col++; - } - } - return col; -} - -/* - Returns the indentation size of string t. -*/ -int indentOfLine( const TQString& t ) -{ - return columnForIndex( t, t.find(firstNonWhiteSpace(t)) ); -} - -/* - Replaces t[k] by ch, unless t[k] is '\t'. Tab characters are better - left alone since they break the "index equals column" rule. No - provisions are taken against '\n' or '\r', which shouldn't occur in - t anyway. -*/ -static inline void eraseChar( TQString& t, int k, TQChar ch ) -{ - if ( t[k] != '\t' ) - t[k] = ch; -} - -/* - Removes some nefast constructs from a code line and returns the - resulting line. -*/ -static TQString trimmedCodeLine( const TQString& t ) -{ - TQString trimmed = t; - int k; - - /* - Replace character and string literals by X's, since they may - contain confusing characters (such as '{' and ';'). "Hello!" is - replaced by XXXXXXXX. The literals are rigourously of the same - length before and after; otherwise, we would break tqalignment of - continuation lines. - */ - k = 0; - while ( (k = trimmed.find(*literal, k)) != -1 ) { - for ( int i = 0; i < literal->matchedLength(); i++ ) - eraseChar( trimmed, k + i, 'X' ); - k += literal->matchedLength(); - } - - /* - Replace inline C-style comments by spaces. Other comments are - handled elsewhere. - */ - k = 0; - while ( (k = trimmed.find(*inlineCComment, k)) != -1 ) { - for ( int i = 0; i < inlineCComment->matchedLength(); i++ ) - eraseChar( trimmed, k + i, ' ' ); - k += inlineCComment->matchedLength(); - } - - /* - Replace goto and switch labels by whitespace, but be careful - with this case: - - foo1: bar1; - bar2; - */ - while ( trimmed.findRev(':') != -1 && trimmed.find(*label) != -1 ) { - TQString cap1 = label->cap( 1 ); - int pos1 = label->pos( 1 ); - int stop = cap1.length(); - - if ( pos1 + stop < (int) trimmed.length() && ppIndentSize < stop ) - stop = ppIndentSize; - - int i = 0; - while ( i < stop ) { - eraseChar( trimmed, pos1 + i, ' ' ); - i++; - } - while ( i < (int) cap1.length() ) { - eraseChar( trimmed, pos1 + i, ';' ); - i++; - } - } - - /* - Remove C++-style comments. - */ - k = trimmed.find( "//" ); - if ( k != -1 ) - trimmed.truncate( k ); - - return trimmed; -} - -/* - Returns '(' if the last parenthesis is opening, ')' if it is - closing, and TQChar::null if there are no parentheses in t. -*/ -static inline TQChar lastParen( const TQString& t ) -{ - int i = t.length(); - while ( i > 0 ) { - i--; - if ( t[i] == TQChar('(') || t[i] == TQChar(')') ) - return t[i]; - } - return TQChar::null; -} - -/* - Returns TRUE if typedIn the same as okayCh or is null; otherwise - returns FALSE. -*/ -static inline bool okay( TQChar typedIn, TQChar okayCh ) -{ - return typedIn == TQChar::null || typedIn == okayCh; -} - -/* - The "linizer" is a group of functions and variables to iterate - through the source code of the program to indent. The program is - given as a list of strings, with the bottom line being the line to - indent. The actual program might contain extra lines, but those are - uninteresting and not passed over to us. -*/ - -struct LinizerState -{ - TQString line; - int braceDepth; - bool leftBraceFollows; - - TQStringList::ConstIterator iter; - bool inCComment; - bool pendingRightBrace; -}; - -static TQStringList *yyProgram = 0; -static LinizerState *yyLinizerState = 0; - -// shorthands -static const TQString *yyLine = 0; -static const int *yyBraceDepth = 0; -static const bool *yyLeftBraceFollows = 0; - -/* - Saves and restores the state of the global linizer. This enables - backtracking. -*/ -#define YY_SAVE() \ - LinizerState savedState = *yyLinizerState -#define YY_RESTORE() \ - *yyLinizerState = savedState - -/* - Advances to the previous line in yyProgram and update yyLine - accordingly. yyLine is cleaned from comments and other damageable - constructs. Empty lines are skipped. -*/ -static bool readLine() -{ - int k; - - yyLinizerState->leftBraceFollows = - ( firstNonWhiteSpace(yyLinizerState->line) == TQChar('{') ); - - do { - if ( yyLinizerState->iter == yyProgram->begin() ) { - yyLinizerState->line = TQString(); - return FALSE; - } - - --yyLinizerState->iter; - yyLinizerState->line = *yyLinizerState->iter; - - yyLinizerState->line = trimmedCodeLine( yyLinizerState->line ); - - /* - Remove C-style comments that span multiple lines. If the - bottom line starts in a C-style comment, we are not aware - of that and eventually yyLine will contain a slash-aster. - - Notice that both if's can be executed, since - yyLinizerState->inCComment is potentially set to FALSE in - the first if. The order of the if's is also important. - */ - - if ( yyLinizerState->inCComment ) { - TQString slashAster( "/*" ); - - k = yyLinizerState->line.find( slashAster ); - if ( k == -1 ) { - yyLinizerState->line = TQString(); - } else { - yyLinizerState->line.truncate( k ); - yyLinizerState->inCComment = FALSE; - } - } - - if ( !yyLinizerState->inCComment ) { - TQString asterSlash( "*/" ); - - k = yyLinizerState->line.find( asterSlash ); - if ( k != -1 ) { - for ( int i = 0; i < k + 2; i++ ) - eraseChar( yyLinizerState->line, i, ' ' ); - yyLinizerState->inCComment = TRUE; - } - } - - /* - Remove preprocessor directives. - */ - k = 0; - while ( k < (int) yyLinizerState->line.length() ) { - TQChar ch = yyLinizerState->line[k]; - if ( ch == TQChar('#') ) { - yyLinizerState->line = TQString(); - } else if ( !ch.isSpace() ) { - break; - } - k++; - } - - /* - Remove trailing spaces. - */ - k = yyLinizerState->line.length(); - while ( k > 0 && yyLinizerState->line[k - 1].isSpace() ) - k--; - yyLinizerState->line.truncate( k ); - - /* - '}' increment the brace depth and '{' decrements it and not - the other way around, as we are parsing backwards. - */ - yyLinizerState->braceDepth += - yyLinizerState->line.contains( '}' ) - - yyLinizerState->line.contains( '{' ); - - /* - We use a dirty trick for - - } else ... - - We don't count the '}' yet, so that it's more or less - equivalent to the friendly construct - - } - else ... - */ - if ( yyLinizerState->pendingRightBrace ) - yyLinizerState->braceDepth++; - yyLinizerState->pendingRightBrace = - ( yyLinizerState->line.find(*braceX) == 0 ); - if ( yyLinizerState->pendingRightBrace ) - yyLinizerState->braceDepth--; - } while ( yyLinizerState->line.isEmpty() ); - - return TRUE; -} - -/* - Resets the linizer to its initial state, with yyLine containing the - line above the bottom line of the program. -*/ -static void startLinizer() -{ - yyLinizerState->braceDepth = 0; - yyLinizerState->inCComment = FALSE; - yyLinizerState->pendingRightBrace = FALSE; - - yyLine = &yyLinizerState->line; - yyBraceDepth = &yyLinizerState->braceDepth; - yyLeftBraceFollows = &yyLinizerState->leftBraceFollows; - - yyLinizerState->iter = yyProgram->end(); - --yyLinizerState->iter; - yyLinizerState->line = *yyLinizerState->iter; - readLine(); -} - -/* - Returns TRUE if the start of the bottom line of yyProgram (and - potentially the whole line) is part of a C-style comment; otherwise - returns FALSE. -*/ -static bool bottomLineStartsInCComment() -{ - TQString slashAster( "/*" ); - TQString asterSlash( "*/" ); - - /* - We could use the linizer here, but that would slow us down - terribly. We are better to trim only the code lines we need. - */ - TQStringList::ConstIterator p = yyProgram->end(); - --p; // skip bottom line - - for ( int i = 0; i < BigRoof; i++ ) { - if ( p == yyProgram->begin() ) - return FALSE; - --p; - - if ( (*p).find(slashAster) != -1 || (*p).find(asterSlash) != -1 ) { - TQString trimmed = trimmedCodeLine( *p ); - - if ( trimmed.find(slashAster) != -1 ) { - return TRUE; - } else if ( trimmed.find(asterSlash) != -1 ) { - return FALSE; - } - } - } - return FALSE; -} - -/* - Returns the recommended indent for the bottom line of yyProgram - assuming that it starts in a C-style comment, a condition that is - tested elsewhere. - - Essentially, we're trying to align against some text on the previous - line. -*/ -static int indentWhenBottomLineStartsInCComment() -{ - int k = yyLine->findRev( "/*" ); - if ( k == -1 ) { - /* - We found a normal text line in a comment. Align the - bottom line with the text on this line. - */ - return indentOfLine( *yyLine ); - } else { - /* - The C-style comment starts on this line. If there is - text on the same line, align with it. Otherwise, align - with the slash-aster plus a given offset. - */ - int indent = columnForIndex( *yyLine, k ); - k += 2; - while ( k < (int) yyLine->length() ) { - if ( !(*yyLine)[k].isSpace() ) - return columnForIndex( *yyLine, k ); - k++; - } - return indent + ppCommentOffset; - } -} - -/* - A function called match...() modifies the linizer state. If it - returns TRUE, yyLine is the top line of the matched construct; - otherwise, the linizer is left in an unknown state. - - A function called is...() keeps the linizer state intact. -*/ - -/* - Returns TRUE if the current line (and upwards) forms a braceless - control statement; otherwise returns FALSE. - - The first line of the following example is a "braceless control - statement": - - if ( x ) - y; -*/ -static bool matchBracelessControlStatement() -{ - int delimDepth = 0; - - if ( yyLine->endsWith("else") ) - return TRUE; - - if ( !yyLine->endsWith(")") ) - return FALSE; - - for ( int i = 0; i < SmallRoof; i++ ) { - int j = yyLine->length(); - while ( j > 0 ) { - j--; - TQChar ch = (*yyLine)[j]; - - switch ( ch.tqunicode() ) { - case ')': - delimDepth++; - break; - case '(': - delimDepth--; - if ( delimDepth == 0 ) { - if ( yyLine->find(*iflikeKeyword) != -1 ) { - /* - We have - - if ( x ) - y - - "if ( x )" is not part of the statement - "y". - */ - return TRUE; - } - } - if ( delimDepth == -1 ) { - /* - We have - - if ( (1 + - 2) - - and not - - if ( 1 + - 2 ) - */ - return FALSE; - } - break; - case '{': - case '}': - case ';': - /* - We met a statement separator, but not where we - expected it. What follows is probably a weird - continuation line. Be careful with ';' in for, - though. - */ - if ( ch != TQChar(';') || delimDepth == 0 ) - return FALSE; - } - } - - if ( !readLine() ) - break; - } - return FALSE; -} - -/* - Returns TRUE if yyLine is an unfinished line; otherwise returns - FALSE. - - In many places we'll use the terms "standalone line", "unfinished - line" and "continuation line". The meaning of these should be - evident from this code example: - - a = b; // standalone line - c = d + // unfinished line - e + // unfinished continuation line - f + // unfinished continuation line - g; // continuation line -*/ -static bool isUnfinishedLine() -{ - bool unf = FALSE; - - YY_SAVE(); - - if ( yyLine->isEmpty() ) - return FALSE; - - TQChar lastCh = (*yyLine)[(int) yyLine->length() - 1]; - if ( TQString("{};").find(lastCh) == -1 && !yyLine->endsWith("...") ) { - /* - It doesn't end with ';' or similar. If it's neither - "TQ_OBJECT" nor "if ( x )", it must be an unfinished line. - */ - unf = ( yyLine->contains("TQ_OBJECT") == 0 && - !matchBracelessControlStatement() ); - } else if ( lastCh == TQChar(';') ) { - if ( lastParen(*yyLine) == TQChar('(') ) { - /* - Exception: - - for ( int i = 1; i < 10; - */ - unf = TRUE; - } else if ( readLine() && yyLine->endsWith(";") && - lastParen(*yyLine) == TQChar('(') ) { - /* - Exception: - - for ( int i = 1; - i < 10; - */ - unf = TRUE; - } - } - - YY_RESTORE(); - return unf; -} - -/* - Returns TRUE if yyLine is a continuation line; otherwise returns - FALSE. -*/ -static bool isContinuationLine() -{ - bool cont = FALSE; - - YY_SAVE(); - if ( readLine() ) - cont = isUnfinishedLine(); - YY_RESTORE(); - return cont; -} - -/* - Returns the recommended indent for the bottom line of yyProgram, - assuming it's a continuation line. - - We're trying to align the continuation line against some parenthesis - or other bracked left opened on a previous line, or some interesting - operator such as '='. -*/ -static int indentForContinuationLine() -{ - int braceDepth = 0; - int delimDepth = 0; - - bool leftBraceFollowed = *yyLeftBraceFollows; - - for ( int i = 0; i < SmallRoof; i++ ) { - int hook = -1; - - int j = yyLine->length(); - while ( j > 0 && hook < 0 ) { - j--; - TQChar ch = (*yyLine)[j]; - - switch ( ch.tqunicode() ) { - case ')': - case ']': - delimDepth++; - break; - case '}': - braceDepth++; - break; - case '(': - case '[': - delimDepth--; - /* - An unclosed delimiter is a good place to align at, - at least for some styles (including Trolltech's). - */ - if ( delimDepth == -1 ) - hook = j; - break; - case '{': - braceDepth--; - /* - A left brace followed by other stuff on the same - line is typically for an enum or an initializer. - Such a brace must be treated just like the other - delimiters. - */ - if ( braceDepth == -1 ) { - if ( j < (int) yyLine->length() - 1 ) { - hook = j; - } else { - return 0; // shouldn't happen - } - } - break; - case '=': - /* - An equal sign is a very natural tqalignment hook - because it's usually the operator with the lowest - precedence in statements it appears in. Case in - point: - - int x = 1 + - 2; - - However, we have to beware of constructs such as - default arguments and explicit enum constant - values: - - void foo( int x = 0, - int y = 0 ); - - And not - - void foo( int x = 0, - int y = 0 ); - - These constructs are caracterized by a ',' at the - end of the unfinished lines or by unbalanced - parentheses. - */ - if ( TQString("!=<>").find((*yyLine)[j - 1]) == -1 && - (*yyLine)[j + 1] != '=' ) { - if ( braceDepth == 0 && delimDepth == 0 && - j < (int) yyLine->length() - 1 && - !yyLine->endsWith(",") && - (yyLine->contains('(') == yyLine->contains(')')) ) - hook = j; - } - } - } - - if ( hook >= 0 ) { - /* - Yes, we have a delimiter or an operator to align - against! We don't really align against it, but rather - against the following token, if any. In this example, - the following token is "11": - - int x = ( 11 + - 2 ); - - If there is no such token, we use a continuation indent: - - static TQRegExp foo( TQString( - "foo foo foo foo foo foo foo foo foo") ); - */ - hook++; - while ( hook < (int) yyLine->length() ) { - if ( !(*yyLine)[hook].isSpace() ) - return columnForIndex( *yyLine, hook ); - hook++; - } - return indentOfLine( *yyLine ) + ppContinuationIndentSize; - } - - if ( braceDepth != 0 ) - break; - - /* - The line's delimiters are balanced. It looks like a - continuation line or something. - */ - if ( delimDepth == 0 ) { - if ( leftBraceFollowed ) { - /* - We have - - int main() - { - - or - - Bar::Bar() - : Foo( x ) - { - - The "{" should be flush left. - */ - if ( !isContinuationLine() ) - return indentOfLine( *yyLine ); - } else if ( isContinuationLine() || yyLine->endsWith(",") ) { - /* - We have - - x = a + - b + - c; - - or - - int t[] = { - 1, 2, 3, - 4, 5, 6 - - The "c;" should fall right under the "b +", and the - "4, 5, 6" right under the "1, 2, 3,". - */ - return indentOfLine( *yyLine ); - } else { - /* - We have - - stream << 1 + - 2; - - We could, but we don't, try to analyze which - operator has precedence over which and so on, to - obtain the excellent result - - stream << 1 + - 2; - - We do have a special trick above for the assignment - operator above, though. - */ - return indentOfLine( *yyLine ) + ppContinuationIndentSize; - } - } - - if ( !readLine() ) - break; - } - return 0; -} - -/* - Returns the recommended indent for the bottom line of yyProgram if - that line is standalone (or should be indented likewise). - - Indenting a standalone line is tricky, mostly because of braceless - control statements. Grossly, we are looking backwards for a special - line, a "hook line", that we can use as a starting point to indent, - and then modify the indentation level according to the braces met - along the way to that hook. - - Let's consider a few examples. In all cases, we want to indent the - bottom line. - - Example 1: - - x = 1; - y = 2; - - The hook line is "x = 1;". We met 0 opening braces and 0 closing - braces. Therefore, "y = 2;" inherits the indent of "x = 1;". - - Example 2: - - if ( x ) { - y; - - The hook line is "if ( x ) {". No matter what precedes it, "y;" has - to be indented one level deeper than the hook line, since we met one - opening brace along the way. - - Example 3: - - if ( a ) - while ( b ) { - c; - } - d; - - To indent "d;" correctly, we have to go as far as the "if ( a )". - Compare with - - if ( a ) { - while ( b ) { - c; - } - d; - - Still, we're striving to go back as little as possible to accomodate - people with irregular indentation schemes. A hook line near at hand - is much more reliable than a remote one. -*/ -static int indentForStandaloneLine() -{ - for ( int i = 0; i < SmallRoof; i++ ) { - if ( !*yyLeftBraceFollows ) { - YY_SAVE(); - - if ( matchBracelessControlStatement() ) { - /* - The situation is this, and we want to indent "z;": - - if ( x && - y ) - z; - - yyLine is "if ( x &&". - */ - return indentOfLine( *yyLine ) + ppIndentSize; - } - YY_RESTORE(); - } - - if ( yyLine->endsWith(";") || yyLine->contains('{') > 0 ) { - /* - The situation is possibly this, and we want to indent - "z;": - - while ( x ) - y; - z; - - We return the indent of "while ( x )". In place of "y;", - any arbitrarily complex compound statement can appear. - */ - - if ( *yyBraceDepth > 0 ) { - do { - if ( !readLine() ) - break; - } while ( *yyBraceDepth > 0 ); - } - - LinizerState hookState; - - while ( isContinuationLine() ) - readLine(); - hookState = *yyLinizerState; - - readLine(); - if ( *yyBraceDepth <= 0 ) { - do { - if ( !matchBracelessControlStatement() ) - break; - hookState = *yyLinizerState; - } while ( readLine() ); - } - - *yyLinizerState = hookState; - - while ( isContinuationLine() ) - readLine(); - - /* - Never trust lines containing only '{' or '}', as some - people (Richard M. Stallman) format them weirdly. - */ - if ( yyLine->stripWhiteSpace().length() > 1 ) - return indentOfLine( *yyLine ) - *yyBraceDepth * ppIndentSize; - } - - if ( !readLine() ) - return -*yyBraceDepth * ppIndentSize; - } - return 0; -} - -/* - Constructs global variables used by the indenter. -*/ -static void initializeIndenter() -{ - literal = new TQRegExp( "([\"'])(?:\\\\.|[^\\\\])*\\1" ); - literal->setMinimal( TRUE ); - label = new TQRegExp( - "^\\s*((?:case\\b([^:]|::)+|[a-zA-Z_0-9]+)(?:\\s+Q_SLOTS)?:)(?!:)" ); - inlineCComment = new TQRegExp( "/\\*.*\\*/" ); - inlineCComment->setMinimal( TRUE ); - braceX = new TQRegExp( "^\\s*\\}\\s*(?:else|catch)\\b" ); - iflikeKeyword = new TQRegExp( "\\b(?:catch|do|for|if|while)\\b" ); - - yyLinizerState = new LinizerState; -} - -/* - Destroys global variables used by the indenter. -*/ -static void terminateIndenter() -{ - delete literal; - delete label; - delete inlineCComment; - delete braceX; - delete iflikeKeyword; - delete yyLinizerState; -} - -/* - Returns the recommended indent for the bottom line of program. - Unless null, typedIn stores the character of yyProgram that - triggered reindentation. - - This function works better if typedIn is set properly; it is - slightly more conservative if typedIn is completely wild, and - slighly more liberal if typedIn is always null. The user might be - annoyed by the liberal behavior. -*/ -int indentForBottomLine( const TQStringList& program, TQChar typedIn ) -{ - if ( program.isEmpty() ) - return 0; - - initializeIndenter(); - - yyProgram = new TQStringList( program ); - startLinizer(); - - const TQString& bottomLine = program.last(); - TQChar firstCh = firstNonWhiteSpace( bottomLine ); - int indent; - - if ( bottomLineStartsInCComment() ) { - /* - The bottom line starts in a C-style comment. Indent it - smartly, unless the user has already played around with it, - in which case it's better to leave her stuff alone. - */ - if ( isOnlyWhiteSpace(bottomLine) ) { - indent = indentWhenBottomLineStartsInCComment(); - } else { - indent = indentOfLine( bottomLine ); - } - } else if ( okay(typedIn, '#') && firstCh == TQChar('#') ) { - /* - Preprocessor directives go flush left. - */ - indent = 0; - } else { - if ( isUnfinishedLine() ) { - indent = indentForContinuationLine(); - } else { - indent = indentForStandaloneLine(); - } - - if ( okay(typedIn, '}') && firstCh == TQChar('}') ) { - /* - A closing brace is one level more to the left than the - code it follows. - */ - indent -= ppIndentSize; - } else if ( okay(typedIn, ':') ) { - TQRegExp caseLabel( - "\\s*(?:case\\b(?:[^:]|::)+" - "|(?:public|protected|private|Q_SIGNALS|default)(?:\\s+Q_SLOTS)?\\s*" - ")?:.*" ); - - if ( caseLabel.exactMatch(bottomLine) ) { - /* - Move a case label (or the ':' in front of a - constructor initialization list) one level to the - left, but only if the user did not play around with - it yet. Some users have exotic tastes in the - matter, and most users probably are not patient - enough to wait for the final ':' to format their - code properly. - - We don't attempt the same for goto labels, as the - user is probably the middle of "foo::bar". (Who - uses goto, anyway?) - */ - if ( indentOfLine(bottomLine) <= indent ) - indent -= ppIndentSize; - else - indent = indentOfLine( bottomLine ); - } - } - } - delete yyProgram; - terminateIndenter(); - return TQMAX( 0, indent ); -} - -#ifdef TQ_TEST_YYINDENT -/* - Test driver. -*/ - -#include <tqfile.h> -#include <tqtextstream.h> - -#include <errno.h> - -static TQString fileContents( const TQString& fileName ) -{ - TQFile f( fileName ); - if ( !f.open(IO_ReadOnly) ) { - qWarning( "yyindent error: Cannot open file '%s' for reading: %s", - fileName.latin1(), strerror(errno) ); - return TQString(); - } - - TQTextStream t( &f ); - TQString contents = t.read(); - f.close(); - if ( contents.isEmpty() ) - qWarning( "yyindent error: File '%s' is empty", fileName.latin1() ); - return contents; -} - -int main( int argc, char **argv ) -{ - if ( argc != 2 ) { - qWarning( "usage: yyindent file.cpp" ); - return 1; - } - - TQString code = fileContents( argv[1] ); - TQStringList program = TQStringList::split( '\n', code, TRUE ); - TQStringList p; - TQString out; - - while ( !program.isEmpty() && program.last().stripWhiteSpace().isEmpty() ) - program.remove( program.fromLast() ); - - TQStringList::ConstIterator line = program.begin(); - while ( line != program.end() ) { - p.push_back( *line ); - TQChar typedIn = firstNonWhiteSpace( *line ); - if ( p.last().endsWith(":") ) - typedIn = ':'; - - int indent = indentForBottomLine( p, typedIn ); - - if ( !(*line).stripWhiteSpace().isEmpty() ) { - for ( int j = 0; j < indent; j++ ) - out += " "; - out += (*line).stripWhiteSpace(); - } - out += "\n"; - ++line; - } - - while ( out.endsWith("\n") ) - out.truncate( out.length() - 1 ); - - printf( "%s\n", out.latin1() ); - return 0; -} -#endif |