]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexNsis.cxx
Warning fixes.
[wxWidgets.git] / src / stc / scintilla / src / LexNsis.cxx
1 // Scintilla source code edit control
2 /** @file LexNsis.cxx
3 ** Lexer for NSIS
4 **/
5 // Copyright 2003, 2004 by Angelo Mandato <angelo [at] spaceblue [dot] com>
6 // Last Updated: 02/22/2004
7 // The License.txt file describes the conditions under which this software may be distributed.
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13
14 #include "Platform.h"
15
16 #include "PropSet.h"
17 #include "Accessor.h"
18 #include "KeyWords.h"
19 #include "Scintilla.h"
20 #include "SciLexer.h"
21
22 /*
23 // located in SciLexer.h
24 #define SCLEX_NSIS 43
25
26 #define SCE_NSIS_DEFAULT 0
27 #define SCE_NSIS_COMMENT 1
28 #define SCE_NSIS_STRINGDQ 2
29 #define SCE_NSIS_STRINGLQ 3
30 #define SCE_NSIS_STRINGRQ 4
31 #define SCE_NSIS_FUNCTION 5
32 #define SCE_NSIS_VARIABLE 6
33 #define SCE_NSIS_LABEL 7
34 #define SCE_NSIS_USERDEFINED 8
35 #define SCE_NSIS_SECTIONDEF 9
36 #define SCE_NSIS_SUBSECTIONDEF 10
37 #define SCE_NSIS_IFDEFINEDEF 11
38 #define SCE_NSIS_MACRODEF 12
39 #define SCE_NSIS_STRINGVAR 13
40 #define SCE_NSIS_NUMBER 14
41 */
42
43 static bool isNsisNumber(char ch)
44 {
45 return (ch >= '0' && ch <= '9');
46 }
47
48 static bool isNsisChar(char ch)
49 {
50 return (ch == '.' ) || (ch == '_' ) || isNsisNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
51 }
52
53 static bool isNsisLetter(char ch)
54 {
55 return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
56 }
57
58 static int NsisCmp( char *s1, char *s2, bool bIgnoreCase )
59 {
60 if( bIgnoreCase )
61 return CompareCaseInsensitive( s1, s2);
62
63 return strcmp( s1, s2 );
64 }
65
66 static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler )
67 {
68 // If the word is too long, it is not what we are looking for
69 if( end - start > 13 )
70 return foldlevel;
71
72 // Check the style at this point, if it is not valid, then return zero
73 if( styler.StyleAt(end) != SCE_NSIS_FUNCTION && styler.StyleAt(end) != SCE_NSIS_SECTIONDEF &&
74 styler.StyleAt(end) != SCE_NSIS_SUBSECTIONDEF && styler.StyleAt(end) != SCE_NSIS_IFDEFINEDEF &&
75 styler.StyleAt(end) != SCE_NSIS_MACRODEF )
76 return foldlevel;
77
78 int newFoldlevel = foldlevel;
79 bool bIgnoreCase = false;
80 if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
81 bIgnoreCase = true;
82
83 char s[15]; // The key word we are looking for has atmost 13 characters
84 for (unsigned int i = 0; i < end - start + 1 && i < 14; i++)
85 {
86 s[i] = static_cast<char>( styler[ start + i ] );
87 s[i + 1] = '\0';
88 }
89
90 if( s[0] == '!' )
91 {
92 if( NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!macro", bIgnoreCase ) == 0 )
93 newFoldlevel++;
94 else if( NsisCmp(s, "!endif", bIgnoreCase) == 0 || NsisCmp(s, "!macroend", bIgnoreCase ) == 0 )
95 newFoldlevel--;
96 }
97 else
98 {
99 if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 )
100 newFoldlevel++;
101 else if( NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 )
102 newFoldlevel--;
103 }
104
105 return newFoldlevel;
106 }
107
108 static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler )
109 {
110 bool bIgnoreCase = false;
111 if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
112 bIgnoreCase = true;
113
114 bool bUserVars = false;
115 if( styler.GetPropertyInt("nsis.uservars") == 1 )
116 bUserVars = true;
117
118 char s[100];
119
120 WordList &Functions = *keywordLists[0];
121 WordList &Variables = *keywordLists[1];
122 WordList &Lables = *keywordLists[2];
123 WordList &UserDefined = *keywordLists[3];
124
125 for (unsigned int i = 0; i < end - start + 1 && i < 99; i++)
126 {
127 if( bIgnoreCase )
128 s[i] = static_cast<char>( tolower(styler[ start + i ] ) );
129 else
130 s[i] = static_cast<char>( styler[ start + i ] );
131 s[i + 1] = '\0';
132 }
133
134 // Check for special words...
135 if( NsisCmp(s, "!macro", bIgnoreCase ) == 0 || NsisCmp(s, "!macroend", bIgnoreCase) == 0 ) // Covers !micro and !microend
136 return SCE_NSIS_MACRODEF;
137
138 if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!endif", bIgnoreCase) == 0 )
139 return SCE_NSIS_IFDEFINEDEF;
140
141 if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase) == 0 ) // Covers Section and SectionEnd
142 return SCE_NSIS_SECTIONDEF;
143
144 if( NsisCmp(s, "SubSection", bIgnoreCase) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd
145 return SCE_NSIS_SUBSECTIONDEF;
146
147 if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd
148 return SCE_NSIS_FUNCTION;
149
150 if ( Functions.InList(s) )
151 return SCE_NSIS_FUNCTION;
152
153 if ( Variables.InList(s) )
154 return SCE_NSIS_VARIABLE;
155
156 if ( Lables.InList(s) )
157 return SCE_NSIS_LABEL;
158
159 if( UserDefined.InList(s) )
160 return SCE_NSIS_USERDEFINED;
161
162 if( strlen(s) > 3 )
163 {
164 if( s[1] == '{' && s[strlen(s)-1] == '}' )
165 return SCE_NSIS_VARIABLE;
166 }
167
168 // See if the variable is a user defined variable
169 if( s[0] == '$' && bUserVars )
170 {
171 bool bHasSimpleNsisChars = true;
172 for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
173 {
174 if( !isNsisChar( s[j] ) )
175 {
176 bHasSimpleNsisChars = false;
177 break;
178 }
179 }
180
181 if( bHasSimpleNsisChars )
182 return SCE_NSIS_VARIABLE;
183 }
184
185 // To check for numbers
186 if( isNsisNumber( s[0] ) )
187 {
188 bool bHasSimpleNsisNumber = true;
189 for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
190 {
191 if( s[j] == '\0' || s[j] == '\r' || s[j] == '\n' )
192 break;
193
194 if( !isNsisNumber( s[j] ) )
195 {
196 bHasSimpleNsisNumber = false;
197 break;
198 }
199 }
200
201 if( bHasSimpleNsisNumber )
202 return SCE_NSIS_NUMBER;
203 }
204
205 return SCE_NSIS_DEFAULT;
206 }
207
208 static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
209 {
210 int state = SCE_NSIS_DEFAULT;
211 styler.StartAt( startPos );
212 styler.GetLine( startPos );
213
214 unsigned int nLengthDoc = startPos + length;
215 styler.StartSegment( startPos );
216
217 char cCurrChar;
218 bool bVarInString = false;
219 bool bClassicVarInString = false;
220
221 unsigned int i;
222 for( i = startPos; i < nLengthDoc; i++ )
223 {
224 cCurrChar = styler.SafeGetCharAt( i );
225 char cNextChar = styler.SafeGetCharAt(i+1);
226
227 switch(state)
228 {
229 case SCE_NSIS_DEFAULT:
230 if( cCurrChar == ';' || cCurrChar == '#' ) // we have a comment line
231 {
232 styler.ColourTo(i-1, state );
233 state = SCE_NSIS_COMMENT;
234 break;
235 }
236 if( cCurrChar == '"' )
237 {
238 styler.ColourTo(i-1, state );
239 state = SCE_NSIS_STRINGDQ;
240 bVarInString = false;
241 bClassicVarInString = false;
242 break;
243 }
244 if( cCurrChar == '\'' )
245 {
246 styler.ColourTo(i-1, state );
247 state = SCE_NSIS_STRINGRQ;
248 bVarInString = false;
249 bClassicVarInString = false;
250 break;
251 }
252 if( cCurrChar == '`' )
253 {
254 styler.ColourTo(i-1, state );
255 state = SCE_NSIS_STRINGLQ;
256 bVarInString = false;
257 bClassicVarInString = false;
258 break;
259 }
260
261 // NSIS KeyWord,Function, Variable, UserDefined:
262 if( cCurrChar == '$' || isNsisChar(cCurrChar) || cCurrChar == '!' )
263 {
264 styler.ColourTo(i-1,state);
265 state = SCE_NSIS_FUNCTION;
266
267 // If it is a number, we must check and set style here first...
268 if( isNsisNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) )
269 styler.ColourTo( i, SCE_NSIS_NUMBER);
270
271 break;
272 }
273 break;
274 case SCE_NSIS_COMMENT:
275 if( cNextChar == '\n' || cNextChar == '\r' )
276 {
277 styler.ColourTo(i,state);
278 state = SCE_NSIS_DEFAULT;
279 }
280 break;
281 case SCE_NSIS_STRINGDQ:
282 if( cCurrChar == '"' || cNextChar == '\r' || cNextChar == '\n' )
283 {
284 styler.ColourTo(i,SCE_NSIS_STRINGDQ);
285 state = SCE_NSIS_DEFAULT;
286 }
287 break;
288 case SCE_NSIS_STRINGLQ:
289 if( cCurrChar == '`' || cNextChar == '\r' || cNextChar == '\n' )
290 {
291 styler.ColourTo(i,SCE_NSIS_STRINGLQ);
292 state = SCE_NSIS_DEFAULT;
293 }
294 break;
295 case SCE_NSIS_STRINGRQ:
296 if( cCurrChar == '\'' || cNextChar == '\r' || cNextChar == '\n' )
297 {
298 styler.ColourTo(i,SCE_NSIS_STRINGRQ);
299 state = SCE_NSIS_DEFAULT;
300 }
301 break;
302 case SCE_NSIS_FUNCTION:
303
304 // NSIS KeyWord:
305 if( cCurrChar == '$' )
306 state = SCE_NSIS_DEFAULT;
307 else if( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
308 state = SCE_NSIS_DEFAULT;
309 else if( (isNsisChar(cCurrChar) && !isNsisChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' )
310 {
311 state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler);
312 styler.ColourTo( i, state);
313 state = SCE_NSIS_DEFAULT;
314 }
315 else if( !isNsisChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' )
316 {
317 if( classifyWordNsis( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_NSIS_NUMBER )
318 styler.ColourTo( i-1, SCE_NSIS_NUMBER );
319
320 state = SCE_NSIS_DEFAULT;
321
322 if( cCurrChar == '"' )
323 {
324 state = SCE_NSIS_STRINGDQ;
325 bVarInString = false;
326 bClassicVarInString = false;
327 }
328 else if( cCurrChar == '`' )
329 {
330 state = SCE_NSIS_STRINGLQ;
331 bVarInString = false;
332 bClassicVarInString = false;
333 }
334 else if( cCurrChar == '\'' )
335 {
336 state = SCE_NSIS_STRINGRQ;
337 bVarInString = false;
338 bClassicVarInString = false;
339 }
340 else if( cCurrChar == '#' || cCurrChar == ';' )
341 {
342 state = SCE_NSIS_COMMENT;
343 }
344 }
345 break;
346 }
347
348 if( state == SCE_NSIS_COMMENT )
349 {
350 styler.ColourTo(i,state);
351 }
352 else if( state == SCE_NSIS_STRINGDQ || state == SCE_NSIS_STRINGLQ || state == SCE_NSIS_STRINGRQ )
353 {
354 bool bIngoreNextDollarSign = false;
355 bool bUserVars = false;
356 if( styler.GetPropertyInt("nsis.uservars") == 1 )
357 bUserVars = true;
358
359 if( bVarInString && cCurrChar == '$' )
360 {
361 bVarInString = false;
362 bIngoreNextDollarSign = true;
363 }
364 else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
365 {
366 bVarInString = false;
367 bIngoreNextDollarSign = true;
368 }
369
370 // Covers "$INSTDIR and user vars like $MYVAR"
371 else if( bVarInString && !isNsisChar(cNextChar) )
372 {
373 int nWordState = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler);
374 if( nWordState == SCE_NSIS_VARIABLE )
375 styler.ColourTo( i, SCE_NSIS_STRINGVAR);
376 else if( bUserVars )
377 styler.ColourTo( i, SCE_NSIS_STRINGVAR);
378 bVarInString = false;
379 }
380 // Covers "${TEST}..."
381 else if( bClassicVarInString && cNextChar == '}' )
382 {
383 styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
384 bClassicVarInString = false;
385 }
386
387 // Start of var in string
388 if( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' )
389 {
390 styler.ColourTo( i-1, state);
391 bClassicVarInString = true;
392 bVarInString = false;
393 }
394 else if( !bIngoreNextDollarSign && cCurrChar == '$' )
395 {
396 styler.ColourTo( i-1, state);
397 bVarInString = true;
398 bClassicVarInString = false;
399 }
400 }
401 }
402
403 // Colourise remaining document
404 switch( state )
405 {
406 case SCE_NSIS_COMMENT:
407 case SCE_NSIS_STRINGDQ:
408 case SCE_NSIS_STRINGLQ:
409 case SCE_NSIS_STRINGRQ:
410 case SCE_NSIS_VARIABLE:
411 case SCE_NSIS_STRINGVAR:
412 styler.ColourTo(nLengthDoc-1,state); break;
413
414 default:
415 styler.ColourTo(nLengthDoc-1,SCE_NSIS_DEFAULT); break;
416 }
417 }
418
419 static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
420 {
421 // No folding enabled, no reason to continue...
422 if( styler.GetPropertyInt("fold") == 0 )
423 return;
424
425 int lineCurrent = styler.GetLine(startPos);
426 unsigned int safeStartPos = styler.LineStart( lineCurrent );
427
428 bool bArg1 = true;
429 int nWordStart = -1;
430
431 int levelCurrent = SC_FOLDLEVELBASE;
432 if (lineCurrent > 0)
433 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
434 int levelNext = levelCurrent;
435
436 for (unsigned int i = safeStartPos; i < startPos + length; i++)
437 {
438 char chCurr = styler.SafeGetCharAt(i);
439
440 if( bArg1 ) //&& chCurr != '\n' )
441 {
442 if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') )
443 nWordStart = i;
444 else if( !isNsisLetter(chCurr) && nWordStart > -1 )
445 {
446 int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler );
447 if( newLevel != levelNext )
448 levelNext = newLevel;
449 bArg1 = false;
450 }
451 }
452
453 if( chCurr == '\n' )
454 {
455 // If we are on a new line...
456 int levelUse = levelCurrent;
457 int lev = levelUse | levelNext << 16;
458 if (levelUse < levelNext)
459 lev |= SC_FOLDLEVELHEADERFLAG;
460 if (lev != styler.LevelAt(lineCurrent))
461 styler.SetLevel(lineCurrent, lev);
462
463 lineCurrent++;
464 levelCurrent = levelNext;
465 bArg1 = true; // New line, lets look at first argument again
466 nWordStart = -1;
467 }
468 }
469
470 int levelUse = levelCurrent;
471 int lev = levelUse | levelNext << 16;
472 if (levelUse < levelNext)
473 lev |= SC_FOLDLEVELHEADERFLAG;
474 if (lev != styler.LevelAt(lineCurrent))
475 styler.SetLevel(lineCurrent, lev);
476 }
477
478 static const char * const nsisWordLists[] = {
479 "Functions",
480 "Variables",
481 "Lables",
482 "UserDefined",
483 0, };
484
485
486 LexerModule lmNsis(SCLEX_NSIS, ColouriseNsisDoc, "nsis", FoldNsisDoc, nsisWordLists);