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"
26 using namespace Scintilla
;
28 static inline bool AtEOL(Accessor
&styler
, Sci_PositionU i
) {
29 return (styler
[i
] == '\n') ||
30 ((styler
[i
] == '\r') && (styler
.SafeGetCharAt(i
+ 1) != '\n'));
33 static void ColouriseMakeLine(
35 Sci_PositionU lengthLine
,
36 Sci_PositionU startLine
,
41 Sci_Position lastNonSpace
= -1;
42 unsigned int state
= SCE_MAKE_DEFAULT
;
43 bool bSpecial
= false;
45 // check for a tab character in column 0 indicating a command
46 bool bCommand
= false;
47 if ((lengthLine
> 0) && (lineBuffer
[0] == '\t'))
50 // Skip initial spaces
51 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) {
55 if (lineBuffer
[i
] == '#') { // Comment
56 styler
.ColourTo(endPos
, SCE_MAKE_COMMENT
);
59 if (lineBuffer
[i
] == '!') { // Special directive
60 styler
.ColourTo(endPos
, SCE_MAKE_PREPROCESSOR
);
65 while (i
< lengthLine
) {
66 if (((i
+ 1) < lengthLine
) && (lineBuffer
[i
] == '$' && lineBuffer
[i
+ 1] == '(')) {
67 styler
.ColourTo(startLine
+ i
- 1, state
);
68 state
= SCE_MAKE_IDENTIFIER
;
70 } else if (state
== SCE_MAKE_IDENTIFIER
&& lineBuffer
[i
] == ')') {
71 if (--varCount
== 0) {
72 styler
.ColourTo(startLine
+ i
, state
);
73 state
= SCE_MAKE_DEFAULT
;
77 // skip identifier and target styling if this is a command line
78 if (!bSpecial
&& !bCommand
) {
79 if (lineBuffer
[i
] == ':') {
80 if (((i
+ 1) < lengthLine
) && (lineBuffer
[i
+ 1] == '=')) {
81 // it's a ':=', so style as an identifier
82 if (lastNonSpace
>= 0)
83 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
84 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
85 styler
.ColourTo(startLine
+ i
+ 1, SCE_MAKE_OPERATOR
);
87 // We should check that no colouring was made since the beginning of the line,
88 // to avoid colouring stuff like /OUT:file
89 if (lastNonSpace
>= 0)
90 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_TARGET
);
91 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
92 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
94 bSpecial
= true; // Only react to the first ':' of the line
95 state
= SCE_MAKE_DEFAULT
;
96 } else if (lineBuffer
[i
] == '=') {
97 if (lastNonSpace
>= 0)
98 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
99 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
100 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
101 bSpecial
= true; // Only react to the first '=' of the line
102 state
= SCE_MAKE_DEFAULT
;
105 if (!isspacechar(lineBuffer
[i
])) {
110 if (state
== SCE_MAKE_IDENTIFIER
) {
111 styler
.ColourTo(endPos
, SCE_MAKE_IDEOL
); // Error, variable reference not ended
113 styler
.ColourTo(endPos
, SCE_MAKE_DEFAULT
);
117 static void ColouriseMakeDoc(Sci_PositionU startPos
, Sci_Position length
, int, WordList
*[], Accessor
&styler
) {
118 char lineBuffer
[1024];
119 styler
.StartAt(startPos
);
120 styler
.StartSegment(startPos
);
121 Sci_PositionU linePos
= 0;
122 Sci_PositionU startLine
= startPos
;
123 for (Sci_PositionU i
= startPos
; i
< startPos
+ length
; i
++) {
124 lineBuffer
[linePos
++] = styler
[i
];
125 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
126 // End of line (or of line buffer) met, colourise it
127 lineBuffer
[linePos
] = '\0';
128 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, i
, styler
);
133 if (linePos
> 0) { // Last line does not have ending characters
134 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
138 static const char *const emptyWordListDesc
[] = {
142 LexerModule
lmMake(SCLEX_MAKEFILE
, ColouriseMakeDoc
, "makefile", 0, emptyWordListDesc
);