1 | // Scintilla source code edit control |
2 | /** @file LexMPT.cxx |
3 | ** Lexer for MPT specific files. Based on LexOthers.cxx |
4 | ** LOT = the text log file created by the MPT application while running a test program |
5 | ** Other MPT specific files to be added later. |
6 | **/ |
7 | // Copyright 2003 by Marius Gheorghe <mgheorghe@cabletest.com> |
8 | // The License.txt file describes the conditions under which this software may be distributed. |
9 | |
10 | #include <stdlib.h> |
11 | #include <string.h> |
12 | #include <stdio.h> |
13 | #include <stdarg.h> |
14 | #include <assert.h> |
15 | #include <ctype.h> |
16 | |
17 | #include <string> |
18 | #include <string_view> |
19 | |
20 | #include "ILexer.h" |
21 | #include "Scintilla.h" |
22 | #include "SciLexer.h" |
23 | |
24 | #include "WordList.h" |
25 | #include "LexAccessor.h" |
26 | #include "Accessor.h" |
27 | #include "StyleContext.h" |
28 | #include "CharacterSet.h" |
29 | #include "LexerModule.h" |
30 | |
31 | using namespace Lexilla; |
32 | |
33 | static int GetLotLineState(std::string &line) { |
34 | if (line.length()) { |
35 | // Most of the time the first non-blank character in line determines that line's type |
36 | // Now finds the first non-blank character |
37 | unsigned i; // Declares counter here to make it persistent after the for loop |
38 | for (i = 0; i < line.length(); ++i) { |
39 | if (!(IsASCII(line[i]) && isspace(line[i]))) |
40 | break; |
41 | } |
42 | |
43 | // Checks if it was a blank line |
44 | if (i == line.length()) |
45 | return SCE_LOT_DEFAULT; |
46 | |
47 | switch (line[i]) { |
48 | case '*': // Fail measurement |
49 | return SCE_LOT_FAIL; |
50 | |
51 | case '+': // Header |
52 | case '|': // Header |
53 | return SCE_LOT_HEADER; |
54 | |
55 | case ':': // Set test limits |
56 | return SCE_LOT_SET; |
57 | |
58 | case '-': // Section break |
59 | return SCE_LOT_BREAK; |
60 | |
61 | default: // Any other line |
62 | // Checks for message at the end of lot file |
63 | if (line.find("PASSED" ) != std::string::npos) { |
64 | return SCE_LOT_PASS; |
65 | } |
66 | else if (line.find("FAILED" ) != std::string::npos) { |
67 | return SCE_LOT_FAIL; |
68 | } |
69 | else if (line.find("ABORTED" ) != std::string::npos) { |
70 | return SCE_LOT_ABORT; |
71 | } |
72 | else { |
73 | return i ? SCE_LOT_PASS : SCE_LOT_DEFAULT; |
74 | } |
75 | } |
76 | } |
77 | else { |
78 | return SCE_LOT_DEFAULT; |
79 | } |
80 | } |
81 | |
82 | static void ColourizeLotDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) { |
83 | styler.StartAt(startPos); |
84 | styler.StartSegment(startPos); |
85 | bool atLineStart = true;// Arms the 'at line start' flag |
86 | char chNext = styler.SafeGetCharAt(startPos); |
87 | std::string line("" ); |
88 | line.reserve(256); // Lot lines are less than 256 chars long most of the time. This should avoid reallocations |
89 | |
90 | // Styles LOT document |
91 | Sci_PositionU i; // Declared here because it's used after the for loop |
92 | for (i = startPos; i < startPos + length; ++i) { |
93 | char ch = chNext; |
94 | chNext = styler.SafeGetCharAt(i + 1); |
95 | line += ch; |
96 | atLineStart = false; |
97 | |
98 | // LOT files are only used on the Win32 platform, thus EOL == CR+LF |
99 | // Searches for the end of line |
100 | if (ch == '\r' && chNext == '\n') { |
101 | line += chNext; // Gets the '\n' |
102 | ++i; // Advances past the '\n' |
103 | chNext = styler.SafeGetCharAt(i + 1); // Gets character of next line |
104 | styler.ColourTo(i, GetLotLineState(line)); |
105 | line = "" ; |
106 | atLineStart = true; // Arms flag for next line |
107 | } |
108 | } |
109 | |
110 | // Last line may not have a line ending |
111 | if (!atLineStart) { |
112 | styler.ColourTo(i - 1, GetLotLineState(line)); |
113 | } |
114 | } |
115 | |
116 | // Folds an MPT LOT file: the blocks that can be folded are: |
117 | // sections (headed by a set line) |
118 | // passes (contiguous pass results within a section) |
119 | // fails (contiguous fail results within a section) |
120 | static void FoldLotDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) { |
121 | bool foldCompact = styler.GetPropertyInt("fold.compact" , 0) != 0; |
122 | Sci_PositionU endPos = startPos + length; |
123 | int visibleChars = 0; |
124 | Sci_Position lineCurrent = styler.GetLine(startPos); |
125 | |
126 | char chNext = styler.SafeGetCharAt(startPos); |
127 | int style = SCE_LOT_DEFAULT; |
128 | int styleNext = styler.StyleAt(startPos); |
129 | int lev = SC_FOLDLEVELBASE; |
130 | |
131 | // Gets style of previous line if not at the beginning of the document |
132 | if (startPos > 1) |
133 | style = styler.StyleAt(startPos - 2); |
134 | |
135 | for (Sci_PositionU i = startPos; i < endPos; i++) { |
136 | char ch = chNext; |
137 | chNext = styler.SafeGetCharAt(i + 1); |
138 | |
139 | if (ch == '\r' && chNext == '\n') { |
140 | // TO DO: |
141 | // Should really get the state of the previous line from the styler |
142 | int stylePrev = style; |
143 | style = styleNext; |
144 | styleNext = styler.StyleAt(i + 2); |
145 | |
146 | switch (style) { |
147 | /* |
148 | case SCE_LOT_SET: |
149 | lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; |
150 | break; |
151 | */ |
152 | case SCE_LOT_FAIL: |
153 | /* |
154 | if (stylePrev != SCE_LOT_FAIL) |
155 | lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; |
156 | else |
157 | lev = SC_FOLDLEVELBASE + 1; |
158 | */ |
159 | lev = SC_FOLDLEVELBASE; |
160 | break; |
161 | |
162 | default: |
163 | if (lineCurrent == 0 || stylePrev == SCE_LOT_FAIL) |
164 | lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; |
165 | else |
166 | lev = SC_FOLDLEVELBASE + 1; |
167 | |
168 | if (visibleChars == 0 && foldCompact) |
169 | lev |= SC_FOLDLEVELWHITEFLAG; |
170 | break; |
171 | } |
172 | |
173 | if (lev != styler.LevelAt(lineCurrent)) |
174 | styler.SetLevel(lineCurrent, lev); |
175 | |
176 | lineCurrent++; |
177 | visibleChars = 0; |
178 | } |
179 | |
180 | if (!isspacechar(ch)) |
181 | visibleChars++; |
182 | } |
183 | |
184 | int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; |
185 | styler.SetLevel(lineCurrent, lev | flagsNext); |
186 | } |
187 | |
188 | static const char * const emptyWordListDesc[] = { |
189 | 0 |
190 | }; |
191 | |
192 | LexerModule lmLot(SCLEX_LOT, ColourizeLotDoc, "lot" , FoldLotDoc, emptyWordListDesc); |
193 | |