| 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 | |