123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- // 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, Sci_PositionU i) {
- return (styler[i] == '\n') ||
- ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
- }
- static void ColouriseMakeLine(
- char *lineBuffer,
- Sci_PositionU lengthLine,
- Sci_PositionU startLine,
- Sci_PositionU endPos,
- Accessor &styler) {
- Sci_PositionU i = 0;
- Sci_Position 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(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) {
- char lineBuffer[1024];
- styler.StartAt(startPos);
- styler.StartSegment(startPos);
- Sci_PositionU linePos = 0;
- Sci_PositionU startLine = startPos;
- for (Sci_PositionU 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);
|