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