~ubuntu-branches/ubuntu/wily/geany/wily

« back to all changes in this revision

Viewing changes to scintilla/lexers/LexCmake.cxx

  • Committer: Package Import Robot
  • Author(s): Chow Loong Jin
  • Date: 2011-12-10 07:43:26 UTC
  • mfrom: (3.3.7 sid)
  • Revision ID: package-import@ubuntu.com-20111210074326-s8yqbew5i20h33tf
Tags: 0.21-1ubuntu1
* Merge from Debian Unstable, remaining changes:
  - debian/patches/20_use_evince_viewer.patch:
     + use evince as viewer for pdf and dvi files
  - debian/patches/20_use_x_terminal_emulator.patch:
     + use x-terminal-emulator as terminal
  - debian/control
     + Add breaks on geany-plugins-common << 0.20
* Also fixes bugs:
  - Filter for MATLAB/Octave files filters everythign (LP: 885505)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Scintilla source code edit control
 
2
/** @file LexCmake.cxx
 
3
 ** Lexer for Cmake
 
4
 **/
 
5
// Copyright 2007 by Cristian Adam <cristian [dot] adam [at] gmx [dot] net>
 
6
// based on the NSIS lexer
 
7
// The License.txt file describes the conditions under which this software may be distributed.
 
8
 
 
9
#include <stdlib.h>
 
10
#include <string.h>
 
11
#include <stdio.h>
 
12
#include <stdarg.h>
 
13
#include <assert.h>
 
14
#include <ctype.h>
 
15
 
 
16
#include "ILexer.h"
 
17
#include "Scintilla.h"
 
18
#include "SciLexer.h"
 
19
 
 
20
#include "WordList.h"
 
21
#include "LexAccessor.h"
 
22
#include "Accessor.h"
 
23
#include "StyleContext.h"
 
24
#include "CharacterSet.h"
 
25
#include "LexerModule.h"
 
26
 
 
27
#ifdef SCI_NAMESPACE
 
28
using namespace Scintilla;
 
29
#endif
 
30
 
 
31
static bool isCmakeNumber(char ch)
 
32
{
 
33
    return(ch >= '0' && ch <= '9');
 
34
}
 
35
 
 
36
static bool isCmakeChar(char ch)
 
37
{
 
38
    return(ch == '.' ) || (ch == '_' ) || isCmakeNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
 
39
}
 
40
 
 
41
static bool isCmakeLetter(char ch)
 
42
{
 
43
    return(ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
 
44
}
 
45
 
 
46
static bool CmakeNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler)
 
47
{
 
48
    int nNextLine = -1;
 
49
    for ( unsigned int i = start; i < end; i++ ) {
 
50
        char cNext = styler.SafeGetCharAt( i );
 
51
        if ( cNext == '\n' ) {
 
52
            nNextLine = i+1;
 
53
            break;
 
54
        }
 
55
    }
 
56
 
 
57
    if ( nNextLine == -1 ) // We never foudn the next line...
 
58
        return false;
 
59
 
 
60
    for ( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ ) {
 
61
        char cNext = styler.SafeGetCharAt( firstChar );
 
62
        if ( cNext == ' ' )
 
63
            continue;
 
64
        if ( cNext == '\t' )
 
65
            continue;
 
66
        if ( styler.Match(firstChar, "ELSE")  || styler.Match(firstChar, "else"))
 
67
            return true;
 
68
        break;
 
69
    }
 
70
 
 
71
    return false;
 
72
}
 
73
 
 
74
static int calculateFoldCmake(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse)
 
75
{
 
76
    // If the word is too long, it is not what we are looking for
 
77
    if ( end - start > 20 )
 
78
        return foldlevel;
 
79
 
 
80
    int newFoldlevel = foldlevel;
 
81
 
 
82
    char s[20]; // The key word we are looking for has atmost 13 characters
 
83
    for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) {
 
84
        s[i] = static_cast<char>( styler[ start + i ] );
 
85
        s[i + 1] = '\0';
 
86
    }
 
