diff options
Diffstat (limited to 'lexers/LexMake.cxx')
-rw-r--r-- | lexers/LexMake.cxx | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/lexers/LexMake.cxx b/lexers/LexMake.cxx new file mode 100644 index 000000000..3ab172682 --- /dev/null +++ b/lexers/LexMake.cxx @@ -0,0 +1,144 @@ +// Scintilla source code edit control +/** @file LexMake.cxx + ** Lexer for make files. + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool AtEOL(Accessor &styler, unsigned int i) { + return (styler[i] == '\n') || + ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +static void ColouriseMakeLine( + char *lineBuffer, + unsigned int lengthLine, + unsigned int startLine, + unsigned int endPos, + Accessor &styler) { + + unsigned int i = 0; + int lastNonSpace = -1; + unsigned int state = SCE_MAKE_DEFAULT; + bool bSpecial = false; + + // check for a tab character in column 0 indicating a command + bool bCommand = false; + if ((lengthLine > 0) && (lineBuffer[0] == '\t')) + bCommand = true; + + // Skip initial spaces + while ((i < lengthLine) && isspacechar(lineBuffer[i])) { + i++; + } + if (i < lengthLine) { + if (lineBuffer[i] == '#') { // Comment + styler.ColourTo(endPos, SCE_MAKE_COMMENT); + return; + } + if (lineBuffer[i] == '!') { // Special directive + styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR); + return; + } + } + int varCount = 0; + while (i < lengthLine) { + if (((i + 1) < lengthLine) && (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(')) { + styler.ColourTo(startLine + i - 1, state); + state = SCE_MAKE_IDENTIFIER; + varCount++; + } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') { + if (--varCount == 0) { + styler.ColourTo(startLine + i, state); + state = SCE_MAKE_DEFAULT; + } + } + + // skip identifier and target styling if this is a command line + if (!bSpecial && !bCommand) { + if (lineBuffer[i] == ':') { + if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) { + // it's a ':=', so style as an identifier + if (lastNonSpace >= 0) + styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); + styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); + styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR); + } else { + // We should check that no colouring was made since the beginning of the line, + // to avoid colouring stuff like /OUT:file + if (lastNonSpace >= 0) + styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET); + styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); + styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); + } + bSpecial = true; // Only react to the first ':' of the line + state = SCE_MAKE_DEFAULT; + } else if (lineBuffer[i] == '=') { + if (lastNonSpace >= 0) + styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); + styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); + styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); + bSpecial = true; // Only react to the first '=' of the line + state = SCE_MAKE_DEFAULT; + } + } + if (!isspacechar(lineBuffer[i])) { + lastNonSpace = i; + } + i++; + } + if (state == SCE_MAKE_IDENTIFIER) { + styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended + } else { + styler.ColourTo(endPos, SCE_MAKE_DEFAULT); + } +} + +static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + char lineBuffer[1024]; + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + unsigned int startLine = startPos; + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler); + linePos = 0; + startLine = i + 1; + } + } + if (linePos > 0) { // Last line does not have ending characters + ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler); + } +} + +static const char *const emptyWordListDesc[] = { + 0 +}; + +LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc); |