]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexOthers.cxx
babb3a0d3771da2336bbc61dc70633f21ae11815
1 // Scintilla source code edit control
2 /** @file LexOthers.cxx
3 ** Lexers for batch files, diff results, properties files, make files and error lists.
4 ** Also lexer for LaTeX documents.
6 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
20 #include "Scintilla.h"
23 static inline bool AtEOL(Accessor
&styler
, unsigned int i
) {
24 return (styler
[i
] == '\n') ||
25 ((styler
[i
] == '\r') && (styler
.SafeGetCharAt(i
+ 1) != '\n'));
28 static void ColouriseBatchLine(
30 unsigned int lengthLine
,
31 unsigned int startLine
,
37 unsigned int state
= SCE_BAT_DEFAULT
;
39 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) { // Skip initial spaces
42 if (lineBuffer
[i
] == '@') { // Hide command (ECHO OFF)
43 styler
.ColourTo(startLine
+ i
, SCE_BAT_HIDE
);
45 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) { // Skip next spaces
49 if (lineBuffer
[i
] == ':') {
51 if (lineBuffer
[i
+ 1] == ':') {
52 // :: is a fake label, similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
53 styler
.ColourTo(endPos
, SCE_BAT_COMMENT
);
54 } else { // Real label
55 styler
.ColourTo(endPos
, SCE_BAT_LABEL
);
58 // Check if initial word is a keyword
60 unsigned int wbl
= 0, offset
= i
;
61 // Copy word in buffer
62 for (; offset
< lengthLine
&& wbl
< 20 &&
63 !isspacechar(lineBuffer
[offset
]); wbl
++, offset
++) {
64 wordBuffer
[wbl
] = static_cast<char>(tolower(lineBuffer
[offset
]));
66 wordBuffer
[wbl
] = '\0';
67 // Check if it is a comment
68 if (CompareCaseInsensitive(wordBuffer
, "rem") == 0) {
69 styler
.ColourTo(endPos
, SCE_BAT_COMMENT
);
72 // Check if it is in the list
73 if (keywords
.InList(wordBuffer
)) {
74 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_WORD
); // Regular keyword
76 // Search end of word (can be a long path)
77 while (offset
< lengthLine
&&
78 !isspacechar(lineBuffer
[offset
])) {
81 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
); // External command / program
83 // Remainder of the line: colourise the variables.
85 while (offset
< lengthLine
) {
86 if (state
== SCE_BAT_DEFAULT
&& lineBuffer
[offset
] == '%') {
87 styler
.ColourTo(startLine
+ offset
- 1, state
);
88 if (isdigit(lineBuffer
[offset
+ 1])) {
89 styler
.ColourTo(startLine
+ offset
+ 1, SCE_BAT_IDENTIFIER
);
91 } else if (lineBuffer
[offset
+ 1] == '%' &&
92 !isspacechar(lineBuffer
[offset
+ 2])) {
93 // Should be safe, as there is CRLF at the end of the line...
94 styler
.ColourTo(startLine
+ offset
+ 2, SCE_BAT_IDENTIFIER
);
97 state
= SCE_BAT_IDENTIFIER
;
99 } else if (state
== SCE_BAT_IDENTIFIER
&& lineBuffer
[offset
] == '%') {
100 styler
.ColourTo(startLine
+ offset
, state
);
101 state
= SCE_BAT_DEFAULT
;
102 } else if (state
== SCE_BAT_DEFAULT
&&
103 (lineBuffer
[offset
] == '*' ||
104 lineBuffer
[offset
] == '?' ||
105 lineBuffer
[offset
] == '=' ||
106 lineBuffer
[offset
] == '<' ||
107 lineBuffer
[offset
] == '>' ||
108 lineBuffer
[offset
] == '|')) {
109 styler
.ColourTo(startLine
+ offset
- 1, state
);
110 styler
.ColourTo(startLine
+ offset
, SCE_BAT_OPERATOR
);
114 // if (endPos > startLine + offset - 1) {
115 styler
.ColourTo(endPos
, SCE_BAT_DEFAULT
); // Remainder of line, currently not lexed
120 // ToDo: (not necessarily at beginning of line) GOTO, [IF] NOT, ERRORLEVEL
121 // IF [NO] (test) (command) -- test is EXIST (filename) | (string1)==(string2) | ERRORLEVEL (number)
122 // FOR %%(variable) IN (set) DO (command) -- variable is [a-zA-Z] -- eg for %%X in (*.txt) do type %%X
123 // ToDo: %n (parameters), %EnvironmentVariable% colourising
124 // ToDo: Colourise = > >> < | "
126 static void ColouriseBatchDoc(
127 unsigned int startPos
,
130 WordList
*keywordlists
[],
133 char lineBuffer
[1024];
134 WordList
&keywords
= *keywordlists
[0];
136 styler
.StartAt(startPos
);
137 styler
.StartSegment(startPos
);
138 unsigned int linePos
= 0;
139 unsigned int startLine
= startPos
;
140 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
141 lineBuffer
[linePos
++] = styler
[i
];
142 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
143 // End of line (or of line buffer) met, colourise it
144 lineBuffer
[linePos
] = '\0';
145 ColouriseBatchLine(lineBuffer
, linePos
, startLine
, i
, keywords
, styler
);
150 if (linePos
> 0) { // Last line does not have ending characters
151 ColouriseBatchLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1,
156 static void ColouriseDiffLine(char *lineBuffer
, int endLine
, Accessor
&styler
) {
157 // It is needed to remember the current state to recognize starting
158 // comment lines before the first "diff " or "--- ". If a real
159 // difference starts then each line starting with ' ' is a whitespace
160 // otherwise it is considered a comment (Only in..., Binary file...)
161 if (0 == strncmp(lineBuffer
, "diff ", 3)) {
162 styler
.ColourTo(endLine
, SCE_DIFF_COMMAND
);
163 } else if (0 == strncmp(lineBuffer
, "--- ", 3)) {
164 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
165 } else if (0 == strncmp(lineBuffer
, "+++ ", 3)) {
166 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
167 } else if (0 == strncmp(lineBuffer
, "***", 3)) {
168 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
169 } else if (lineBuffer
[0] == '@') {
170 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
171 } else if (lineBuffer
[0] == '-') {
172 styler
.ColourTo(endLine
, SCE_DIFF_DELETED
);
173 } else if (lineBuffer
[0] == '+') {
174 styler
.ColourTo(endLine
, SCE_DIFF_ADDED
);
175 } else if (lineBuffer
[0] != ' ') {
176 styler
.ColourTo(endLine
, SCE_DIFF_COMMENT
);
178 styler
.ColourTo(endLine
, SCE_DIFF_DEFAULT
);
182 static void ColouriseDiffDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
183 char lineBuffer
[1024];
184 styler
.StartAt(startPos
);
185 styler
.StartSegment(startPos
);
186 unsigned int linePos
= 0;
187 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
188 lineBuffer
[linePos
++] = styler
[i
];
189 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
190 // End of line (or of line buffer) met, colourise it
191 lineBuffer
[linePos
] = '\0';
192 ColouriseDiffLine(lineBuffer
, i
, styler
);
196 if (linePos
> 0) { // Last line does not have ending characters
197 ColouriseDiffLine(lineBuffer
, startPos
+ length
- 1, styler
);
201 static void ColourisePropsLine(
203 unsigned int lengthLine
,
204 unsigned int startLine
,
209 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) // Skip initial spaces
211 if (i
< lengthLine
) {
212 if (lineBuffer
[i
] == '#' || lineBuffer
[i
] == '!' || lineBuffer
[i
] == ';') {
213 styler
.ColourTo(endPos
, SCE_PROPS_COMMENT
);
214 } else if (lineBuffer
[i
] == '[') {
215 styler
.ColourTo(endPos
, SCE_PROPS_SECTION
);
216 } else if (lineBuffer
[i
] == '@') {
217 styler
.ColourTo(startLine
+ i
, SCE_PROPS_DEFVAL
);
218 if (lineBuffer
[++i
] == '=')
219 styler
.ColourTo(startLine
+ i
, SCE_PROPS_ASSIGNMENT
);
220 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
222 // Search for the '=' character
223 while ((i
< lengthLine
) && (lineBuffer
[i
] != '='))
225 if ((i
< lengthLine
) && (lineBuffer
[i
] == '=')) {
226 styler
.ColourTo(startLine
+ i
- 1, SCE_PROPS_DEFAULT
);
227 styler
.ColourTo(startLine
+ i
, 3);
228 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
230 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
234 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
238 static void ColourisePropsDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
239 char lineBuffer
[1024];
240 styler
.StartAt(startPos
);
241 styler
.StartSegment(startPos
);
242 unsigned int linePos
= 0;
243 unsigned int startLine
= startPos
;
244 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
245 lineBuffer
[linePos
++] = styler
[i
];
246 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
247 // End of line (or of line buffer) met, colourise it
248 lineBuffer
[linePos
] = '\0';
249 ColourisePropsLine(lineBuffer
, linePos
, startLine
, i
, styler
);
254 if (linePos
> 0) { // Last line does not have ending characters
255 ColourisePropsLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
259 static void ColouriseMakeLine(
261 unsigned int lengthLine
,
262 unsigned int startLine
,
267 unsigned int lastNonSpace
= 0;
268 unsigned int state
= SCE_MAKE_DEFAULT
;
269 bool bSpecial
= false;
270 // Skip initial spaces
271 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) {
274 if (lineBuffer
[i
] == '#') { // Comment
275 styler
.ColourTo(endPos
, SCE_MAKE_COMMENT
);
278 if (lineBuffer
[i
] == '!') { // Special directive
279 styler
.ColourTo(endPos
, SCE_MAKE_PREPROCESSOR
);
282 while (i
< lengthLine
) {
283 if (lineBuffer
[i
] == '$' && lineBuffer
[i
+ 1] == '(') {
284 styler
.ColourTo(startLine
+ i
- 1, state
);
285 state
= SCE_MAKE_IDENTIFIER
;
286 } else if (state
== SCE_MAKE_IDENTIFIER
&& lineBuffer
[i
] == ')') {
287 styler
.ColourTo(startLine
+ i
, state
);
288 state
= SCE_MAKE_DEFAULT
;
291 if (lineBuffer
[i
] == ':') {
292 // We should check that no colouring was made since the beginning of the line,
293 // to avoid colouring stuff like /OUT:file
294 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_TARGET
);
295 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
296 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
297 bSpecial
= true; // Only react to the first ':' of the line
298 state
= SCE_MAKE_DEFAULT
;
299 } else if (lineBuffer
[i
] == '=') {
300 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
301 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
302 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
303 bSpecial
= true; // Only react to the first '=' of the line
304 state
= SCE_MAKE_DEFAULT
;
307 if (!isspacechar(lineBuffer
[i
])) {
312 if (state
== SCE_MAKE_IDENTIFIER
) {
313 styler
.ColourTo(endPos
, SCE_MAKE_IDEOL
); // Error, variable reference not ended
315 styler
.ColourTo(endPos
, SCE_MAKE_DEFAULT
);
319 static void ColouriseMakeDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
320 char lineBuffer
[1024];
321 styler
.StartAt(startPos
);
322 styler
.StartSegment(startPos
);
323 unsigned int linePos
= 0;
324 unsigned int startLine
= startPos
;
325 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
326 lineBuffer
[linePos
++] = styler
[i
];
327 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
328 // End of line (or of line buffer) met, colourise it
329 lineBuffer
[linePos
] = '\0';
330 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, i
, styler
);
335 if (linePos
> 0) { // Last line does not have ending characters
336 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
340 static void ColouriseErrorListLine(
342 unsigned int lengthLine
,
343 // unsigned int startLine,
346 if (lineBuffer
[0] == '>') {
347 // Command or return status
348 styler
.ColourTo(endPos
, SCE_ERR_CMD
);
349 } else if (lineBuffer
[0] == '<') {
350 // Diff removal, but not interested. Trapped to avoid hitting CTAG cases.
351 styler
.ColourTo(endPos
, SCE_ERR_DEFAULT
);
352 } else if (lineBuffer
[0] == '!') {
353 styler
.ColourTo(endPos
, SCE_ERR_DIFF_CHANGED
);
354 } else if (lineBuffer
[0] == '+') {
355 styler
.ColourTo(endPos
, SCE_ERR_DIFF_ADDITION
);
356 } else if (lineBuffer
[0] == '-' && lineBuffer
[1] == '-' && lineBuffer
[2] == '-') {
357 styler
.ColourTo(endPos
, SCE_ERR_DIFF_MESSAGE
);
358 } else if (lineBuffer
[0] == '-') {
359 styler
.ColourTo(endPos
, SCE_ERR_DIFF_DELETION
);
360 } else if (strstr(lineBuffer
, "File \"") && strstr(lineBuffer
, ", line ")) {
361 styler
.ColourTo(endPos
, SCE_ERR_PYTHON
);
362 } else if (0 == strncmp(lineBuffer
, "Error ", strlen("Error "))) {
363 // Borland error message
364 styler
.ColourTo(endPos
, SCE_ERR_BORLAND
);
365 } else if (0 == strncmp(lineBuffer
, "Warning ", strlen("Warning "))) {
366 // Borland warning message
367 styler
.ColourTo(endPos
, SCE_ERR_BORLAND
);
368 } else if (strstr(lineBuffer
, "at line " ) &&
369 (strstr(lineBuffer
, "at line " ) < (lineBuffer
+ lengthLine
)) &&
370 strstr(lineBuffer
, "file ") &&
371 (strstr(lineBuffer
, "file ") < (lineBuffer
+ lengthLine
))) {
373 styler
.ColourTo(endPos
, SCE_ERR_LUA
);
374 } else if (strstr(lineBuffer
, " at " ) &&
375 (strstr(lineBuffer
, " at " ) < (lineBuffer
+ lengthLine
)) &&
376 strstr(lineBuffer
, " line ") &&
377 (strstr(lineBuffer
, " line ") < (lineBuffer
+ lengthLine
))) {
378 // perl error message
379 styler
.ColourTo(endPos
, SCE_ERR_PERL
);
380 } else if ((memcmp(lineBuffer
, " at ", 6) == 0) &&
381 strstr(lineBuffer
, ":line ")) {
383 styler
.ColourTo(endPos
, SCE_ERR_NET
);
385 // Look for <filename>:<line>:message
386 // Look for <filename>(line)message
387 // Look for <filename>(line,pos)message
389 for (unsigned int i
= 0; i
< lengthLine
; i
++) {
390 if ((state
== 0) && (lineBuffer
[i
] == ':') && isdigit(lineBuffer
[i
+ 1])) {
392 } else if ((state
== 0) && (lineBuffer
[i
] == '(')) {
394 } else if ((state
== 0) && (lineBuffer
[i
] == '\t')) {
396 } else if ((state
== 1) && isdigit(lineBuffer
[i
])) {
398 } else if ((state
== 2) && (lineBuffer
[i
] == ':')) {
401 } else if ((state
== 2) && !isdigit(lineBuffer
[i
])) {
403 } else if ((state
== 10) && isdigit(lineBuffer
[i
])) {
405 } else if ((state
== 11) && (lineBuffer
[i
] == ',')) {
407 } else if ((state
== 11) && (lineBuffer
[i
] == ')')) {
409 } else if ((state
== 12) && (lineBuffer
[i
] == ':')) {
411 } else if ((state
== 14) && (lineBuffer
[i
] == ')')) {
414 } else if (((state
== 11) || (state
== 14)) && !((lineBuffer
[i
] == ' ') || isdigit(lineBuffer
[i
]))) {
416 } else if ((state
== 20) && (lineBuffer
[i
-1] == '\t') &&
417 ((lineBuffer
[i
] == '/' && lineBuffer
[i
+1] == '^') || isdigit(lineBuffer
[i
]))) {
420 } else if ((state
== 20) && ((lineBuffer
[i
] == '/') && (lineBuffer
[i
+1] == '^'))) {
422 } else if ((state
== 21) && ((lineBuffer
[i
] == '$') && (lineBuffer
[i
+1] == '/'))) {
428 styler
.ColourTo(endPos
, SCE_ERR_GCC
);
429 } else if ((state
== 13) || (state
== 14) || (state
== 15)) {
430 styler
.ColourTo(endPos
, SCE_ERR_MS
);
431 } else if (((state
== 22) || (state
== 24)) && (lineBuffer
[0] != '\t')) {
432 styler
.ColourTo(endPos
, SCE_ERR_CTAG
);
434 styler
.ColourTo(endPos
, SCE_ERR_DEFAULT
);
439 static void ColouriseErrorListDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
440 char lineBuffer
[1024];
441 styler
.StartAt(startPos
);
442 styler
.StartSegment(startPos
);
443 unsigned int linePos
= 0;
444 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
445 lineBuffer
[linePos
++] = styler
[i
];
446 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
447 // End of line (or of line buffer) met, colourise it
448 lineBuffer
[linePos
] = '\0';
449 ColouriseErrorListLine(lineBuffer
, linePos
, i
, styler
);
453 if (linePos
> 0) { // Last line does not have ending characters
454 ColouriseErrorListLine(lineBuffer
, linePos
, startPos
+ length
- 1, styler
);
458 static int isSpecial(char s
) {
459 return (s
== '\\') || (s
== ',') || (s
== ';') || (s
== '\'') || (s
== ' ') ||
460 (s
== '\"') || (s
== '`') || (s
== '^') || (s
== '~');
463 static int isTag(int start
, Accessor
&styler
) {
465 unsigned int i
= 0, e
= 1;
467 s
[i
] = styler
[start
+ i
];
469 e
= styler
[start
+ i
] != '{';
472 return (strcmp(s
, "begin") == 0) || (strcmp(s
, "end") == 0);
475 static void ColouriseLatexDoc(unsigned int startPos
, int length
, int initStyle
,
476 WordList
*[], Accessor
&styler
) {
478 styler
.StartAt(startPos
);
480 int state
= initStyle
;
481 char chNext
= styler
[startPos
];
482 styler
.StartSegment(startPos
);
483 int lengthDoc
= startPos
+ length
;
485 for (int i
= startPos
; i
< lengthDoc
; i
++) {
487 chNext
= styler
.SafeGetCharAt(i
+ 1);
489 if (styler
.IsLeadByte(ch
)) {
490 chNext
= styler
.SafeGetCharAt(i
+ 2);
498 styler
.ColourTo(i
- 1, state
);
499 if (isSpecial(styler
[i
+ 1])) {
500 styler
.ColourTo(i
+ 1, SCE_L_COMMAND
);
502 chNext
= styler
.SafeGetCharAt(i
+ 1);
504 if (isTag(i
+ 1, styler
))
507 state
= SCE_L_COMMAND
;
511 styler
.ColourTo(i
- 1, state
);
515 chNext
= styler
.SafeGetCharAt(i
+ 1);
519 styler
.ColourTo(i
- 1, state
);
520 state
= SCE_L_COMMENT
;
525 if (chNext
== '[' || chNext
== '{' || chNext
== '}' ||
526 chNext
== ' ' || chNext
== '\r' || chNext
== '\n') {
527 styler
.ColourTo(i
, state
);
528 state
= SCE_L_DEFAULT
;
530 chNext
= styler
.SafeGetCharAt(i
+ 1);
535 styler
.ColourTo(i
, state
);
536 state
= SCE_L_DEFAULT
;
543 chNext
= styler
.SafeGetCharAt(i
+ 1);
545 styler
.ColourTo(i
, state
);
546 state
= SCE_L_DEFAULT
;
550 if (ch
== '\r' || ch
== '\n') {
551 styler
.ColourTo(i
- 1, state
);
552 state
= SCE_L_DEFAULT
;
556 styler
.ColourTo(lengthDoc
, state
);
559 LexerModule
lmBatch(SCLEX_BATCH
, ColouriseBatchDoc
, "batch");
560 LexerModule
lmDiff(SCLEX_DIFF
, ColouriseDiffDoc
, "diff");
561 LexerModule
lmProps(SCLEX_PROPERTIES
, ColourisePropsDoc
, "props");
562 LexerModule
lmMake(SCLEX_MAKEFILE
, ColouriseMakeDoc
, "makefile");
563 LexerModule
lmErrorList(SCLEX_ERRORLIST
, ColouriseErrorListDoc
, "errorlist");
564 LexerModule
lmLatex(SCLEX_LATEX
, ColouriseLatexDoc
, "latex");