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
31using namespace Lexilla;
32
33static 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
82static 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)
120static 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
188static const char * const emptyWordListDesc[] = {
189 0
190};
191
192LexerModule lmLot(SCLEX_LOT, ColourizeLotDoc, "lot", FoldLotDoc, emptyWordListDesc);
193