]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexOthers.cxx
1681ba5d4a6bd38c218d4ea4ad68cf1a90795d4b
[wxWidgets.git] / src / stc / scintilla / src / LexOthers.cxx
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.
5 **/
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.
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14
15 #include "Platform.h"
16
17 #include "PropSet.h"
18 #include "Accessor.h"
19 #include "KeyWords.h"
20 #include "Scintilla.h"
21 #include "SciLexer.h"
22
23 static bool Is0To9(char ch) {
24 return (ch >= '0') && (ch <= '9');
25 }
26
27 static bool Is1To9(char ch) {
28 return (ch >= '1') && (ch <= '9');
29 }
30
31 static inline bool AtEOL(Accessor &styler, unsigned int i) {
32 return (styler[i] == '\n') ||
33 ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
34 }
35
36 static void ColouriseBatchLine(
37 char *lineBuffer,
38 unsigned int lengthLine,
39 unsigned int startLine,
40 unsigned int endPos,
41 WordList &keywords,
42 Accessor &styler) {
43
44 unsigned int i = 0;
45 unsigned int state = SCE_BAT_DEFAULT;
46
47 while ((i < lengthLine) && isspacechar(lineBuffer[i])) { // Skip initial spaces
48 i++;
49 }
50 if (lineBuffer[i] == '@') { // Hide command (ECHO OFF)
51 styler.ColourTo(startLine + i, SCE_BAT_HIDE);
52 i++;
53 while ((i < lengthLine) && isspacechar(lineBuffer[i])) { // Skip next spaces
54 i++;
55 }
56 }
57 if (lineBuffer[i] == ':') {
58 // Label
59 if (lineBuffer[i + 1] == ':') {
60 // :: is a fake label, similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
61 styler.ColourTo(endPos, SCE_BAT_COMMENT);
62 } else { // Real label
63 styler.ColourTo(endPos, SCE_BAT_LABEL);
64 }
65 } else {
66 // Check if initial word is a keyword
67 char wordBuffer[21];
68 unsigned int wbl = 0, offset = i;
69 // Copy word in buffer
70 for (; offset < lengthLine && wbl < 20 &&
71 !isspacechar(lineBuffer[offset]); wbl++, offset++) {
72 wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset]));
73 }
74 wordBuffer[wbl] = '\0';
75 // Check if it is a comment
76 if (CompareCaseInsensitive(wordBuffer, "rem") == 0) {
77 styler.ColourTo(endPos, SCE_BAT_COMMENT);
78 return ;
79 }
80 // Check if it is in the list
81 if (keywords.InList(wordBuffer)) {
82 styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD); // Regular keyword
83 } else {
84 // Search end of word (can be a long path)
85 while (offset < lengthLine &&
86 !isspacechar(lineBuffer[offset])) {
87 offset++;
88 }
89 styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); // External command / program
90 }
91 // Remainder of the line: colourise the variables.
92
93 while (offset < lengthLine) {
94 if (state == SCE_BAT_DEFAULT && lineBuffer[offset] == '%') {
95 styler.ColourTo(startLine + offset - 1, state);
96 if (Is0To9(lineBuffer[offset + 1])) {
97 styler.ColourTo(startLine + offset + 1, SCE_BAT_IDENTIFIER);
98 offset += 2;
99 } else if (lineBuffer[offset + 1] == '%' &&
100 !isspacechar(lineBuffer[offset + 2])) {
101 // Should be safe, as there is CRLF at the end of the line...
102 styler.ColourTo(startLine + offset + 2, SCE_BAT_IDENTIFIER);
103 offset += 3;
104 } else {
105 state = SCE_BAT_IDENTIFIER;
106 }
107 } else if (state == SCE_BAT_IDENTIFIER && lineBuffer[offset] == '%') {
108 styler.ColourTo(startLine + offset, state);
109 state = SCE_BAT_DEFAULT;
110 } else if (state == SCE_BAT_DEFAULT &&
111 (lineBuffer[offset] == '*' ||
112 lineBuffer[offset] == '?' ||
113 lineBuffer[offset] == '=' ||
114 lineBuffer[offset] == '<' ||
115 lineBuffer[offset] == '>' ||
116 lineBuffer[offset] == '|')) {
117 styler.ColourTo(startLine + offset - 1, state);
118 styler.ColourTo(startLine + offset, SCE_BAT_OPERATOR);
119 }
120 offset++;
121 }
122 // if (endPos > startLine + offset - 1) {
123 styler.ColourTo(endPos, SCE_BAT_DEFAULT); // Remainder of line, currently not lexed
124 // }
125 }
126
127 }
128 // ToDo: (not necessarily at beginning of line) GOTO, [IF] NOT, ERRORLEVEL
129 // IF [NO] (test) (command) -- test is EXIST (filename) | (string1)==(string2) | ERRORLEVEL (number)
130 // FOR %%(variable) IN (set) DO (command) -- variable is [a-zA-Z] -- eg for %%X in (*.txt) do type %%X
131 // ToDo: %n (parameters), %EnvironmentVariable% colourising
132 // ToDo: Colourise = > >> < | "
133
134 static void ColouriseBatchDoc(
135 unsigned int startPos,
136 int length,
137 int /*initStyle*/,
138 WordList *keywordlists[],
139 Accessor &styler) {
140
141 char lineBuffer[1024];
142 WordList &keywords = *keywordlists[0];
143
144 styler.StartAt(startPos);
145 styler.StartSegment(startPos);
146 unsigned int linePos = 0;
147 unsigned int startLine = startPos;
148 for (unsigned int i = startPos; i < startPos + length; i++) {
149 lineBuffer[linePos++] = styler[i];
150 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
151 // End of line (or of line buffer) met, colourise it
152 lineBuffer[linePos] = '\0';
153 ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywords, styler);
154 linePos = 0;
155 startLine = i + 1;
156 }
157 }
158 if (linePos > 0) { // Last line does not have ending characters
159 ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1,
160 keywords, styler);
161 }
162 }
163
164 static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) {
165 // It is needed to remember the current state to recognize starting
166 // comment lines before the first "diff " or "--- ". If a real
167 // difference starts then each line starting with ' ' is a whitespace
168 // otherwise it is considered a comment (Only in..., Binary file...)
169 if (0 == strncmp(lineBuffer, "diff ", 5)) {
170 styler.ColourTo(endLine, SCE_DIFF_COMMAND);
171 } else if (0 == strncmp(lineBuffer, "--- ", 4)) {
172 // In a context diff, --- appears in both the header and the position markers
173 if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/'))
174 styler.ColourTo(endLine, SCE_DIFF_POSITION);
175 else
176 styler.ColourTo(endLine, SCE_DIFF_HEADER);
177 } else if (0 == strncmp(lineBuffer, "+++ ", 4)) {
178 // I don't know of any diff where "+++ " is a position marker, but for
179 // consistency, do the same as with "--- " and "*** ".
180 if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/'))
181 styler.ColourTo(endLine, SCE_DIFF_POSITION);
182 else
183 styler.ColourTo(endLine, SCE_DIFF_HEADER);
184 } else if (0 == strncmp(lineBuffer, "====", 4)) { // For p4's diff
185 styler.ColourTo(endLine, SCE_DIFF_HEADER);
186 } else if (0 == strncmp(lineBuffer, "***", 3)) {
187 // In a context diff, *** appears in both the header and the position markers.
188 // Also ******** is a chunk header, but here it's treated as part of the
189 // position marker since there is no separate style for a chunk header.
190 if (lineBuffer[3] == ' ' && atoi(lineBuffer+4) && !strchr(lineBuffer, '/'))
191 styler.ColourTo(endLine, SCE_DIFF_POSITION);
192 else if (lineBuffer[3] == '*')
193 styler.ColourTo(endLine, SCE_DIFF_POSITION);
194 else
195 styler.ColourTo(endLine, SCE_DIFF_HEADER);
196 } else if (0 == strncmp(lineBuffer, "? ", 2)) { // For difflib
197 styler.ColourTo(endLine, SCE_DIFF_HEADER);
198 } else if (lineBuffer[0] == '@') {
199 styler.ColourTo(endLine, SCE_DIFF_POSITION);
200 } else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') {
201 styler.ColourTo(endLine, SCE_DIFF_POSITION);
202 } else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') {
203 styler.ColourTo(endLine, SCE_DIFF_DELETED);
204 } else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') {
205 styler.ColourTo(endLine, SCE_DIFF_ADDED);
206 } else if (lineBuffer[0] != ' ') {
207 styler.ColourTo(endLine, SCE_DIFF_COMMENT);
208 } else {
209 styler.ColourTo(endLine, SCE_DIFF_DEFAULT);
210 }
211 }
212
213 static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
214 char lineBuffer[1024];
215 styler.StartAt(startPos);
216 styler.StartSegment(startPos);
217 unsigned int linePos = 0;
218 for (unsigned int i = startPos; i < startPos + length; i++) {
219 lineBuffer[linePos++] = styler[i];
220 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
221 // End of line (or of line buffer) met, colourise it
222 lineBuffer[linePos] = '\0';
223 ColouriseDiffLine(lineBuffer, i, styler);
224 linePos = 0;
225 }
226 }
227 if (linePos > 0) { // Last line does not have ending characters
228 ColouriseDiffLine(lineBuffer, startPos + length - 1, styler);
229 }
230 }
231
232 static void FoldDiffDoc(unsigned int startPos, int length, int, WordList*[], Accessor &styler) {
233 int curLine = styler.GetLine(startPos);
234 int prevLevel = SC_FOLDLEVELBASE;
235 if (curLine > 0)
236 prevLevel = styler.LevelAt(curLine-1);
237
238 int curLineStart = styler.LineStart(curLine);
239 do {
240 int nextLevel = prevLevel;
241 if (prevLevel & SC_FOLDLEVELHEADERFLAG)
242 nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1;
243
244 int lineType = styler.StyleAt(curLineStart);
245 if (lineType == SCE_DIFF_COMMAND)
246 nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG;
247 else if (lineType == SCE_DIFF_HEADER) {
248 nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG;
249 } else if (lineType == SCE_DIFF_POSITION)
250 nextLevel = (SC_FOLDLEVELBASE + 3) | SC_FOLDLEVELHEADERFLAG;
251
252 if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel))
253 styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG);
254
255 styler.SetLevel(curLine, nextLevel);
256 prevLevel = nextLevel;
257
258 curLineStart = styler.LineStart(++curLine);
259 } while (static_cast<int>(startPos) + length > curLineStart);
260 }
261
262
263 static void ColourisePropsLine(
264 char *lineBuffer,
265 unsigned int lengthLine,
266 unsigned int startLine,
267 unsigned int endPos,
268 Accessor &styler) {
269
270 unsigned int i = 0;
271 while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces
272 i++;
273 if (i < lengthLine) {
274 if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
275 styler.ColourTo(endPos, SCE_PROPS_COMMENT);
276 } else if (lineBuffer[i] == '[') {
277 styler.ColourTo(endPos, SCE_PROPS_SECTION);
278 } else if (lineBuffer[i] == '@') {
279 styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL);
280 if (lineBuffer[++i] == '=')
281 styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
282 styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
283 } else {
284 // Search for the '=' character
285 while ((i < lengthLine) && (lineBuffer[i] != '='))
286 i++;
287 if ((i < lengthLine) && (lineBuffer[i] == '=')) {
288 styler.ColourTo(startLine + i - 1, SCE_PROPS_DEFAULT);
289 styler.ColourTo(startLine + i, 3);
290 styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
291 } else {
292 styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
293 }
294 }
295 } else {
296 styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
297 }
298 }
299
300 static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
301 char lineBuffer[1024];
302 styler.StartAt(startPos);
303 styler.StartSegment(startPos);
304 unsigned int linePos = 0;
305 unsigned int startLine = startPos;
306 for (unsigned int i = startPos; i < startPos + length; i++) {
307 lineBuffer[linePos++] = styler[i];
308 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
309 // End of line (or of line buffer) met, colourise it
310 lineBuffer[linePos] = '\0';
311 ColourisePropsLine(lineBuffer, linePos, startLine, i, styler);
312 linePos = 0;
313 startLine = i + 1;
314 }
315 }
316 if (linePos > 0) { // Last line does not have ending characters
317 ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
318 }
319 }
320
321 // adaption by ksc, using the "} else {" trick of 1.53
322 // 030721
323 static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
324 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
325
326 unsigned int endPos = startPos + length;
327 int visibleChars = 0;
328 int lineCurrent = styler.GetLine(startPos);
329
330 char chNext = styler[startPos];
331 int styleNext = styler.StyleAt(startPos);
332 bool headerPoint = false;
333
334 for (unsigned int i = startPos; i < endPos; i++) {
335 char ch = chNext;
336 chNext = styler[i+1];
337
338 int style = styleNext;
339 styleNext = styler.StyleAt(i + 1);
340 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
341
342 if (style==2) {
343 headerPoint = true;
344 }
345
346 if (atEOL) {
347 int lev = SC_FOLDLEVELBASE+1;
348 if (headerPoint)
349 lev = SC_FOLDLEVELBASE;
350
351 if (visibleChars == 0 && foldCompact)
352 lev |= SC_FOLDLEVELWHITEFLAG;
353
354 if (headerPoint)
355 lev |= SC_FOLDLEVELHEADERFLAG;
356
357 if (lev != styler.LevelAt(lineCurrent)) {
358 styler.SetLevel(lineCurrent, lev);
359 }
360
361 lineCurrent++;
362 visibleChars = 0;
363 headerPoint=false;
364 }
365 if (!isspacechar(ch))
366 visibleChars++;
367 }
368
369 int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1;
370 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
371 styler.SetLevel(lineCurrent, lev | flagsNext);
372 }
373
374 static void ColouriseMakeLine(
375 char *lineBuffer,
376 unsigned int lengthLine,
377 unsigned int startLine,
378 unsigned int endPos,
379 Accessor &styler) {
380
381 unsigned int i = 0;
382 int lastNonSpace = -1;
383 unsigned int state = SCE_MAKE_DEFAULT;
384 bool bSpecial = false;
385 // Skip initial spaces
386 while ((i < lengthLine) && isspacechar(lineBuffer[i])) {
387 i++;
388 }
389 if (lineBuffer[i] == '#') { // Comment
390 styler.ColourTo(endPos, SCE_MAKE_COMMENT);
391 return;
392 }
393 if (lineBuffer[i] == '!') { // Special directive
394 styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR);
395 return;
396 }
397 while (i < lengthLine) {
398 if (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(') {
399 styler.ColourTo(startLine + i - 1, state);
400 state = SCE_MAKE_IDENTIFIER;
401 } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') {
402 styler.ColourTo(startLine + i, state);
403 state = SCE_MAKE_DEFAULT;
404 }
405 if (!bSpecial) {
406 if (lineBuffer[i] == ':') {
407 // We should check that no colouring was made since the beginning of the line,
408 // to avoid colouring stuff like /OUT:file
409 if (lastNonSpace >= 0)
410 styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET);
411 styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
412 styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
413 bSpecial = true; // Only react to the first ':' of the line
414 state = SCE_MAKE_DEFAULT;
415 } else if (lineBuffer[i] == '=') {
416 if (lastNonSpace >= 0)
417 styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
418 styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
419 styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
420 bSpecial = true; // Only react to the first '=' of the line
421 state = SCE_MAKE_DEFAULT;
422 }
423 }
424 if (!isspacechar(lineBuffer[i])) {
425 lastNonSpace = i;
426 }
427 i++;
428 }
429 if (state == SCE_MAKE_IDENTIFIER) {
430 styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended
431 } else {
432 styler.ColourTo(endPos, SCE_MAKE_DEFAULT);
433 }
434 }
435
436 static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
437 char lineBuffer[1024];
438 styler.StartAt(startPos);
439 styler.StartSegment(startPos);
440 unsigned int linePos = 0;
441 unsigned int startLine = startPos;
442 for (unsigned int i = startPos; i < startPos + length; i++) {
443 lineBuffer[linePos++] = styler[i];
444 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
445 // End of line (or of line buffer) met, colourise it
446 lineBuffer[linePos] = '\0';
447 ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler);
448 linePos = 0;
449 startLine = i + 1;
450 }
451 }
452 if (linePos > 0) { // Last line does not have ending characters
453 ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
454 }
455 }
456
457 static bool strstart(char *haystack, char *needle) {
458 return strncmp(haystack, needle, strlen(needle)) == 0;
459 }
460
461 static void ColouriseErrorListLine(
462 char *lineBuffer,
463 unsigned int lengthLine,
464 // unsigned int startLine,
465 unsigned int endPos,
466 Accessor &styler) {
467 const int unRecognized = 99;
468 if (lineBuffer[0] == '>') {
469 // Command or return status
470 styler.ColourTo(endPos, SCE_ERR_CMD);
471 } else if (lineBuffer[0] == '<') {
472 // Diff removal, but not interested. Trapped to avoid hitting CTAG cases.
473 styler.ColourTo(endPos, SCE_ERR_DEFAULT);
474 } else if (lineBuffer[0] == '!') {
475 styler.ColourTo(endPos, SCE_ERR_DIFF_CHANGED);
476 } else if (lineBuffer[0] == '+') {
477 styler.ColourTo(endPos, SCE_ERR_DIFF_ADDITION);
478 } else if (lineBuffer[0] == '-' && lineBuffer[1] == '-' && lineBuffer[2] == '-') {
479 styler.ColourTo(endPos, SCE_ERR_DIFF_MESSAGE);
480 } else if (lineBuffer[0] == '-') {
481 styler.ColourTo(endPos, SCE_ERR_DIFF_DELETION);
482 } else if (strstart(lineBuffer, "cf90-")) {
483 // Absoft Pro Fortran 90/95 v8.2 error and/or warning message
484 styler.ColourTo(endPos, SCE_ERR_ABSF);
485 } else if (strstart(lineBuffer, "fortcom:")) {
486 // Intel Fortran Compiler v8.0 error/warning message
487 styler.ColourTo(endPos, SCE_ERR_IFORT);
488 } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
489 styler.ColourTo(endPos, SCE_ERR_PYTHON);
490 } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) {
491 styler.ColourTo(endPos, SCE_ERR_PHP);
492 } else if ((strstart(lineBuffer, "Error ") ||
493 strstart(lineBuffer, "Warning ")) &&
494 strstr(lineBuffer, " at (") &&
495 strstr(lineBuffer, ") : ") &&
496 (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) {
497 // Intel Fortran Compiler error/warning message
498 styler.ColourTo(endPos, SCE_ERR_IFC);
499 } else if (strstart(lineBuffer, "Error ")) {
500 // Borland error message
501 styler.ColourTo(endPos, SCE_ERR_BORLAND);
502 } else if (strstart(lineBuffer, "Warning ")) {
503 // Borland warning message
504 styler.ColourTo(endPos, SCE_ERR_BORLAND);
505 } else if (strstr(lineBuffer, "at line " ) &&
506 (strstr(lineBuffer, "at line " ) < (lineBuffer + lengthLine)) &&
507 strstr(lineBuffer, "file ") &&
508 (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) {
509 // Lua 4 error message
510 styler.ColourTo(endPos, SCE_ERR_LUA);
511 } else if (strstr(lineBuffer, " at " ) &&
512 (strstr(lineBuffer, " at " ) < (lineBuffer + lengthLine)) &&
513 strstr(lineBuffer, " line ") &&
514 (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) &&
515 (strstr(lineBuffer, " at " ) < (strstr(lineBuffer, " line ")))) {
516 // perl error message
517 styler.ColourTo(endPos, SCE_ERR_PERL);
518 } else if ((memcmp(lineBuffer, " at ", 6) == 0) &&
519 strstr(lineBuffer, ":line ")) {
520 // A .NET traceback
521 styler.ColourTo(endPos, SCE_ERR_NET);
522 } else if (strstart(lineBuffer, "Line ") &&
523 strstr(lineBuffer, ", file ")) {
524 // Essential Lahey Fortran error message
525 styler.ColourTo(endPos, SCE_ERR_ELF);
526 } else {
527 // Look for GCC <filename>:<line>:message
528 // Look for Microsoft <filename>(line) :message
529 // Look for Microsoft <filename>(line,pos)message
530 // Look for CTags \tmessage
531 // Look for Lua 5 traceback \t<filename>:<line>:message
532 bool initialTab = (lineBuffer[0] == '\t');
533 int state = 0;
534 for (unsigned int i = 0; i < lengthLine; i++) {
535 char ch = lineBuffer[i];
536 char chNext = ' ';
537 if ((i+1) < lengthLine)
538 chNext = lineBuffer[i+1];
539 if (state == 0) {
540 if (ch == ':') {
541 // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
542 if ((chNext != '\\') && (chNext != '/')) {
543 // This check is not completely accurate as may be on
544 // GTK+ with a file name that includes ':'.
545 state = 1;
546 }
547 } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) {
548 // May be Microsoft
549 // Check against '0' often removes phone numbers
550 state = 10;
551 } else if ((ch == '\t') && (!initialTab)) {
552 // May be CTags
553 state = 20;
554 }
555 } else if (state == 1) {
556 state = Is1To9(ch) ? 2 : unRecognized;
557 } else if (state == 2) {
558 if (ch == ':') {
559 state = 3; // :9.*: is GCC
560 break;
561 } else if (!Is0To9(ch)) {
562 state = unRecognized;
563 }
564 } else if (state == 10) {
565 state = Is0To9(ch) ? 11 : unRecognized;
566 } else if (state == 11) {
567 if (ch == ',') {
568 state = 14;
569 } else if (ch == ')') {
570 state = 12;
571 } else if ((ch != ' ') && !Is0To9(ch)) {
572 state = unRecognized;
573 }
574 } else if (state == 12) {
575 if ((ch == ' ') && (chNext == ':')) {
576 state = 13;
577 } else {
578 state = unRecognized;
579 }
580 } else if (state == 14) {
581 if (ch == ')') {
582 state = 15;
583 break;
584 } else if ((ch != ' ') && !Is0To9(ch)) {
585 state = unRecognized;
586 }
587 } else if (state == 20) {
588 if ((lineBuffer[i-1] == '\t') &&
589 ((ch == '/' && lineBuffer[i+1] == '^') || Is0To9(ch))) {
590 state = 24;
591 break;
592 } else if ((ch == '/') && (lineBuffer[i+1] == '^')) {
593 state = 21;
594 }
595 } else if ((state == 21) && ((lineBuffer[i] == '$') && (lineBuffer[i+1] == '/'))) {
596 state = 22;
597 break;
598 }
599 }
600 if (state == 3) {
601 styler.ColourTo(endPos, SCE_ERR_GCC);
602 } else if ((state == 13) || (state == 14) || (state == 15)) {
603 styler.ColourTo(endPos, SCE_ERR_MS);
604 } else if ((state == 22) || (state == 24)) {
605 styler.ColourTo(endPos, SCE_ERR_CTAG);
606 } else {
607 styler.ColourTo(endPos, SCE_ERR_DEFAULT);
608 }
609 }
610 }
611
612 static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
613 char lineBuffer[1024];
614 styler.StartAt(startPos);
615 styler.StartSegment(startPos);
616 unsigned int linePos = 0;
617 for (unsigned int i = startPos; i < startPos + length; i++) {
618 lineBuffer[linePos++] = styler[i];
619 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
620 // End of line (or of line buffer) met, colourise it
621 lineBuffer[linePos] = '\0';
622 ColouriseErrorListLine(lineBuffer, linePos, i, styler);
623 linePos = 0;
624 }
625 }
626 if (linePos > 0) { // Last line does not have ending characters
627 ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler);
628 }
629 }
630
631 static int isSpecial(char s) {
632 return (s == '\\') || (s == ',') || (s == ';') || (s == '\'') || (s == ' ') ||
633 (s == '\"') || (s == '`') || (s == '^') || (s == '~');
634 }
635
636 static int isTag(int start, Accessor &styler) {
637 char s[6];
638 unsigned int i = 0, e = 1;
639 while (i < 5 && e) {
640 s[i] = styler[start + i];
641 i++;
642 e = styler[start + i] != '{';
643 }
644 s[i] = '\0';
645 return (strcmp(s, "begin") == 0) || (strcmp(s, "end") == 0);
646 }
647
648 static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle,
649 WordList *[], Accessor &styler) {
650
651 styler.StartAt(startPos);
652
653 int state = initStyle;
654 char chNext = styler[startPos];
655 styler.StartSegment(startPos);
656 int lengthDoc = startPos + length;
657
658 for (int i = startPos; i < lengthDoc; i++) {
659 char ch = chNext;
660 chNext = styler.SafeGetCharAt(i + 1);
661
662 if (styler.IsLeadByte(ch)) {
663 chNext = styler.SafeGetCharAt(i + 2);
664 i++;
665 continue;
666 }
667 switch (state) {
668 case SCE_L_DEFAULT :
669 switch (ch) {
670 case '\\' :
671 styler.ColourTo(i - 1, state);
672 if (isSpecial(styler[i + 1])) {
673 styler.ColourTo(i + 1, SCE_L_COMMAND);
674 i++;
675 chNext = styler.SafeGetCharAt(i + 1);
676 } else {
677 if (isTag(i + 1, styler))
678 state = SCE_L_TAG;
679 else
680 state = SCE_L_COMMAND;
681 }
682 break;
683 case '$' :
684 styler.ColourTo(i - 1, state);
685 state = SCE_L_MATH;
686 if (chNext == '$') {
687 i++;
688 chNext = styler.SafeGetCharAt(i + 1);
689 }
690 break;
691 case '%' :
692 styler.ColourTo(i - 1, state);
693 state = SCE_L_COMMENT;
694 break;
695 }
696 break;
697 case SCE_L_COMMAND :
698 if (chNext == '[' || chNext == '{' || chNext == '}' ||
699 chNext == ' ' || chNext == '\r' || chNext == '\n') {
700 styler.ColourTo(i, state);
701 state = SCE_L_DEFAULT;
702 i++;
703 chNext = styler.SafeGetCharAt(i + 1);
704 }
705 break;
706 case SCE_L_TAG :
707 if (ch == '}') {
708 styler.ColourTo(i, state);
709 state = SCE_L_DEFAULT;
710 }
711 break;
712 case SCE_L_MATH :
713 if (ch == '$') {
714 if (chNext == '$') {
715 i++;
716 chNext = styler.SafeGetCharAt(i + 1);
717 }
718 styler.ColourTo(i, state);
719 state = SCE_L_DEFAULT;
720 }
721 break;
722 case SCE_L_COMMENT :
723 if (ch == '\r' || ch == '\n') {
724 styler.ColourTo(i - 1, state);
725 state = SCE_L_DEFAULT;
726 }
727 }
728 }
729 styler.ColourTo(lengthDoc-1, state);
730 }
731
732 static const char * const batchWordListDesc[] = {
733 "Keywords",
734 0
735 };
736
737 static const char * const emptyWordListDesc[] = {
738 0
739 };
740
741 static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[],
742 Accessor &styler) {
743 // Null language means all style bytes are 0 so just mark the end - no need to fill in.
744 if (length > 0) {
745 styler.StartAt(startPos + length - 1);
746 styler.StartSegment(startPos + length - 1);
747 styler.ColourTo(startPos + length - 1, 0);
748 }
749 }
750
751 LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc);
752 LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc);
753 LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc);
754 LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc);
755 LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc);
756 LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc);
757 LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");