diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-30 11:36:13 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-30 11:36:13 -0600 |
commit | 664e37abfe5c796c1279b8295fb030f126b0a7d8 (patch) | |
tree | 85f4e661e5c615f01ee1cdf51ca1250b96efe315 /src/LexNsis.cpp | |
download | tqscintilla-664e37abfe5c796c1279b8295fb030f126b0a7d8.tar.gz tqscintilla-664e37abfe5c796c1279b8295fb030f126b0a7d8.zip |
Initial import of qscintilla from 2007
Diffstat (limited to 'src/LexNsis.cpp')
-rwxr-xr-x | src/LexNsis.cpp | 647 |
1 files changed, 647 insertions, 0 deletions
diff --git a/src/LexNsis.cpp b/src/LexNsis.cpp new file mode 100755 index 0000000..6a7274e --- /dev/null +++ b/src/LexNsis.cpp @@ -0,0 +1,647 @@ +// Scintilla source code edit control +/** @file LexNsis.cxx + ** Lexer for NSIS + **/ +// Copyright 2003 - 2005 by Angelo Mandato <angelo [at] spaceblue [dot] com> +// Last Updated: 03/13/2005 +// The License.txt file describes the conditions under which this software may be distributed. +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +/* +// located in SciLexer.h +#define SCLEX_NSIS 43 + +#define SCE_NSIS_DEFAULT 0 +#define SCE_NSIS_COMMENT 1 +#define SCE_NSIS_STRINGDQ 2 +#define SCE_NSIS_STRINGLQ 3 +#define SCE_NSIS_STRINGRQ 4 +#define SCE_NSIS_FUNCTION 5 +#define SCE_NSIS_VARIABLE 6 +#define SCE_NSIS_LABEL 7 +#define SCE_NSIS_USERDEFINED 8 +#define SCE_NSIS_SECTIONDEF 9 +#define SCE_NSIS_SUBSECTIONDEF 10 +#define SCE_NSIS_IFDEFINEDEF 11 +#define SCE_NSIS_MACRODEF 12 +#define SCE_NSIS_STRINGVAR 13 +#define SCE_NSIS_NUMBER 14 +// ADDED for Scintilla v1.63 +#define SCE_NSIS_SECTIONGROUP 15 +#define SCE_NSIS_PAGEEX 16 +#define SCE_NSIS_FUNCTIONDEF 17 +#define SCE_NSIS_COMMENTBOX 18 +*/ + +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 bool NsisNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler) +{ + int nNextLine = -1; + for( unsigned int i = start; i < end; i++ ) + { + char cNext = styler.SafeGetCharAt( i ); + if( cNext == '\n' ) + { + nNextLine = i+1; + break; + } + } + + if( nNextLine == -1 ) // We never foudn the next line... + return false; + + for( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ ) + { + char cNext = styler.SafeGetCharAt( firstChar ); + if( cNext == ' ' ) + continue; + if( cNext == '\t' ) + continue; + if( cNext == '!' ) + { + if( styler.Match(firstChar, "!else") ) + return true; + } + break; + } + + return false; +} + +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, bool bElse, bool foldUtilityCmd ) +{ + int style = styler.StyleAt(end); + + // If the word is too long, it is not what we are looking for + if( end - start > 20 ) + return foldlevel; + + if( foldUtilityCmd ) + { + // Check the style at this point, if it is not valid, then return zero + if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF && + style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_IFDEFINEDEF && + style != SCE_NSIS_MACRODEF && style != SCE_NSIS_SECTIONGROUP && + style != SCE_NSIS_PAGEEX ) + return foldlevel; + } + else + { + if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF && + style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_SECTIONGROUP && + style != SCE_NSIS_PAGEEX ) + return foldlevel; + } + + int newFoldlevel = foldlevel; + bool bIgnoreCase = false; + if( styler.GetPropertyInt("nsis.ignorecase") == 1 ) + bIgnoreCase = true; + + char s[20]; // The key word we are looking for has atmost 13 characters + for (unsigned int i = 0; i < end - start + 1 && i < 19; 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( bElse && NsisCmp(s, "!else", bIgnoreCase) == 0 ) + newFoldlevel++; + } + else + { + 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 ) + newFoldlevel++; + 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 ) + 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]; + WordList &Variables = *keywordLists[1]; + WordList &Lables = *keywordLists[2]; + WordList &UserDefined = *keywordLists[3]; + + for (unsigned int i = 0; i < end - start + 1 && i < 99; 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( NsisCmp(s, "!macro", bIgnoreCase ) == 0 || NsisCmp(s, "!macroend", bIgnoreCase) == 0 ) // Covers !micro and !microend + return SCE_NSIS_MACRODEF; + + if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!endif", bIgnoreCase) == 0 ) + return SCE_NSIS_IFDEFINEDEF; + + if( NsisCmp(s, "!else", bIgnoreCase ) == 0 ) // || NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!endif", bIgnoreCase) == 0 ) + return SCE_NSIS_IFDEFINEDEF; + + if( NsisCmp(s, "SectionGroup", bIgnoreCase) == 0 || NsisCmp(s, "SectionGroupEnd", bIgnoreCase) == 0 ) // Covers SectionGroup and SectionGroupEnd + return SCE_NSIS_SECTIONGROUP; + + if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase) == 0 ) // Covers Section and SectionEnd + return SCE_NSIS_SECTIONDEF; + + if( NsisCmp(s, "SubSection", bIgnoreCase) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd + return SCE_NSIS_SUBSECTIONDEF; + + if( NsisCmp(s, "PageEx", bIgnoreCase) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase) == 0 ) // Covers PageEx and PageExEnd + return SCE_NSIS_PAGEEX; + + if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers Function and FunctionEnd + return SCE_NSIS_FUNCTIONDEF; + + if ( Functions.InList(s) ) + return SCE_NSIS_FUNCTION; + + if ( Variables.InList(s) ) + return SCE_NSIS_VARIABLE; + + if ( Lables.InList(s) ) + return SCE_NSIS_LABEL; + + if( UserDefined.InList(s) ) + return SCE_NSIS_USERDEFINED; + + 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( !isNsisNumber( s[j] ) ) + { + bHasSimpleNsisNumber = false; + break; + } + } + + if( bHasSimpleNsisNumber ) + return SCE_NSIS_NUMBER; + } + + return SCE_NSIS_DEFAULT; +} + +static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) +{ + int state = SCE_NSIS_DEFAULT; + if( startPos > 0 ) + state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox + + styler.StartAt( startPos ); + styler.GetLine( startPos ); + + unsigned int nLengthDoc = startPos + length; + styler.StartSegment( startPos ); + + char cCurrChar; + bool bVarInString = false; + bool bClassicVarInString = false; + + unsigned int i; + for( i = startPos; i < nLengthDoc; i++ ) + { + cCurrChar = styler.SafeGetCharAt( i ); + char cNextChar = styler.SafeGetCharAt(i+1); + + switch(state) + { + case SCE_NSIS_DEFAULT: + if( cCurrChar == ';' || cCurrChar == '#' ) // we have a comment line + { + styler.ColourTo(i-1, state ); + state = SCE_NSIS_COMMENT; + break; + } + if( cCurrChar == '"' ) + { + styler.ColourTo(i-1, state ); + state = SCE_NSIS_STRINGDQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + if( cCurrChar == '\'' ) + { + styler.ColourTo(i-1, state ); + state = SCE_NSIS_STRINGRQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + if( cCurrChar == '`' ) + { + styler.ColourTo(i-1, state ); + state = SCE_NSIS_STRINGLQ; + bVarInString = false; + bClassicVarInString = false; + break; + } + + // NSIS KeyWord,Function, Variable, UserDefined: + 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; + } + + if( cCurrChar == '/' && cNextChar == '*' ) + { + styler.ColourTo(i-1,state); + state = SCE_NSIS_COMMENTBOX; + break; + } + + break; + case SCE_NSIS_COMMENT: + if( cNextChar == '\n' || cNextChar == '\r' ) + { + // Special case: + if( cCurrChar == '\\' ) + { + styler.ColourTo(i-2,state); + styler.ColourTo(i,SCE_NSIS_DEFAULT); + } + else + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + } + } + break; + case SCE_NSIS_STRINGDQ: + case SCE_NSIS_STRINGLQ: + case SCE_NSIS_STRINGRQ: + + if( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' ) + break; // Ignore the next character, even if it is a quote of some sort + + if( cCurrChar == '"' && state == SCE_NSIS_STRINGDQ ) + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + break; + } + + if( cCurrChar == '`' && state == SCE_NSIS_STRINGLQ ) + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + break; + } + + if( cCurrChar == '\'' && state == SCE_NSIS_STRINGRQ ) + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + break; + } + + if( cNextChar == '\r' || cNextChar == '\n' ) + { + int nCurLine = styler.GetLine(i+1); + int nBack = i; + // We need to check if the previous line has a \ in it... + bool bNextLine = false; + + while( nBack > 0 ) + { + if( styler.GetLine(nBack) != nCurLine ) + break; + + char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here + + if( cTemp == '\\' ) + { + bNextLine = true; + break; + } + if( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' ) + break; + + nBack--; + } + + if( bNextLine ) + { + styler.ColourTo(i+1,state); + } + if( bNextLine == false ) + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + } + } + break; + + case SCE_NSIS_FUNCTION: + + // NSIS KeyWord: + 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; + } + 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 == '"' ) + { + state = SCE_NSIS_STRINGDQ; + bVarInString = false; + bClassicVarInString = false; + } + else if( cCurrChar == '`' ) + { + state = SCE_NSIS_STRINGLQ; + bVarInString = false; + bClassicVarInString = false; + } + else if( cCurrChar == '\'' ) + { + state = SCE_NSIS_STRINGRQ; + bVarInString = false; + bClassicVarInString = false; + } + else if( cCurrChar == '#' || cCurrChar == ';' ) + { + state = SCE_NSIS_COMMENT; + } + } + break; + case SCE_NSIS_COMMENTBOX: + + if( styler.SafeGetCharAt(i-1) == '*' && cCurrChar == '/' ) + { + styler.ColourTo(i,state); + state = SCE_NSIS_DEFAULT; + } + break; + } + + if( state == SCE_NSIS_COMMENT || state == SCE_NSIS_COMMENTBOX ) + { + styler.ColourTo(i,state); + } + else if( state == SCE_NSIS_STRINGDQ || state == SCE_NSIS_STRINGLQ || state == SCE_NSIS_STRINGRQ ) + { + 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' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) + { + styler.ColourTo( i+1, SCE_NSIS_STRINGVAR); + bVarInString = false; + bIngoreNextDollarSign = false; + } + + // 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); + else if( bUserVars ) + styler.ColourTo( i, SCE_NSIS_STRINGVAR); + bVarInString = false; + } + // Covers "${TEST}..." + else if( bClassicVarInString && cNextChar == '}' ) + { + styler.ColourTo( i+1, SCE_NSIS_STRINGVAR); + bClassicVarInString = false; + } + + // Start of var in string + if( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) + { + styler.ColourTo( i-1, state); + bClassicVarInString = true; + bVarInString = false; + } + else if( !bIngoreNextDollarSign && cCurrChar == '$' ) + { + styler.ColourTo( i-1, state); + bVarInString = true; + bClassicVarInString = false; + } + } + } + + // Colourise remaining document + styler.ColourTo(nLengthDoc-1,state); +} + +static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + // No folding enabled, no reason to continue... + if( styler.GetPropertyInt("fold") == 0 ) + return; + + bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1; + bool foldUtilityCmd = styler.GetPropertyInt("nsis.foldutilcmd", 1) == 1; + bool blockComment = false; + + 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; + int style = styler.StyleAt(safeStartPos); + if( style == SCE_NSIS_COMMENTBOX ) + { + if( styler.SafeGetCharAt(safeStartPos) == '/' && styler.SafeGetCharAt(safeStartPos+1) == '*' ) + levelNext++; + blockComment = true; + } + + for (unsigned int i = safeStartPos; i < startPos + length; i++) + { + char chCurr = styler.SafeGetCharAt(i); + style = styler.StyleAt(i); + if( blockComment && style != SCE_NSIS_COMMENTBOX ) + { + levelNext--; + blockComment = false; + } + else if( !blockComment && style == SCE_NSIS_COMMENTBOX ) + { + levelNext++; + blockComment = true; + } + + if( bArg1 && !blockComment) + { + if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') ) + { + nWordStart = i; + } + else if( isNsisLetter(chCurr) == false && nWordStart > -1 ) + { + int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler, foldAtElse, foldUtilityCmd ); + + if( newLevel == levelNext ) + { + if( foldAtElse && foldUtilityCmd ) + { + if( NsisNextLineHasElse(i, startPos + length, styler) ) + levelNext--; + } + } + else + levelNext = newLevel; + bArg1 = false; + } + } + + if( chCurr == '\n' ) + { + if( bArg1 && foldAtElse && foldUtilityCmd && !blockComment ) + { + if( NsisNextLineHasElse(i, startPos + length, styler) ) + levelNext--; + } + + // 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[] = { + "Functions", + "Variables", + "Lables", + "UserDefined", + 0, }; + + +LexerModule lmNsis(SCLEX_NSIS, ColouriseNsisDoc, "nsis", FoldNsisDoc, nsisWordLists); + |