diff options
-rw-r--r-- | include/SciLexer.h | 1 | ||||
-rw-r--r-- | include/Scintilla.iface | 1 | ||||
-rw-r--r-- | src/LexNsis.cxx | 332 |
3 files changed, 235 insertions, 99 deletions
diff --git a/include/SciLexer.h b/include/SciLexer.h index a93397adc..997f5f77b 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -560,6 +560,7 @@ #define SCE_NSIS_IFDEFINEDEF 11 #define SCE_NSIS_MACRODEF 12 #define SCE_NSIS_STRINGVAR 13 +#define SCE_NSIS_NUMBER 14 #define SCE_MMIXAL_LEADWS 0 #define SCE_MMIXAL_COMMENT 1 #define SCE_MMIXAL_LABEL 2 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index d84ab688e..9175681f9 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -2272,6 +2272,7 @@ val SCE_NSIS_SUBSECTIONDEF=10 val SCE_NSIS_IFDEFINEDEF=11 val SCE_NSIS_MACRODEF=12 val SCE_NSIS_STRINGVAR=13 +val SCE_NSIS_NUMBER=14 # Lexical states for SCLEX_MMIXAL lex MMIXAL=SCLEX_MMIXAL SCE_MMIXAL_ val SCE_MMIXAL_LEADWS=0 diff --git a/src/LexNsis.cxx b/src/LexNsis.cxx index c09a8ae86..dbaf28598 100644 --- a/src/LexNsis.cxx +++ b/src/LexNsis.cxx @@ -2,7 +2,8 @@ /** @file LexNsis.cxx ** Lexer for NSIS **/ -// Copyright 2003 by Angelo Mandato <angelo@spaceblue.com> +// Copyright 2003, 2004 by Angelo Mandato <angelo@spaceblue.com> +// Last Updated: 01/29/2004 // The License.txt file describes the conditions under which this software may be distributed. #include <stdlib.h> @@ -20,8 +21,8 @@ #include "SciLexer.h" /* -// Put in SciLexer.h -#define SCLEX_NSIS 34 +// located in SciLexer.h +#define SCLEX_NSIS 43 #define SCE_NSIS_DEFAULT 0 #define SCE_NSIS_COMMENT 1 @@ -37,10 +38,84 @@ #define SCE_NSIS_IFDEFINEDEF 11 #define SCE_NSIS_MACRODEF 12 #define SCE_NSIS_STRINGVAR 13 +#define SCE_NSIS_NUMBER 14 // NEW option */ -static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler) +static bool isNsisNumber(char ch) { + return (ch >= '0' && ch <= '9'); +} + +static bool isNsisChar(char ch) +{ + return (ch == '.' ) || (ch == '_' ) || isNsisNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static bool isNsisLetter(char ch) +{ + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +static int NsisCmp( char *s1, char *s2, bool bIgnoreCase ) +{ + if( bIgnoreCase ) + return CompareCaseInsensitive( s1, s2); + + return strcmp( s1, s2 ); +} + +static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler ) +{ + // If the word is too long, it is not what we are looking for + if( end - start > 13 ) + return foldlevel; + + // Check the style at this point, if it is not valid, then return zero + if( styler.StyleAt(end) != SCE_NSIS_FUNCTION && styler.StyleAt(end) != SCE_NSIS_SECTIONDEF && + styler.StyleAt(end) != SCE_NSIS_SUBSECTIONDEF && styler.StyleAt(end) != SCE_NSIS_IFDEFINEDEF && + styler.StyleAt(end) != SCE_NSIS_MACRODEF ) + return foldlevel; + + int newFoldlevel = foldlevel; + bool bIgnoreCase = false; + if( styler.GetPropertyInt("nsis.ignorecase") == 1 ) + bIgnoreCase = true; + + char s[15]; // The key word we are looking for has atmost 13 characters + for (unsigned int i = 0; i < end - start + 1 && i < 14; i++) + { + s[i] = static_cast<char>( styler[ start + i ] ); + s[i + 1] = '\0'; + } + + if( s[0] == '!' ) + { + if( NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!macro", bIgnoreCase ) == 0 ) + newFoldlevel++; + else if( NsisCmp(s, "!endif", bIgnoreCase) == 0 || NsisCmp(s, "!macroend", bIgnoreCase ) == 0 ) + newFoldlevel--; + } + else + { + if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 ) + newFoldlevel++; + else if( NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 ) + newFoldlevel--; + } + + return newFoldlevel; +} + +static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler ) +{ + bool bIgnoreCase = false; + if( styler.GetPropertyInt("nsis.ignorecase") == 1 ) + bIgnoreCase = true; + + bool bUserVars = false; + if( styler.GetPropertyInt("nsis.uservars") == 1 ) + bUserVars = true; + char s[100]; WordList &Functions = *keywordLists[0]; @@ -48,27 +123,29 @@ static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keyw WordList &Lables = *keywordLists[2]; WordList &UserDefined = *keywordLists[3]; - for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) + for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) { - s[i] = static_cast<char>( styler[ start + i ] ); + if( bIgnoreCase ) + s[i] = static_cast<char>( tolower(styler[ start + i ] ) ); + else + s[i] = static_cast<char>( styler[ start + i ] ); s[i + 1] = '\0'; } // Check for special words... - - if( strcmp(s, "!macro") == 0 || strcmp(s, "!macroend") == 0 ) // Covers !micro and !microend + if( NsisCmp(s, "!macro", bIgnoreCase ) == 0 || NsisCmp(s, "!macroend", bIgnoreCase) == 0 ) // Covers !micro and !microend return SCE_NSIS_MACRODEF; - if( strcmp(s, "!ifdef") == 0 || strcmp(s, "!ifndef") == 0 || strcmp(s, "!endif") == 0 ) + if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!endif", bIgnoreCase) == 0 ) return SCE_NSIS_IFDEFINEDEF; - if( strcmp(s, "Section") == 0 || strcmp(s, "SectionEnd") == 0 ) // Covers Section and SectionEnd + if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase) == 0 ) // Covers Section and SectionEnd return SCE_NSIS_SECTIONDEF; - if( strcmp(s, "SubSection") == 0 || strcmp(s, "SubSectionEnd") == 0 ) // Covers SubSection and SubSectionEnd + if( NsisCmp(s, "SubSection", bIgnoreCase) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd return SCE_NSIS_SUBSECTIONDEF; - if( strcmp(s, "Function") == 0 || strcmp(s, "FunctionEnd") == 0 ) // Covers SubSection and SubSectionEnd + if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd return SCE_NSIS_FUNCTION; if ( Functions.InList(s) ) @@ -83,12 +160,49 @@ static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keyw if( UserDefined.InList(s) ) return SCE_NSIS_USERDEFINED; - if( strlen(s) > 2 ) + if( strlen(s) > 3 ) { if( s[1] == '{' && s[strlen(s)-1] == '}' ) return SCE_NSIS_VARIABLE; } + // See if the variable is a user defined variable + if( s[0] == '$' && bUserVars ) + { + bool bHasSimpleNsisChars = true; + for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) + { + if( !isNsisChar( s[j] ) ) + { + bHasSimpleNsisChars = false; + break; + } + } + + if( bHasSimpleNsisChars ) + return SCE_NSIS_VARIABLE; + } + + // To check for numbers + if( isNsisNumber( s[0] ) ) + { + bool bHasSimpleNsisNumber = true; + for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) + { + if( s[j] == '\0' || s[j] == '\r' || s[j] == '\n' ) + break; + + if( !isNsisNumber( s[j] ) ) + { + bHasSimpleNsisNumber = false; + break; + } + } + + if( bHasSimpleNsisNumber ) + return SCE_NSIS_NUMBER; + } + return SCE_NSIS_DEFAULT; } @@ -102,7 +216,8 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k styler.StartSegment( startPos ); char cCurrChar; - bool bVarInString = true; + bool bVarInString = false; + bool bClassicVarInString = false; unsigned int i; for( i = startPos; i < nLengthDoc; i++ ) @@ -110,8 +225,6 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k cCurrChar = styler.SafeGetCharAt( i ); char cNextChar = styler.SafeGetCharAt( i+1, EOF ); - - switch(state) { case SCE_NSIS_DEFAULT: @@ -131,6 +244,7 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k styler.ColourTo(i-1, state ); state = SCE_NSIS_STRINGDQ; bVarInString = false; + bClassicVarInString = false; break; } if( cCurrChar == '\'' ) @@ -138,6 +252,7 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k styler.ColourTo(i-1, state ); state = SCE_NSIS_STRINGRQ; bVarInString = false; + bClassicVarInString = false; break; } if( cCurrChar == '`' ) @@ -145,14 +260,20 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k styler.ColourTo(i-1, state ); state = SCE_NSIS_STRINGLQ; bVarInString = false; + bClassicVarInString = false; break; } // NSIS KeyWord,Function, Variable, UserDefined: - if( cCurrChar == '$' || iswordchar(cCurrChar) || cCurrChar == '!' ) + if( cCurrChar == '$' || isNsisChar(cCurrChar) || cCurrChar == '!' ) { styler.ColourTo(i-1,state); state = SCE_NSIS_FUNCTION; + + // If it is a number, we must check and set style here first... + if( isNsisNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) ) + styler.ColourTo( i, SCE_NSIS_NUMBER); + break; } break; @@ -187,35 +308,45 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k case SCE_NSIS_FUNCTION: // NSIS KeyWord: - if( (iswordchar(cCurrChar) && !iswordchar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) + if( cCurrChar == '$' ) + state = SCE_NSIS_DEFAULT; + else if( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) ) + state = SCE_NSIS_DEFAULT; + else if( (isNsisChar(cCurrChar) && !isNsisChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) { state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler); styler.ColourTo( i, state); - state = SCE_NSIS_DEFAULT; // Everything after goes back to the default state + state = SCE_NSIS_DEFAULT; } - else if( !iswordchar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) + else if( !isNsisChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) { + if( classifyWordNsis( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_NSIS_NUMBER ) + styler.ColourTo( i-1, SCE_NSIS_NUMBER ); + state = SCE_NSIS_DEFAULT; - if( cCurrChar == '"' ) // Next + if( cCurrChar == '"' ) { state = SCE_NSIS_STRINGDQ; bVarInString = false; + bClassicVarInString = false; } - if( cCurrChar == '`' ) + else if( cCurrChar == '`' ) { state = SCE_NSIS_STRINGLQ; bVarInString = false; + bClassicVarInString = false; } - if( cCurrChar == '\'' ) + else if( cCurrChar == '\'' ) { state = SCE_NSIS_STRINGRQ; bVarInString = false; + bClassicVarInString = false; } - if( cCurrChar == '#' || cCurrChar == ';' ) + else if( cCurrChar == '#' || cCurrChar == ';' ) + { state = SCE_NSIS_COMMENT; - - styler.ColourTo( i, state); + } } break; } @@ -226,25 +357,58 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k } else if( state == SCE_NSIS_STRINGDQ || state == SCE_NSIS_STRINGLQ || state == SCE_NSIS_STRINGRQ ) { - // Check for var in String.. - if( bVarInString && (iswordchar(cCurrChar) || cCurrChar == '}') ) // || cCurrChar == '{' ) ) - { - int nWordState = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler); + bool bIngoreNextDollarSign = false; + bool bUserVars = false; + if( styler.GetPropertyInt("nsis.uservars") == 1 ) + bUserVars = true; + + if( bVarInString && cCurrChar == '$' ) + { + bVarInString = false; + bIngoreNextDollarSign = true; + } + else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) ) + { + bVarInString = false; + bIngoreNextDollarSign = true; + } + + // Covers "$INSTDIR and user vars like $MYVAR" + else if( bVarInString && !isNsisChar(cNextChar) ) + { + int nWordState = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler); if( nWordState == SCE_NSIS_VARIABLE ) - { styler.ColourTo( i, SCE_NSIS_STRINGVAR); - bVarInString = false; - } - } - if( cCurrChar == '$' ) + else if( bUserVars ) + styler.ColourTo( i, SCE_NSIS_STRINGVAR); + bVarInString = false; + } + // Covers "${TEST}..." + else if( bClassicVarInString && cNextChar == '}' ) + { + styler.ColourTo( i, SCE_NSIS_STRINGVAR); + bClassicVarInString = false; + } + + // Start of var in string + if( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) { styler.ColourTo( i-1, state); - bVarInString = true; + bClassicVarInString = true; + bVarInString = false; } + else if( !bIngoreNextDollarSign && cCurrChar == '$' ) + { + styler.ColourTo( i-1, state); + bVarInString = true; + bClassicVarInString = false; + } } } -} + if( state == SCE_NSIS_COMMENT ) + styler.ColourTo(i,state); +} static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { @@ -252,87 +416,57 @@ static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Ac if( styler.GetPropertyInt("fold") == 0 ) return; - unsigned int endPos = startPos + length; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; + int lineCurrent = styler.GetLine(startPos); + unsigned int safeStartPos = styler.LineStart( lineCurrent ); + + bool bArg1 = true; + int nWordStart = -1; + + int levelCurrent = SC_FOLDLEVELBASE; if (lineCurrent > 0) levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style; - for (unsigned int i = startPos; i < endPos; i++) + for (unsigned int i = safeStartPos; i < startPos + length; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - // Functions Start: Function, Section, SubSection - // Functions End: FunctionEnd, SectionEnd, SubSectionEnd - // Label Start: !ifdef, !ifndef - // Label End: !endif - - if( style == SCE_NSIS_FUNCTION ) - { - if( styler.Match(i, "FunctionEnd") ) - levelNext--; - else if( styler.Match(i, "Function") ) - levelNext++; - } - else if( style == SCE_NSIS_SECTIONDEF ) - { - if( styler.Match(i, "SectionEnd") ) - levelNext--; - else if( styler.Match(i, "Section") ) - levelNext++; - } - else if( style == SCE_NSIS_SUBSECTIONDEF ) - { - if( styler.Match(i, "SubSectionEnd") ) - levelNext--; - else if( styler.Match(i, "SubSection") ) - levelNext++; - } - else if( style == SCE_NSIS_IFDEFINEDEF ) - { - if( styler.Match(i, "!endif") ) - levelNext--; - else if( styler.Match(i, "!ifdef") || styler.Match(i, "!ifndef")) - levelNext++; - } - else if( style == SCE_NSIS_MACRODEF ) - { - if( styler.Match(i, "!macroend") ) - levelNext--; - else if( styler.Match(i, "!macro") ) - levelNext++; - } - - if( atEOL ) - { - int levelUse = levelCurrent; + char chCurr = styler.SafeGetCharAt(i); + + if( bArg1 ) //&& chCurr != '\n' ) + { + if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') ) + nWordStart = i; + else if( !isNsisLetter(chCurr) && nWordStart > -1 ) + { + int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler ); + if( newLevel != levelNext ) + levelNext = newLevel; + bArg1 = false; + } + } + + if( chCurr == '\n' ) + { + // If we are on a new line... + int levelUse = levelCurrent; int lev = levelUse | levelNext << 16; if (levelUse < levelNext) lev |= SC_FOLDLEVELHEADERFLAG; if (lev != styler.LevelAt(lineCurrent)) - { styler.SetLevel(lineCurrent, lev); - } + lineCurrent++; levelCurrent = levelNext; - } - } + bArg1 = true; // New line, lets look at first argument again + nWordStart = -1; + } + } int levelUse = levelCurrent; int lev = levelUse | levelNext << 16; if (levelUse < levelNext) lev |= SC_FOLDLEVELHEADERFLAG; if (lev != styler.LevelAt(lineCurrent)) - { styler.SetLevel(lineCurrent, lev); - } } static const char * const nsisWordLists[] = { |