1 // Scintilla source code edit control
3 ** Lexer for make files.
5 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
16 #include "Scintilla.h"
20 #include "LexAccessor.h"
22 #include "StyleContext.h"
23 #include "CharacterSet.h"
24 #include "LexerModule.h"
27 using namespace Scintilla
;
30 static inline bool AtEOL(Accessor
&styler
, Sci_PositionU i
) {
31 return (styler
[i
] == '\n') ||
32 ((styler
[i
] == '\r') && (styler
.SafeGetCharAt(i
+ 1) != '\n'));
35 static void ColouriseMakeLine(
37 Sci_PositionU lengthLine
,
38 Sci_PositionU startLine
,
43 Sci_Position lastNonSpace
= -1;
44 unsigned int state
= SCE_MAKE_DEFAULT
;
45 bool bSpecial
= false;
47 // check for a tab character in column 0 indicating a command
48 bool bCommand
= false;
49 if ((lengthLine
> 0) && (lineBuffer
[0] == '\t'))
52 // Skip initial spaces
53 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) {
57 if (lineBuffer
[i
] == '#') { // Comment
58 styler
.ColourTo(endPos
, SCE_MAKE_COMMENT
);
61 if (lineBuffer
[i
] == '!') { // Special directive
62 styler
.ColourTo(endPos
, SCE_MAKE_PREPROCESSOR
);
67 while (i
< lengthLine
) {
68 if (((i
+ 1) < lengthLine
) && (lineBuffer
[i
] == '$' && lineBuffer
[i
+ 1] == '(')) {
69 styler
.ColourTo(startLine
+ i
- 1, state
);
70 state
= SCE_MAKE_IDENTIFIER
;
72 } else if (state
== SCE_MAKE_IDENTIFIER
&& lineBuffer
[i
] == ')') {
73 if (--varCount
== 0) {
74 styler
.ColourTo(startLine
+ i
, state
);
75 state
= SCE_MAKE_DEFAULT
;
79 // skip identifier and target styling if this is a command line
80 if (!bSpecial
&& !bCommand
) {
81 if (lineBuffer
[i
] == ':') {
82 if (((i
+ 1) < lengthLine
) && (lineBuffer
[i
+ 1] == '=')) {
83 // it's a ':=', so style as an identifier
84 if (lastNonSpace
>= 0)
85 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
86 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
87 styler
.ColourTo(startLine
+ i
+ 1, SCE_MAKE_OPERATOR
);
89 // We should check that no colouring was made since the beginning of the line,
90 // to avoid colouring stuff like /OUT:file
91 if (lastNonSpace
>= 0)
92 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_TARGET
);
93 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
94 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
96 bSpecial
= true; // Only react to the first ':' of the line
97 state
= SCE_MAKE_DEFAULT
;
98 } else if (lineBuffer
[i
] == '=') {
99 if (lastNonSpace
>= 0)
100 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
101 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
102 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
103 bSpecial
= true; // Only react to the first '=' of the line
104 state
= SCE_MAKE_DEFAULT
;
107 if (!isspacechar(lineBuffer
[i
])) {
112 if (state
== SCE_MAKE_IDENTIFIER
) {
113 styler
.ColourTo(endPos
, SCE_MAKE_IDEOL
); // Error, variable reference not ended
115 styler
.ColourTo(endPos
, SCE_MAKE_DEFAULT
);
119 static void ColouriseMakeDoc(Sci_PositionU startPos
, Sci_Position length
, int, WordList
*[], Accessor
&styler
) {
120 char lineBuffer
[1024];
121 styler
.StartAt(startPos
);
122 styler
.StartSegment(startPos
);
123 Sci_PositionU linePos
= 0;
124 Sci_PositionU startLine
= startPos
;
125 for (Sci_PositionU i
= startPos
; i
< startPos
+ length
; i
++) {
126 lineBuffer
[linePos
++] = styler
[i
];
127 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
128 // End of line (or of line buffer) met, colourise it
129 lineBuffer
[linePos
] = '\0';
130 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, i
, styler
);
135 if (linePos
> 0) { // Last line does not have ending characters
136 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
140 static const char *const emptyWordListDesc
[] = {
144 LexerModule
lmMake(SCLEX_MAKEFILE
, ColouriseMakeDoc
, "makefile", 0, emptyWordListDesc
);