• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/amule/wxWidgets-2.8.12/contrib/src/stc/scintilla/src/
1// Scintilla source code edit control
2/** @file LexNsis.cxx
3 ** Lexer for NSIS
4 **/
5// Copyright 2003 - 2005 by Angelo Mandato <angelo [at] spaceblue [dot] com>
6// Last Updated: 03/13/2005
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// ADDED for Scintilla v1.63
42#define SCE_NSIS_SECTIONGROUP 15
43#define SCE_NSIS_PAGEEX 16
44#define SCE_NSIS_FUNCTIONDEF 17
45#define SCE_NSIS_COMMENTBOX 18
46*/
47
48static bool isNsisNumber(char ch)
49{
50  return (ch >= '0' && ch <= '9');
51}
52
53static bool isNsisChar(char ch)
54{
55  return (ch == '.' ) || (ch == '_' ) || isNsisNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
56}
57
58static bool isNsisLetter(char ch)
59{
60  return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
61}
62
63static bool NsisNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler)
64{
65  int nNextLine = -1;
66  for( unsigned int i = start; i < end; i++ )
67  {
68    char cNext = styler.SafeGetCharAt( i );
69    if( cNext == '\n' )
70    {
71      nNextLine = i+1;
72      break;
73    }
74  }
75
76  if( nNextLine == -1 ) // We never foudn the next line...
77    return false;
78
79  for( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ )
80  {
81    char cNext = styler.SafeGetCharAt( firstChar );
82    if( cNext == ' ' )
83      continue;
84    if( cNext == '\t' )
85      continue;
86    if( cNext == '!' )
87    {
88      if( styler.Match(firstChar, "!else") )
89        return true;
90    }
91    break;
92  }
93
94  return false;
95}
96
97static int NsisCmp( char *s1, char *s2, bool bIgnoreCase )
98{
99  if( bIgnoreCase )
100     return CompareCaseInsensitive( s1, s2);
101
102  return strcmp( s1, s2 );
103}
104
105static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse, bool foldUtilityCmd )
106{
107  int style = styler.StyleAt(end);
108
109  // If the word is too long, it is not what we are looking for
110  if( end - start > 20 )
111    return foldlevel;
112
113  if( foldUtilityCmd )
114  {
115    // Check the style at this point, if it is not valid, then return zero
116    if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF &&
117        style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_IFDEFINEDEF &&
118        style != SCE_NSIS_MACRODEF && style != SCE_NSIS_SECTIONGROUP &&
119        style != SCE_NSIS_PAGEEX )
120          return foldlevel;
121  }
122  else
123  {
124    if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF &&
125        style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_SECTIONGROUP &&
126        style != SCE_NSIS_PAGEEX )
127          return foldlevel;
128  }
129
130  int newFoldlevel = foldlevel;
131  bool bIgnoreCase = false;
132  if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
133    bIgnoreCase = true;
134
135  char s[20]; // The key word we are looking for has atmost 13 characters
136  for (unsigned int i = 0; i < end - start + 1 && i < 19; i++)
137	{
138		s[i] = static_cast<char>( styler[ start + i ] );
139		s[i + 1] = '\0';
140	}
141
142  if( s[0] == '!' )
143  {
144    if( NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!macro", bIgnoreCase ) == 0 )
145      newFoldlevel++;
146    else if( NsisCmp(s, "!endif", bIgnoreCase) == 0 || NsisCmp(s, "!macroend", bIgnoreCase ) == 0 )
147      newFoldlevel--;
148    else if( bElse && NsisCmp(s, "!else", bIgnoreCase) == 0 )
149      newFoldlevel++;
150  }
151  else
152  {
153    if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionGroup", bIgnoreCase ) == 0 || NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 || NsisCmp(s, "PageEx", bIgnoreCase ) == 0 )
154      newFoldlevel++;
155    else if( NsisCmp(s, "SectionGroupEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase ) == 0 )
156      newFoldlevel--;
157  }
158
159  return newFoldlevel;
160}
161
162static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler )
163{
164  bool bIgnoreCase = false;
165  if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
166    bIgnoreCase = true;
167
168  bool bUserVars = false;
169  if( styler.GetPropertyInt("nsis.uservars") == 1 )
170    bUserVars = true;
171
172	char s[100];
173
174	WordList &Functions = *keywordLists[0];
175	WordList &Variables = *keywordLists[1];
176	WordList &Lables = *keywordLists[2];
177	WordList &UserDefined = *keywordLists[3];
178
179	for (unsigned int i = 0; i < end - start + 1 && i < 99; i++)
180	{
181    if( bIgnoreCase )
182      s[i] = static_cast<char>( tolower(styler[ start + i ] ) );
183    else
184		  s[i] = static_cast<char>( styler[ start + i ] );
185		s[i + 1] = '\0';
186	}
187
188	// Check for special words...
189	if( NsisCmp(s, "!macro", bIgnoreCase ) == 0 || NsisCmp(s, "!macroend", bIgnoreCase) == 0 ) // Covers !micro and !microend
190		return SCE_NSIS_MACRODEF;
191
192	if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 ||  NsisCmp(s, "!ifndef", bIgnoreCase) == 0 ||  NsisCmp(s, "!endif", bIgnoreCase) == 0 )
193		return SCE_NSIS_IFDEFINEDEF;
194
195  if( NsisCmp(s, "!else", bIgnoreCase ) == 0 ) // ||  NsisCmp(s, "!ifndef", bIgnoreCase) == 0 ||  NsisCmp(s, "!endif", bIgnoreCase) == 0 )
196		return SCE_NSIS_IFDEFINEDEF;
197
198  if( NsisCmp(s, "SectionGroup", bIgnoreCase) == 0 || NsisCmp(s, "SectionGroupEnd", bIgnoreCase) == 0 ) // Covers SectionGroup and SectionGroupEnd
199    return SCE_NSIS_SECTIONGROUP;
200
201	if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase) == 0 ) // Covers Section and SectionEnd
202		return SCE_NSIS_SECTIONDEF;
203
204	if( NsisCmp(s, "SubSection", bIgnoreCase) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd
205		return SCE_NSIS_SUBSECTIONDEF;
206
207  if( NsisCmp(s, "PageEx", bIgnoreCase) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase) == 0 ) // Covers PageEx and PageExEnd
208    return SCE_NSIS_PAGEEX;
209
210	if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers Function and FunctionEnd
211		return SCE_NSIS_FUNCTIONDEF;
212
213	if ( Functions.InList(s) )
214		return SCE_NSIS_FUNCTION;
215
216	if ( Variables.InList(s) )
217		return SCE_NSIS_VARIABLE;
218
219	if ( Lables.InList(s) )
220		return SCE_NSIS_LABEL;
221
222	if( UserDefined.InList(s) )
223		return SCE_NSIS_USERDEFINED;
224
225	if( strlen(s) > 3 )
226	{
227		if( s[1] == '{' && s[strlen(s)-1] == '}' )
228			return SCE_NSIS_VARIABLE;
229	}
230
231  // See if the variable is a user defined variable
232  if( s[0] == '$' && bUserVars )
233  {
234    bool bHasSimpleNsisChars = true;
235    for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
236	  {
237      if( !isNsisChar( s[j] ) )
238      {
239        bHasSimpleNsisChars = false;
240        break;
241      }
242	  }
243
244    if( bHasSimpleNsisChars )
245      return SCE_NSIS_VARIABLE;
246  }
247
248  // To check for numbers
249  if( isNsisNumber( s[0] ) )
250  {
251    bool bHasSimpleNsisNumber = true;
252    for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
253	  {
254      if( !isNsisNumber( s[j] ) )
255      {
256        bHasSimpleNsisNumber = false;
257        break;
258      }
259	  }
260
261    if( bHasSimpleNsisNumber )
262      return SCE_NSIS_NUMBER;
263  }
264
265	return SCE_NSIS_DEFAULT;
266}
267
268static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
269{
270	int state = SCE_NSIS_DEFAULT;
271  if( startPos > 0 )
272    state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox
273
274	styler.StartAt( startPos );
275	styler.GetLine( startPos );
276
277	unsigned int nLengthDoc = startPos + length;
278	styler.StartSegment( startPos );
279
280	char cCurrChar;
281	bool bVarInString = false;
282  bool bClassicVarInString = false;
283
284	unsigned int i;
285	for( i = startPos; i < nLengthDoc; i++ )
286	{
287		cCurrChar = styler.SafeGetCharAt( i );
288		char cNextChar = styler.SafeGetCharAt(i+1);
289
290		switch(state)
291		{
292			case SCE_NSIS_DEFAULT:
293				if( cCurrChar == ';' || cCurrChar == '#' ) // we have a comment line
294				{
295					styler.ColourTo(i-1, state );
296					state = SCE_NSIS_COMMENT;
297					break;
298				}
299				if( cCurrChar == '"' )
300				{
301					styler.ColourTo(i-1, state );
302					state = SCE_NSIS_STRINGDQ;
303					bVarInString = false;
304          bClassicVarInString = false;
305					break;
306				}
307				if( cCurrChar == '\'' )
308				{
309					styler.ColourTo(i-1, state );
310					state = SCE_NSIS_STRINGRQ;
311					bVarInString = false;
312          bClassicVarInString = false;
313					break;
314				}
315				if( cCurrChar == '`' )
316				{
317					styler.ColourTo(i-1, state );
318					state = SCE_NSIS_STRINGLQ;
319					bVarInString = false;
320          bClassicVarInString = false;
321					break;
322				}
323
324				// NSIS KeyWord,Function, Variable, UserDefined:
325				if( cCurrChar == '$' || isNsisChar(cCurrChar) || cCurrChar == '!' )
326				{
327					styler.ColourTo(i-1,state);
328				  state = SCE_NSIS_FUNCTION;
329
330          // If it is a number, we must check and set style here first...
331          if( isNsisNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) )
332              styler.ColourTo( i, SCE_NSIS_NUMBER);
333
334					break;
335				}
336
337        if( cCurrChar == '/' && cNextChar == '*' )
338        {
339          styler.ColourTo(i-1,state);
340          state = SCE_NSIS_COMMENTBOX;
341          break;
342        }
343
344				break;
345			case SCE_NSIS_COMMENT:
346				if( cNextChar == '\n' || cNextChar == '\r' )
347        {
348          // Special case:
349          if( cCurrChar == '\\' )
350          {
351            styler.ColourTo(i-2,state);
352            styler.ColourTo(i,SCE_NSIS_DEFAULT);
353          }
354          else
355          {
356				    styler.ColourTo(i,state);
357            state = SCE_NSIS_DEFAULT;
358          }
359        }
360				break;
361			case SCE_NSIS_STRINGDQ:
362      case SCE_NSIS_STRINGLQ:
363      case SCE_NSIS_STRINGRQ:
364
365        if( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' )
366          break; // Ignore the next character, even if it is a quote of some sort
367
368        if( cCurrChar == '"' && state == SCE_NSIS_STRINGDQ )
369				{
370					styler.ColourTo(i,state);
371				  state = SCE_NSIS_DEFAULT;
372          break;
373				}
374
375        if( cCurrChar == '`' && state == SCE_NSIS_STRINGLQ )
376        {
377					styler.ColourTo(i,state);
378				  state = SCE_NSIS_DEFAULT;
379          break;
380				}
381
382        if( cCurrChar == '\'' && state == SCE_NSIS_STRINGRQ )
383				{
384					styler.ColourTo(i,state);
385				  state = SCE_NSIS_DEFAULT;
386          break;
387				}
388
389        if( cNextChar == '\r' || cNextChar == '\n' )
390        {
391          int nCurLine = styler.GetLine(i+1);
392          int nBack = i;
393          // We need to check if the previous line has a \ in it...
394          bool bNextLine = false;
395
396          while( nBack > 0 )
397          {
398            if( styler.GetLine(nBack) != nCurLine )
399              break;
400
401            char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here
402
403            if( cTemp == '\\' )
404            {
405              bNextLine = true;
406              break;
407            }
408            if( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' )
409              break;
410
411            nBack--;
412          }
413
414          if( bNextLine )
415          {
416            styler.ColourTo(i+1,state);
417          }
418          if( bNextLine == false )
419          {
420            styler.ColourTo(i,state);
421				    state = SCE_NSIS_DEFAULT;
422          }
423        }
424				break;
425
426			case SCE_NSIS_FUNCTION:
427
428				// NSIS KeyWord:
429        if( cCurrChar == '$' )
430          state = SCE_NSIS_DEFAULT;
431        else if( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
432          state = SCE_NSIS_DEFAULT;
433				else if( (isNsisChar(cCurrChar) && !isNsisChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' )
434				{
435					state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler );
436					styler.ColourTo( i, state);
437					state = SCE_NSIS_DEFAULT;
438				}
439				else if( !isNsisChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' )
440				{
441          if( classifyWordNsis( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_NSIS_NUMBER )
442             styler.ColourTo( i-1, SCE_NSIS_NUMBER );
443
444					state = SCE_NSIS_DEFAULT;
445
446					if( cCurrChar == '"' )
447					{
448						state = SCE_NSIS_STRINGDQ;
449						bVarInString = false;
450            bClassicVarInString = false;
451					}
452					else if( cCurrChar == '`' )
453					{
454						state = SCE_NSIS_STRINGLQ;
455						bVarInString = false;
456            bClassicVarInString = false;
457					}
458					else if( cCurrChar == '\'' )
459					{
460						state = SCE_NSIS_STRINGRQ;
461						bVarInString = false;
462            bClassicVarInString = false;
463					}
464					else if( cCurrChar == '#' || cCurrChar == ';' )
465          {
466						state = SCE_NSIS_COMMENT;
467          }
468				}
469				break;
470      case SCE_NSIS_COMMENTBOX:
471
472        if( styler.SafeGetCharAt(i-1) == '*' && cCurrChar == '/' )
473        {
474          styler.ColourTo(i,state);
475          state = SCE_NSIS_DEFAULT;
476        }
477        break;
478		}
479
480		if( state == SCE_NSIS_COMMENT || state == SCE_NSIS_COMMENTBOX )
481		{
482			styler.ColourTo(i,state);
483		}
484		else if( state == SCE_NSIS_STRINGDQ || state == SCE_NSIS_STRINGLQ || state == SCE_NSIS_STRINGRQ )
485		{
486      bool bIngoreNextDollarSign = false;
487      bool bUserVars = false;
488      if( styler.GetPropertyInt("nsis.uservars") == 1 )
489        bUserVars = true;
490
491      if( bVarInString && cCurrChar == '$' )
492      {
493        bVarInString = false;
494        bIngoreNextDollarSign = true;
495      }
496      else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) )
497      {
498        styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
499        bVarInString = false;
500        bIngoreNextDollarSign = false;
501      }
502
503      // Covers "$INSTDIR and user vars like $MYVAR"
504      else if( bVarInString && !isNsisChar(cNextChar) )
505      {
506        int nWordState = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler);
507				if( nWordState == SCE_NSIS_VARIABLE )
508					styler.ColourTo( i, SCE_NSIS_STRINGVAR);
509        else if( bUserVars )
510          styler.ColourTo( i, SCE_NSIS_STRINGVAR);
511        bVarInString = false;
512      }
513      // Covers "${TEST}..."
514      else if( bClassicVarInString && cNextChar == '}' )
515      {
516        styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
517				bClassicVarInString = false;
518      }
519
520      // Start of var in string
521			if( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' )
522			{
523				styler.ColourTo( i-1, state);
524				bClassicVarInString = true;
525        bVarInString = false;
526			}
527      else if( !bIngoreNextDollarSign && cCurrChar == '$' )
528      {
529        styler.ColourTo( i-1, state);
530        bVarInString = true;
531        bClassicVarInString = false;
532      }
533		}
534	}
535
536  // Colourise remaining document
537	styler.ColourTo(nLengthDoc-1,state);
538}
539
540static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
541{
542	// No folding enabled, no reason to continue...
543	if( styler.GetPropertyInt("fold") == 0 )
544		return;
545
546  bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1;
547  bool foldUtilityCmd = styler.GetPropertyInt("nsis.foldutilcmd", 1) == 1;
548  bool blockComment = false;
549
550  int lineCurrent = styler.GetLine(startPos);
551  unsigned int safeStartPos = styler.LineStart( lineCurrent );
552
553  bool bArg1 = true;
554  int nWordStart = -1;
555
556  int levelCurrent = SC_FOLDLEVELBASE;
557	if (lineCurrent > 0)
558		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
559	int levelNext = levelCurrent;
560  int style = styler.StyleAt(safeStartPos);
561  if( style == SCE_NSIS_COMMENTBOX )
562  {
563    if( styler.SafeGetCharAt(safeStartPos) == '/' && styler.SafeGetCharAt(safeStartPos+1) == '*' )
564      levelNext++;
565    blockComment = true;
566  }
567
568  for (unsigned int i = safeStartPos; i < startPos + length; i++)
569	{
570    char chCurr = styler.SafeGetCharAt(i);
571    style = styler.StyleAt(i);
572    if( blockComment && style != SCE_NSIS_COMMENTBOX )
573    {
574      levelNext--;
575      blockComment = false;
576    }
577    else if( !blockComment && style == SCE_NSIS_COMMENTBOX )
578    {
579      levelNext++;
580      blockComment = true;
581    }
582
583    if( bArg1 && !blockComment)
584    {
585      if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') )
586      {
587        nWordStart = i;
588      }
589      else if( isNsisLetter(chCurr) == false && nWordStart > -1 )
590      {
591        int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler, foldAtElse, foldUtilityCmd );
592
593        if( newLevel == levelNext )
594        {
595          if( foldAtElse && foldUtilityCmd )
596          {
597            if( NsisNextLineHasElse(i, startPos + length, styler) )
598              levelNext--;
599          }
600        }
601        else
602          levelNext = newLevel;
603        bArg1 = false;
604      }
605    }
606
607    if( chCurr == '\n' )
608    {
609      if( bArg1 && foldAtElse && foldUtilityCmd && !blockComment )
610      {
611        if( NsisNextLineHasElse(i, startPos + length, styler) )
612          levelNext--;
613      }
614
615      // If we are on a new line...
616      int levelUse = levelCurrent;
617			int lev = levelUse | levelNext << 16;
618      if (levelUse < levelNext )
619				lev |= SC_FOLDLEVELHEADERFLAG;
620			if (lev != styler.LevelAt(lineCurrent))
621				styler.SetLevel(lineCurrent, lev);
622
623			lineCurrent++;
624			levelCurrent = levelNext;
625      bArg1 = true; // New line, lets look at first argument again
626      nWordStart = -1;
627    }
628  }
629
630	int levelUse = levelCurrent;
631	int lev = levelUse | levelNext << 16;
632	if (levelUse < levelNext)
633		lev |= SC_FOLDLEVELHEADERFLAG;
634	if (lev != styler.LevelAt(lineCurrent))
635		styler.SetLevel(lineCurrent, lev);
636}
637
638static const char * const nsisWordLists[] = {
639	"Functions",
640	"Variables",
641	"Lables",
642	"UserDefined",
643	0, };
644
645
646LexerModule lmNsis(SCLEX_NSIS, ColouriseNsisDoc, "nsis", FoldNsisDoc, nsisWordLists);
647
648