87
 
 
88
    if ( CompareCaseInsensitive(s, "IF") == 0 || CompareCaseInsensitive(s, "WHILE") == 0
 
89
         || CompareCaseInsensitive(s, "MACRO") == 0 || CompareCaseInsensitive(s, "FOREACH") == 0
 
90
         || CompareCaseInsensitive(s, "ELSEIF") == 0 )
 
91
        newFoldlevel++;
 
92
    else if ( CompareCaseInsensitive(s, "ENDIF") == 0 || CompareCaseInsensitive(s, "ENDWHILE") == 0
 
93
              || CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0)
 
94
        newFoldlevel--;
 
95
    else if ( bElse && CompareCaseInsensitive(s, "ELSEIF") == 0 )
 
96
        newFoldlevel++;
 
97
    else if ( bElse && CompareCaseInsensitive(s, "ELSE") == 0 )
 
98
        newFoldlevel++;
 
99
 
 
100
    return newFoldlevel;
 
101
}
 
102
 
 
103
static int classifyWordCmake(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler )
 
104
{
 
105
    char word[100] = {0};
 
106
    char lowercaseWord[100] = {0};
 
107
 
 
108
    WordList &Commands = *keywordLists[0];
 
109
    WordList &Parameters = *keywordLists[1];
 
110
    WordList &UserDefined = *keywordLists[2];
 
111
 
 
112
    for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) {
 
113
        word[i] = static_cast<char>( styler[ start + i ] );
 
114
        lowercaseWord[i] = static_cast<char>(tolower(word[i]));
 
115
    }
 
116
 
 
117
    // Check for special words...
 
118
    if ( CompareCaseInsensitive(word, "MACRO") == 0 || CompareCaseInsensitive(word, "ENDMACRO") == 0 )
 
119
        return SCE_CMAKE_MACRODEF;
 
120
 
 
121
    if ( CompareCaseInsensitive(word, "IF") == 0 ||  CompareCaseInsensitive(word, "ENDIF") == 0 )
 
122
        return SCE_CMAKE_IFDEFINEDEF;
 
123
 
 
124
    if ( CompareCaseInsensitive(word, "ELSEIF") == 0  || CompareCaseInsensitive(word, "ELSE") == 0 )
 
125
        return SCE_CMAKE_IFDEFINEDEF;
 
126
 
 
127
    if ( CompareCaseInsensitive(word, "WHILE") == 0 || CompareCaseInsensitive(word, "ENDWHILE") == 0)
 
128
        return SCE_CMAKE_WHILEDEF;
 
129
 
 
130
    if ( CompareCaseInsensitive(word, "FOREACH") == 0 || CompareCaseInsensitive(word, "ENDFOREACH") == 0)
 
131
        return SCE_CMAKE_FOREACHDEF;
 
132
 
 
133
    if ( Commands.InList(lowercaseWord) )
 
134
        return SCE_CMAKE_COMMANDS;
 
135
 
 
136
    if ( Parameters.InList(word) )
 
137
        return SCE_CMAKE_PARAMETERS;
 
138
 
 
139
 
 
140
    if ( UserDefined.InList(word) )
 
141
        return SCE_CMAKE_USERDEFINED;
 
142
 
 
143
    if ( strlen(word) > 3 ) {
 
144
        if ( word[1] == '{' && word[strlen(word)-1] == '}' )
 
145
            return SCE_CMAKE_VARIABLE;
 
146
    }
 
147
 
 
148
    // To check for numbers
 
149
    if ( isCmakeNumber( word[0] ) ) {
 
150
        bool bHasSimpleCmakeNumber = true;
 
151
        for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) {
 
152
            if ( !isCmakeNumber( word[j] ) ) {
 
153
                bHasSimpleCmakeNumber = false;
 
154
                break;
 
155
            }
 
156
        }
 
157
 
 
158
        if ( bHasSimpleCmakeNumber )
 
159
            return SCE_CMAKE_NUMBER;
 
160
    }
 
161
 
 
162
    return SCE_CMAKE_DEFAULT;
 
163
}
 
164
 
 
165
static void ColouriseCmakeDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
 
166
{
 
167
    int state = SCE_CMAKE_DEFAULT;
 
168
    if ( startPos > 0 )
 
169
        state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox
 
170
 
 
171
    styler.StartAt( startPos );
 
172
    styler.GetLine( startPos );
 
173
 
 
174
    unsigned int nLengthDoc = startPos + length;
 
175
    styler.StartSegment( startPos );
 
176
 
 
177
    char cCurrChar;
 
178
    bool bVarInString = false;
 
179
    bool bClassicVarInString = false;
 
180
 
 
181
    unsigned int i;
 
182
    for ( i = startPos; i < nLengthDoc; i++ ) {
 
183
        cCurrChar = styler.SafeGetCharAt( i );
 
184
        char cNextChar = styler.SafeGetCharAt(i+1);
 
185
 
 
186
        switch (state) {
 
187
        case SCE_CMAKE_DEFAULT:
 
188
            if ( cCurrChar == '#' ) { // we have a comment line
 
189
                styler.ColourTo(i-1, state );
 
190
                state = SCE_CMAKE_COMMENT;
 
191
                break;
 
192
            }
 
193
            if ( cCurrChar == '"' ) {
 
194
                styler.ColourTo(i-1, state );
 
195
                state = SCE_CMAKE_STRINGDQ;
 
196
                bVarInString = false;
 
197
                bClassicVarInString = false;
 
198
                break;
 
199
            }
 
200
            if ( cCurrChar == '\'' ) {
 
201
                styler.ColourTo(i-1, state );
 
202
                state = SCE_CMAKE_STRINGRQ;
 
203
                bVarInString = false;
 
204
                bClassicVarInString = false;
 
205
                break;
 
206
            }
 
207
            if ( cCurrChar == '`' ) {
 
208
                styler.ColourTo(i-1, state );
 
209
                state = SCE_CMAKE_STRINGLQ;
 
210
                bVarInString = false;
 
211
                bClassicVarInString = false;
 
212
                break;
 
213
            }
 
214
 
 
215
            // CMake Variable
 
216
            if ( cCurrChar == '$' || isCmakeChar(cCurrChar)) {
 
217
                styler.ColourTo(i-1,state);
 
218
                state = SCE_CMAKE_VARIABLE;
 
219
 
 
220
                // If it is a number, we must check and set style here first...
 
221
                if ( isCmakeNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) )
 
222
                    styler.ColourTo( i, SCE_CMAKE_NUMBER);
 
223
 
 
224
                break;
 
225
            }
 
226
 
 
227
            break;
 
228
        case SCE_CMAKE_COMMENT:
 
229
            if ( cNextChar == '\n' || cNextChar == '\r' ) {
 
230
                // Special case:
 
231
                if ( cCurrChar == '\\' ) {
 
232
                    styler.ColourTo(i-2,state);
 
233
                    styler.ColourTo(i,SCE_CMAKE_DEFAULT);
 
234
                }
 
235
                else {
 
236
                    styler.ColourTo(i,state);
 
237
                    state = SCE_CMAKE_DEFAULT;
 
238
                }
 
239
            }
 
240
            break;
 
241
        case SCE_CMAKE_STRINGDQ:
 
242
        case SCE_CMAKE_STRINGLQ:
 
243
        case SCE_CMAKE_STRINGRQ:
 
244
 
 
245
            if ( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' )
 
246
                break; // Ignore the next character, even if it is a quote of some sort
 
247
 
 
248
            if ( cCurrChar == '"' && state == SCE_CMAKE_STRINGDQ ) {
 
249
                styler.ColourTo(i,state);
 
250
                state = SCE_CMAKE_DEFAULT;
 
251
                break;
 
252
            }
 
253
 
 
254
            if ( cCurrChar == '`' && state == SCE_CMAKE_STRINGLQ ) {
 
255
                styler.ColourTo(i,state);
 
256
                state = SCE_CMAKE_DEFAULT;
 
257
                break;
 
258
            }
 
259
 
 
260
            if ( cCurrChar == '\'' && state == SCE_CMAKE_STRINGRQ ) {
 
261
                styler.ColourTo(i,state);
 
262
                state = SCE_CMAKE_DEFAULT;
 
263
                break;
 
264
            }
 
265
 
 
266
            if ( cNextChar == '\r' || cNextChar == '\n' ) {
 
267
                int nCurLine = styler.GetLine(i+1);
 
268
                int nBack = i;
 
269
                // We need to check if the previous line has a \ in it...
 
270
                bool bNextLine = false;
 
271
 
 
272
                while ( nBack > 0 ) {
 
273
                    if ( styler.GetLine(nBack) != nCurLine )
 
274
                        break;
 
275
 
 
276
                    char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here
 
277
 
 
278
                    if ( cTemp == '\\' ) {
 
279
                        bNextLine = true;
 
280
                        break;
 
281
                    }
 
282
                    if ( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' )
 
283
                        break;
 
284
 
 
285
                    nBack--;
 
286
                }
 
287
 
 
288
                if ( bNextLine ) {
 
289
                    styler.ColourTo(i+1,state);
 
290
                }
 
291
                if ( bNextLine == false ) {
 
292
                    styler.ColourTo(i,state);
 
293
                    state = SCE_CMAKE_DEFAULT;
 
294
                }
 
295
            }
 
296
            break;
 
297
 
 
298
        case SCE_CMAKE_VARIABLE:
 
299
 
 
300
            // CMake Variable:
 
301
            if ( cCurrChar == '$' )
 
302
                state = SCE_CMAKE_DEFAULT;
 
303
            else if ( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
 
304
                state = SCE_CMAKE_DEFAULT;
 
305
            else if ( (isCmakeChar(cCurrChar) && !isCmakeChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) {
 
306
                state = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler );
 
307
                styler.ColourTo( i, state);
 
308
                state = SCE_CMAKE_DEFAULT;
 
309
            }
 
310
            else if ( !isCmakeChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) {
 
311
                if ( classifyWordCmake( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_CMAKE_NUMBER )
 
312
                    styler.ColourTo( i-1, SCE_CMAKE_NUMBER );
 
313
 
 
314
                state = SCE_CMAKE_DEFAULT;
 
315
 
 
316
                if ( cCurrChar == '"' ) {
 
317
                    state = SCE_CMAKE_STRINGDQ;
 
318
                    bVarInString = false;
 
319
                    bClassicVarInString = false;
 
320
                }
 
321
                else if ( cCurrChar == '`' ) {
 
322
                    state = SCE_CMAKE_STRINGLQ;
 
323
                    bVarInString = false;
 
324
                    bClassicVarInString = false;
 
325
                }
 
326
                else if ( cCurrChar == '\'' ) {
 
327
                    state = SCE_CMAKE_STRINGRQ;
 
328
                    bVarInString = false;
 
329
                    bClassicVarInString = false;
 
330
                }
 
331
                else if ( cCurrChar == '#' ) {
 
332
                    state = SCE_CMAKE_COMMENT;
 
333
                }
 
334
            }
 
335
            break;
 
336
        }
 
337
 
 
338
        if ( state == SCE_CMAKE_COMMENT) {
 
339
            styler.ColourTo(i,state);
 
340
        }
 
341
        else if ( state == SCE_CMAKE_STRINGDQ || state == SCE_CMAKE_STRINGLQ || state == SCE_CMAKE_STRINGRQ ) {
 
342
            bool bIngoreNextDollarSign = false;
 
343
 
 
344
            if ( bVarInString && cCurrChar == '$' ) {
 
345
                bVarInString = false;
 
346
                bIngoreNextDollarSign = true;
 
347
            }
 
348
            else if ( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) {
 
349
                styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR);
 
350
                bVarInString = false;
 
351
                bIngoreNextDollarSign = false;
 
352
            }
 
353
 
 
354
            else if ( bVarInString && !isCmakeChar(cNextChar) ) {
 
355
                int nWordState = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler);
 
356
                if ( nWordState == SCE_CMAKE_VARIABLE )
 
357
                    styler.ColourTo( i, SCE_CMAKE_STRINGVAR);
 
358
                bVarInString = false;
 
359
            }
 
360
            // Covers "${TEST}..."
 
361
            else if ( bClassicVarInString && cNextChar == '}' ) {
 
362
                styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR);
 
363
                bClassicVarInString = false;
 
364
            }
 
365
 
 
366
            // Start of var in string
 
367
            if ( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) {
 
368
                styler.ColourTo( i-1, state);
 
369
                bClassicVarInString = true;
 
370
                bVarInString = false;
 
371
            }
 
372
            else if ( !bIngoreNextDollarSign && cCurrChar == '$' ) {
 
373
                styler.ColourTo( i-1, state);
 
374
                bVarInString = true;
 
375
                bClassicVarInString = false;
 
376
            }
 
377
        }
 
378
    }
 
379
 
 
380
    // Colourise remaining document
 
381
    styler.ColourTo(nLengthDoc-1,state);
 
382
}
 
383
 
 
384
static void FoldCmakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
 
385
{
 
386
    // No folding enabled, no reason to continue...
 
387
    if ( styler.GetPropertyInt("fold") == 0 )
 
388
        return;
 
389
 
 
390
    bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1;
 
391
 
 
392
    int lineCurrent = styler.GetLine(startPos);
 
393
    unsigned int safeStartPos = styler.LineStart( lineCurrent );
 
394
 
 
395
    bool bArg1 = true;
 
396
    int nWordStart = -1;
 
397
 
 
398
    int levelCurrent = SC_FOLDLEVELBASE;
 
399
    if (lineCurrent > 0)
 
400
        levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
 
401
    int levelNext = levelCurrent;
 
402
 
 
403
    for (unsigned int i = safeStartPos; i < startPos + length; i++) {
 
404
        char chCurr = styler.SafeGetCharAt(i);
 
405
 
 
406
        if ( bArg1 ) {
 
407
            if ( nWordStart == -1 && (isCmakeLetter(chCurr)) ) {
 
408
                nWordStart = i;
 
409
            }
 
410
            else if ( isCmakeLetter(chCurr) == false && nWordStart > -1 ) {
 
411
                int newLevel = calculateFoldCmake( nWordStart, i-1, levelNext, styler, foldAtElse);
 
412
 
 
413
                if ( newLevel == levelNext ) {
 
414
                    if ( foldAtElse ) {
 
415
                        if ( CmakeNextLineHasElse(i, startPos + length, styler) )
 
416
                            levelNext--;
 
417
                    }
 
418
                }
 
419
                else
 
420
                    levelNext = newLevel;
 
421
                bArg1 = false;
 
422
            }
 
423
        }
 
424
 
 
425
        if ( chCurr == '\n' ) {
 
426
            if ( bArg1 && foldAtElse) {
 
427
                if ( CmakeNextLineHasElse(i, startPos + length, styler) )
 
428
                    levelNext--;
 
429
            }
 
430
 
 
431
            // If we are on a new line...
 
432
            int levelUse = levelCurrent;
 
433
            int lev = levelUse | levelNext << 16;
 
434
            if (levelUse < levelNext )
 
435
                lev |= SC_FOLDLEVELHEADERFLAG;
 
436
            if (lev != styler.LevelAt(lineCurrent))
 
437
                styler.SetLevel(lineCurrent, lev);
 
438
 
 
439
            lineCurrent++;
 
440
            levelCurrent = levelNext;
 
441
            bArg1 = true; // New line, lets look at first argument again
 
442
            nWordStart = -1;
 
443
        }
 
444
    }
 
445
 
 
446
    int levelUse = levelCurrent;
 
447
    int lev = levelUse | levelNext << 16;
 
448
    if (levelUse < levelNext)
 
449
        lev |= SC_FOLDLEVELHEADERFLAG;
 
450
    if (lev != styler.LevelAt(lineCurrent))
 
451
        styler.SetLevel(lineCurrent, lev);
 
452
}
 
453
 
 
454
static const char * const cmakeWordLists[] = {
 
455
    "Commands",
 
456
    "Parameters",
 
457
    "UserDefined",
 
458
    0,
 
459
    0,};
 
460
 
 
461
LexerModule lmCmake(SCLEX_CMAKE, ColouriseCmakeDoc, "cmake", FoldCmakeDoc, cmakeWordLists);