1 // Scintilla source code edit control
3 ** Lexers for Motorola S-Record, Intel HEX and Tektronix extended HEX.
5 ** Written by Markus Heidelberg
7 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
8 // The License.txt file describes the conditions under which this software may be distributed.
12 * ===============================
14 * Each record (line) is built as follows:
19 * | start | 1 ('S') SCE_HEX_RECSTART
21 * | type | 1 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN)
23 * | count | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG
25 * | address | 4/6/8 SCE_HEX_NOADDRESS, SCE_HEX_DATAADDRESS, SCE_HEX_RECCOUNT, SCE_HEX_STARTADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN)
27 * | data | 0..504/502/500 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN, SCE_HEX_DATA_EMPTY, (SCE_HEX_DATA_UNKNOWN)
29 * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG
34 * ===============================
36 * Each record (line) is built as follows:
41 * | start | 1 (':') SCE_HEX_RECSTART
43 * | count | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG
45 * | address | 4 SCE_HEX_NOADDRESS, SCE_HEX_DATAADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN)
47 * | type | 2 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN)
49 * | data | 0..510 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN, SCE_HEX_DATA_EMPTY, SCE_HEX_EXTENDEDADDRESS, SCE_HEX_STARTADDRESS, (SCE_HEX_DATA_UNKNOWN)
51 * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG
57 * Data records (type 0x00), which follow an extended address record (type
58 * 0x02 or 0x04), can be folded. The extended address record is the fold
59 * point at fold level 0, the corresponding data records are set to level 1.
61 * Any record, which is not a data record, sets the fold level back to 0.
62 * Any line, which is not a record (blank lines and lines starting with a
63 * character other than ':'), leaves the fold level unchanged.
66 * Tektronix extended HEX
67 * ===============================
69 * Each record (line) is built as follows:
74 * | start | 1 ('%') SCE_HEX_RECSTART
76 * | length | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG
78 * | type | 1 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN)
80 * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG
82 * | address | 9 SCE_HEX_DATAADDRESS, SCE_HEX_STARTADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN)
84 * | data | 0..241 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN
88 * General notes for all lexers
89 * ===============================
91 * - Depending on where the helper functions are invoked, some of them have to
92 * read beyond the current position. In case of malformed data (record too
93 * short), it has to be ensured that this either does not have bad influence
94 * or will be captured deliberately.
96 * - States in parentheses in the upper format descriptions indicate that they
97 * should not appear in a valid hex file.
99 * - State SCE_HEX_GARBAGE means garbage data after the intended end of the
100 * record, the line is too long then. This state is used in all lexers.
111 #include "Scintilla.h"
112 #include "SciLexer.h"
114 #include "WordList.h"
115 #include "LexAccessor.h"
116 #include "Accessor.h"
117 #include "StyleContext.h"
118 #include "CharacterSet.h"
119 #include "LexerModule.h"
122 using namespace Scintilla
;
125 // prototypes for general helper functions
126 static inline bool IsNewline(const int ch
);
127 static int GetHexaNibble(char hd
);
128 static int GetHexaChar(char hd1
, char hd2
);
129 static int GetHexaChar(unsigned int pos
, Accessor
&styler
);
130 static bool ForwardWithinLine(StyleContext
&sc
, int nb
= 1);
131 static bool PosInSameRecord(unsigned int pos1
, unsigned int pos2
, Accessor
&styler
);
132 static int CountByteCount(unsigned int startPos
, int uncountedDigits
, Accessor
&styler
);
133 static int CalcChecksum(unsigned int startPos
, int cnt
, bool twosCompl
, Accessor
&styler
);
135 // prototypes for file format specific helper functions
136 static unsigned int GetSrecRecStartPosition(unsigned int pos
, Accessor
&styler
);
137 static int GetSrecByteCount(unsigned int recStartPos
, Accessor
&styler
);
138 static int CountSrecByteCount(unsigned int recStartPos
, Accessor
&styler
);
139 static int GetSrecAddressFieldSize(unsigned int recStartPos
, Accessor
&styler
);
140 static int GetSrecAddressFieldType(unsigned int recStartPos
, Accessor
&styler
);
141 static int GetSrecDataFieldType(unsigned int recStartPos
, Accessor
&styler
);
142 static int GetSrecRequiredDataFieldSize(unsigned int recStartPos
, Accessor
&styler
);
143 static int GetSrecChecksum(unsigned int recStartPos
, Accessor
&styler
);
144 static int CalcSrecChecksum(unsigned int recStartPos
, Accessor
&styler
);
146 static unsigned int GetIHexRecStartPosition(unsigned int pos
, Accessor
&styler
);
147 static int GetIHexByteCount(unsigned int recStartPos
, Accessor
&styler
);
148 static int CountIHexByteCount(unsigned int recStartPos
, Accessor
&styler
);
149 static int GetIHexAddressFieldType(unsigned int recStartPos
, Accessor
&styler
);
150 static int GetIHexDataFieldType(unsigned int recStartPos
, Accessor
&styler
);
151 static int GetIHexRequiredDataFieldSize(unsigned int recStartPos
, Accessor
&styler
);
152 static int GetIHexChecksum(unsigned int recStartPos
, Accessor
&styler
);
153 static int CalcIHexChecksum(unsigned int recStartPos
, Accessor
&styler
);
155 static int GetTEHexDigitCount(unsigned int recStartPos
, Accessor
&styler
);
156 static int CountTEHexDigitCount(unsigned int recStartPos
, Accessor
&styler
);
157 static int GetTEHexAddressFieldType(unsigned int recStartPos
, Accessor
&styler
);
158 static int GetTEHexChecksum(unsigned int recStartPos
, Accessor
&styler
);
159 static int CalcTEHexChecksum(unsigned int recStartPos
, Accessor
&styler
);
161 static inline bool IsNewline(const int ch
)
163 return (ch
== '\n' || ch
== '\r');
166 static int GetHexaNibble(char hd
)
170 if (hd
>= '0' && hd
<= '9') {
171 hexValue
+= hd
- '0';
172 } else if (hd
>= 'A' && hd
<= 'F') {
173 hexValue
+= hd
- 'A' + 10;
174 } else if (hd
>= 'a' && hd
<= 'f') {
175 hexValue
+= hd
- 'a' + 10;
183 static int GetHexaChar(char hd1
, char hd2
)
187 if (hd1
>= '0' && hd1
<= '9') {
188 hexValue
+= 16 * (hd1
- '0');
189 } else if (hd1
>= 'A' && hd1
<= 'F') {
190 hexValue
+= 16 * (hd1
- 'A' + 10);
191 } else if (hd1
>= 'a' && hd1
<= 'f') {
192 hexValue
+= 16 * (hd1
- 'a' + 10);
197 if (hd2
>= '0' && hd2
<= '9') {
198 hexValue
+= hd2
- '0';
199 } else if (hd2
>= 'A' && hd2
<= 'F') {
200 hexValue
+= hd2
- 'A' + 10;
201 } else if (hd2
>= 'a' && hd2
<= 'f') {
202 hexValue
+= hd2
- 'a' + 10;
210 static int GetHexaChar(unsigned int pos
, Accessor
&styler
)
212 char highNibble
, lowNibble
;
214 highNibble
= styler
.SafeGetCharAt(pos
);
215 lowNibble
= styler
.SafeGetCharAt(pos
+ 1);
217 return GetHexaChar(highNibble
, lowNibble
);
220 // Forward <nb> characters, but abort (and return false) if hitting the line
221 // end. Return true if forwarding within the line was possible.
222 // Avoids influence on highlighting of the subsequent line if the current line
223 // is malformed (too short).
224 static bool ForwardWithinLine(StyleContext
&sc
, int nb
)
226 for (int i
= 0; i
< nb
; i
++) {
229 sc
.SetState(SCE_HEX_DEFAULT
);
240 // Checks whether the given positions are in the same record.
241 static bool PosInSameRecord(unsigned int pos1
, unsigned int pos2
, Accessor
&styler
)
243 return styler
.GetLine(pos1
) == styler
.GetLine(pos2
);
246 // Count the number of digit pairs from <startPos> till end of record, ignoring
247 // <uncountedDigits> digits.
248 // If the record is too short, a negative count may be returned.
249 static int CountByteCount(unsigned int startPos
, int uncountedDigits
, Accessor
&styler
)
256 while (!IsNewline(styler
.SafeGetCharAt(pos
, '\n'))) {
260 // number of digits in this line minus number of digits of uncounted fields
261 cnt
= static_cast<int>(pos
- startPos
) - uncountedDigits
;
263 // Prepare round up if odd (digit pair incomplete), this way the byte
264 // count is considered to be valid if the checksum is incomplete.
275 // Calculate the checksum of the record.
276 // <startPos> is the position of the first character of the starting digit
277 // pair, <cnt> is the number of digit pairs.
278 static int CalcChecksum(unsigned int startPos
, int cnt
, bool twosCompl
, Accessor
&styler
)
282 for (unsigned int pos
= startPos
; pos
< startPos
+ cnt
; pos
+= 2) {
283 int val
= GetHexaChar(pos
, styler
);
289 // overflow does not matter
294 // low byte of two's complement
297 // low byte of one's complement
302 // Get the position of the record "start" field (first character in line) in
303 // the record around position <pos>.
304 static unsigned int GetSrecRecStartPosition(unsigned int pos
, Accessor
&styler
)
306 while (styler
.SafeGetCharAt(pos
) != 'S') {
313 // Get the value of the "byte count" field, it counts the number of bytes in
314 // the subsequent fields ("address", "data" and "checksum" fields).
315 static int GetSrecByteCount(unsigned int recStartPos
, Accessor
&styler
)
319 val
= GetHexaChar(recStartPos
+ 2, styler
);
327 // Count the number of digit pairs for the "address", "data" and "checksum"
328 // fields in this record. Has to be equal to the "byte count" field value.
329 // If the record is too short, a negative count may be returned.
330 static int CountSrecByteCount(unsigned int recStartPos
, Accessor
&styler
)
332 return CountByteCount(recStartPos
, 4, styler
);
335 // Get the size of the "address" field.
336 static int GetSrecAddressFieldSize(unsigned int recStartPos
, Accessor
&styler
)
338 switch (styler
.SafeGetCharAt(recStartPos
+ 1)) {
359 // Get the type of the "address" field content.
360 static int GetSrecAddressFieldType(unsigned int recStartPos
, Accessor
&styler
)
362 switch (styler
.SafeGetCharAt(recStartPos
+ 1)) {
364 return SCE_HEX_NOADDRESS
;
369 return SCE_HEX_DATAADDRESS
;
373 return SCE_HEX_RECCOUNT
;
378 return SCE_HEX_STARTADDRESS
;
380 default: // handle possible format extension in the future
381 return SCE_HEX_ADDRESSFIELD_UNKNOWN
;
385 // Get the type of the "data" field content.
386 static int GetSrecDataFieldType(unsigned int recStartPos
, Accessor
&styler
)
388 switch (styler
.SafeGetCharAt(recStartPos
+ 1)) {
393 return SCE_HEX_DATA_ODD
;
400 return SCE_HEX_DATA_EMPTY
;
402 default: // handle possible format extension in the future
403 return SCE_HEX_DATA_UNKNOWN
;
407 // Get the required size of the "data" field. Useless for block header and
408 // ordinary data records (type S0, S1, S2, S3), return the value calculated
409 // from the "byte count" and "address field" size in this case.
410 static int GetSrecRequiredDataFieldSize(unsigned int recStartPos
, Accessor
&styler
)
412 switch (styler
.SafeGetCharAt(recStartPos
+ 1)) {
421 return GetSrecByteCount(recStartPos
, styler
)
422 - GetSrecAddressFieldSize(recStartPos
, styler
)
423 - 1; // -1 for checksum field
427 // Get the value of the "checksum" field.
428 static int GetSrecChecksum(unsigned int recStartPos
, Accessor
&styler
)
432 byteCount
= GetSrecByteCount(recStartPos
, styler
);
434 return GetHexaChar(recStartPos
+ 2 + byteCount
* 2, styler
);
437 // Calculate the checksum of the record.
438 static int CalcSrecChecksum(unsigned int recStartPos
, Accessor
&styler
)
442 byteCount
= GetSrecByteCount(recStartPos
, styler
);
444 // sum over "byte count", "address" and "data" fields (6..510 digits)
445 return CalcChecksum(recStartPos
+ 2, byteCount
* 2, false, styler
);
448 // Get the position of the record "start" field (first character in line) in
449 // the record around position <pos>.
450 static unsigned int GetIHexRecStartPosition(unsigned int pos
, Accessor
&styler
)
452 while (styler
.SafeGetCharAt(pos
) != ':') {
459 // Get the value of the "byte count" field, it counts the number of bytes in
461 static int GetIHexByteCount(unsigned int recStartPos
, Accessor
&styler
)
465 val
= GetHexaChar(recStartPos
+ 1, styler
);
473 // Count the number of digit pairs for the "data" field in this record. Has to
474 // be equal to the "byte count" field value.
475 // If the record is too short, a negative count may be returned.
476 static int CountIHexByteCount(unsigned int recStartPos
, Accessor
&styler
)
478 return CountByteCount(recStartPos
, 11, styler
);
481 // Get the type of the "address" field content.
482 static int GetIHexAddressFieldType(unsigned int recStartPos
, Accessor
&styler
)
484 if (!PosInSameRecord(recStartPos
, recStartPos
+ 7, styler
)) {
485 // malformed (record too short)
486 // type cannot be determined
487 return SCE_HEX_ADDRESSFIELD_UNKNOWN
;
490 switch (GetHexaChar(recStartPos
+ 7, styler
)) {
492 return SCE_HEX_DATAADDRESS
;
499 return SCE_HEX_NOADDRESS
;
501 default: // handle possible format extension in the future
502 return SCE_HEX_ADDRESSFIELD_UNKNOWN
;
506 // Get the type of the "data" field content.
507 static int GetIHexDataFieldType(unsigned int recStartPos
, Accessor
&styler
)
509 switch (GetHexaChar(recStartPos
+ 7, styler
)) {
511 return SCE_HEX_DATA_ODD
;
514 return SCE_HEX_DATA_EMPTY
;
518 return SCE_HEX_EXTENDEDADDRESS
;
522 return SCE_HEX_STARTADDRESS
;
524 default: // handle possible format extension in the future
525 return SCE_HEX_DATA_UNKNOWN
;
529 // Get the required size of the "data" field. Useless for an ordinary data
530 // record (type 00), return the "byte count" in this case.
531 static int GetIHexRequiredDataFieldSize(unsigned int recStartPos
, Accessor
&styler
)
533 switch (GetHexaChar(recStartPos
+ 7, styler
)) {
546 return GetIHexByteCount(recStartPos
, styler
);
550 // Get the value of the "checksum" field.
551 static int GetIHexChecksum(unsigned int recStartPos
, Accessor
&styler
)
555 byteCount
= GetIHexByteCount(recStartPos
, styler
);
557 return GetHexaChar(recStartPos
+ 9 + byteCount
* 2, styler
);
560 // Calculate the checksum of the record.
561 static int CalcIHexChecksum(unsigned int recStartPos
, Accessor
&styler
)
565 byteCount
= GetIHexByteCount(recStartPos
, styler
);
567 // sum over "byte count", "address", "type" and "data" fields (8..518 digits)
568 return CalcChecksum(recStartPos
+ 1, 8 + byteCount
* 2, true, styler
);
572 // Get the value of the "record length" field, it counts the number of digits in
573 // the record excluding the percent.
574 static int GetTEHexDigitCount(unsigned int recStartPos
, Accessor
&styler
)
576 int val
= GetHexaChar(recStartPos
+ 1, styler
);
583 // Count the number of digits in this record. Has to
584 // be equal to the "record length" field value.
585 static int CountTEHexDigitCount(unsigned int recStartPos
, Accessor
&styler
)
591 while (!IsNewline(styler
.SafeGetCharAt(pos
, '\n'))) {
595 return static_cast<int>(pos
- (recStartPos
+1));
598 // Get the type of the "address" field content.
599 static int GetTEHexAddressFieldType(unsigned int recStartPos
, Accessor
&styler
)
601 switch (styler
.SafeGetCharAt(recStartPos
+ 3)) {
603 return SCE_HEX_DATAADDRESS
;
606 return SCE_HEX_STARTADDRESS
;
608 default: // handle possible format extension in the future
609 return SCE_HEX_ADDRESSFIELD_UNKNOWN
;
613 // Get the value of the "checksum" field.
614 static int GetTEHexChecksum(unsigned int recStartPos
, Accessor
&styler
)
616 return GetHexaChar(recStartPos
+4, styler
);
619 // Calculate the checksum of the record (excluding the checksum field).
620 static int CalcTEHexChecksum(unsigned int recStartPos
, Accessor
&styler
)
622 unsigned int pos
= recStartPos
+1;
623 unsigned int length
= GetTEHexDigitCount(recStartPos
, styler
);
625 int cs
= GetHexaNibble(styler
.SafeGetCharAt(pos
++));//length
626 cs
+= GetHexaNibble(styler
.SafeGetCharAt(pos
++));//length
628 cs
+= GetHexaNibble(styler
.SafeGetCharAt(pos
++));//type
630 pos
+= 2;// jump over CS field
632 for (; pos
<= recStartPos
+ length
; ++pos
) {
633 int val
= GetHexaNibble(styler
.SafeGetCharAt(pos
));
639 // overflow does not matter
648 static void ColouriseSrecDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*[], Accessor
&styler
)
650 StyleContext
sc(startPos
, length
, initStyle
, styler
);
653 unsigned int recStartPos
;
654 int byteCount
, reqByteCount
, addrFieldSize
, addrFieldType
, dataFieldSize
, dataFieldType
;
658 case SCE_HEX_DEFAULT
:
659 if (sc
.atLineStart
&& sc
.Match('S')) {
660 sc
.SetState(SCE_HEX_RECSTART
);
662 ForwardWithinLine(sc
);
665 case SCE_HEX_RECSTART
:
666 recStartPos
= sc
.currentPos
- 1;
667 addrFieldType
= GetSrecAddressFieldType(recStartPos
, styler
);
669 if (addrFieldType
== SCE_HEX_ADDRESSFIELD_UNKNOWN
) {
670 sc
.SetState(SCE_HEX_RECTYPE_UNKNOWN
);
672 sc
.SetState(SCE_HEX_RECTYPE
);
675 ForwardWithinLine(sc
);
678 case SCE_HEX_RECTYPE
:
679 case SCE_HEX_RECTYPE_UNKNOWN
:
680 recStartPos
= sc
.currentPos
- 2;
681 byteCount
= GetSrecByteCount(recStartPos
, styler
);
682 reqByteCount
= GetSrecAddressFieldSize(recStartPos
, styler
)
683 + GetSrecRequiredDataFieldSize(recStartPos
, styler
)
684 + 1; // +1 for checksum field
686 if (byteCount
== CountSrecByteCount(recStartPos
, styler
)
687 && byteCount
== reqByteCount
) {
688 sc
.SetState(SCE_HEX_BYTECOUNT
);
690 sc
.SetState(SCE_HEX_BYTECOUNT_WRONG
);
693 ForwardWithinLine(sc
, 2);
696 case SCE_HEX_BYTECOUNT
:
697 case SCE_HEX_BYTECOUNT_WRONG
:
698 recStartPos
= sc
.currentPos
- 4;
699 addrFieldSize
= GetSrecAddressFieldSize(recStartPos
, styler
);
700 addrFieldType
= GetSrecAddressFieldType(recStartPos
, styler
);
702 sc
.SetState(addrFieldType
);
703 ForwardWithinLine(sc
, addrFieldSize
* 2);
706 case SCE_HEX_NOADDRESS
:
707 case SCE_HEX_DATAADDRESS
:
708 case SCE_HEX_RECCOUNT
:
709 case SCE_HEX_STARTADDRESS
:
710 case SCE_HEX_ADDRESSFIELD_UNKNOWN
:
711 recStartPos
= GetSrecRecStartPosition(sc
.currentPos
, styler
);
712 dataFieldType
= GetSrecDataFieldType(recStartPos
, styler
);
714 // Using the required size here if possible has the effect that the
715 // checksum is highlighted at a fixed position after this field for
716 // specific record types, independent on the "byte count" value.
717 dataFieldSize
= GetSrecRequiredDataFieldSize(recStartPos
, styler
);
719 sc
.SetState(dataFieldType
);
721 if (dataFieldType
== SCE_HEX_DATA_ODD
) {
722 for (int i
= 0; i
< dataFieldSize
* 2; i
++) {
723 if ((i
& 0x3) == 0) {
724 sc
.SetState(SCE_HEX_DATA_ODD
);
725 } else if ((i
& 0x3) == 2) {
726 sc
.SetState(SCE_HEX_DATA_EVEN
);
729 if (!ForwardWithinLine(sc
)) {
734 ForwardWithinLine(sc
, dataFieldSize
* 2);
738 case SCE_HEX_DATA_ODD
:
739 case SCE_HEX_DATA_EVEN
:
740 case SCE_HEX_DATA_EMPTY
:
741 case SCE_HEX_DATA_UNKNOWN
:
742 recStartPos
= GetSrecRecStartPosition(sc
.currentPos
, styler
);
743 cs1
= CalcSrecChecksum(recStartPos
, styler
);
744 cs2
= GetSrecChecksum(recStartPos
, styler
);
746 if (cs1
!= cs2
|| cs1
< 0 || cs2
< 0) {
747 sc
.SetState(SCE_HEX_CHECKSUM_WRONG
);
749 sc
.SetState(SCE_HEX_CHECKSUM
);
752 ForwardWithinLine(sc
, 2);
755 case SCE_HEX_CHECKSUM
:
756 case SCE_HEX_CHECKSUM_WRONG
:
757 case SCE_HEX_GARBAGE
:
758 // record finished or line too long
759 sc
.SetState(SCE_HEX_GARBAGE
);
760 ForwardWithinLine(sc
);
764 // prevent endless loop in faulty state
765 sc
.SetState(SCE_HEX_DEFAULT
);
772 static void ColouriseIHexDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*[], Accessor
&styler
)
774 StyleContext
sc(startPos
, length
, initStyle
, styler
);
777 unsigned int recStartPos
;
778 int byteCount
, addrFieldType
, dataFieldSize
, dataFieldType
;
782 case SCE_HEX_DEFAULT
:
783 if (sc
.atLineStart
&& sc
.Match(':')) {
784 sc
.SetState(SCE_HEX_RECSTART
);
786 ForwardWithinLine(sc
);
789 case SCE_HEX_RECSTART
:
790 recStartPos
= sc
.currentPos
- 1;
791 byteCount
= GetIHexByteCount(recStartPos
, styler
);
792 dataFieldSize
= GetIHexRequiredDataFieldSize(recStartPos
, styler
);
794 if (byteCount
== CountIHexByteCount(recStartPos
, styler
)
795 && byteCount
== dataFieldSize
) {
796 sc
.SetState(SCE_HEX_BYTECOUNT
);
798 sc
.SetState(SCE_HEX_BYTECOUNT_WRONG
);
801 ForwardWithinLine(sc
, 2);
804 case SCE_HEX_BYTECOUNT
:
805 case SCE_HEX_BYTECOUNT_WRONG
:
806 recStartPos
= sc
.currentPos
- 3;
807 addrFieldType
= GetIHexAddressFieldType(recStartPos
, styler
);
809 sc
.SetState(addrFieldType
);
810 ForwardWithinLine(sc
, 4);
813 case SCE_HEX_NOADDRESS
:
814 case SCE_HEX_DATAADDRESS
:
815 case SCE_HEX_ADDRESSFIELD_UNKNOWN
:
816 recStartPos
= sc
.currentPos
- 7;
817 addrFieldType
= GetIHexAddressFieldType(recStartPos
, styler
);
819 if (addrFieldType
== SCE_HEX_ADDRESSFIELD_UNKNOWN
) {
820 sc
.SetState(SCE_HEX_RECTYPE_UNKNOWN
);
822 sc
.SetState(SCE_HEX_RECTYPE
);
825 ForwardWithinLine(sc
, 2);
828 case SCE_HEX_RECTYPE
:
829 case SCE_HEX_RECTYPE_UNKNOWN
:
830 recStartPos
= sc
.currentPos
- 9;
831 dataFieldType
= GetIHexDataFieldType(recStartPos
, styler
);
833 // Using the required size here if possible has the effect that the
834 // checksum is highlighted at a fixed position after this field for
835 // specific record types, independent on the "byte count" value.
836 dataFieldSize
= GetIHexRequiredDataFieldSize(recStartPos
, styler
);
838 sc
.SetState(dataFieldType
);
840 if (dataFieldType
== SCE_HEX_DATA_ODD
) {
841 for (int i
= 0; i
< dataFieldSize
* 2; i
++) {
842 if ((i
& 0x3) == 0) {
843 sc
.SetState(SCE_HEX_DATA_ODD
);
844 } else if ((i
& 0x3) == 2) {
845 sc
.SetState(SCE_HEX_DATA_EVEN
);
848 if (!ForwardWithinLine(sc
)) {
853 ForwardWithinLine(sc
, dataFieldSize
* 2);
857 case SCE_HEX_DATA_ODD
:
858 case SCE_HEX_DATA_EVEN
:
859 case SCE_HEX_DATA_EMPTY
:
860 case SCE_HEX_EXTENDEDADDRESS
:
861 case SCE_HEX_STARTADDRESS
:
862 case SCE_HEX_DATA_UNKNOWN
:
863 recStartPos
= GetIHexRecStartPosition(sc
.currentPos
, styler
);
864 cs1
= CalcIHexChecksum(recStartPos
, styler
);
865 cs2
= GetIHexChecksum(recStartPos
, styler
);
867 if (cs1
!= cs2
|| cs1
< 0 || cs2
< 0) {
868 sc
.SetState(SCE_HEX_CHECKSUM_WRONG
);
870 sc
.SetState(SCE_HEX_CHECKSUM
);
873 ForwardWithinLine(sc
, 2);
876 case SCE_HEX_CHECKSUM
:
877 case SCE_HEX_CHECKSUM_WRONG
:
878 case SCE_HEX_GARBAGE
:
879 // record finished or line too long
880 sc
.SetState(SCE_HEX_GARBAGE
);
881 ForwardWithinLine(sc
);
885 // prevent endless loop in faulty state
886 sc
.SetState(SCE_HEX_DEFAULT
);
893 static void FoldIHexDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
)
895 unsigned int endPos
= startPos
+ length
;
897 int lineCurrent
= styler
.GetLine(startPos
);
898 int levelCurrent
= SC_FOLDLEVELBASE
;
900 levelCurrent
= styler
.LevelAt(lineCurrent
- 1);
902 unsigned int lineStartNext
= styler
.LineStart(lineCurrent
+ 1);
903 int levelNext
= SC_FOLDLEVELBASE
; // default if no specific line found
905 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
906 bool atEOL
= i
== (lineStartNext
- 1);
907 int style
= styler
.StyleAt(i
);
909 // search for specific lines
910 if (style
== SCE_HEX_EXTENDEDADDRESS
) {
911 // extended addres record
912 levelNext
= SC_FOLDLEVELBASE
| SC_FOLDLEVELHEADERFLAG
;
913 } else if (style
== SCE_HEX_DATAADDRESS
914 || (style
== SCE_HEX_DEFAULT
915 && i
== (unsigned int)styler
.LineStart(lineCurrent
))) {
916 // data record or no record start code at all
917 if (levelCurrent
& SC_FOLDLEVELHEADERFLAG
) {
918 levelNext
= SC_FOLDLEVELBASE
+ 1;
920 // continue level 0 or 1, no fold point
921 levelNext
= levelCurrent
;
925 if (atEOL
|| (i
== endPos
- 1)) {
926 styler
.SetLevel(lineCurrent
, levelNext
);
929 lineStartNext
= styler
.LineStart(lineCurrent
+ 1);
930 levelCurrent
= levelNext
;
931 levelNext
= SC_FOLDLEVELBASE
;
936 static void ColouriseTEHexDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*[], Accessor
&styler
)
938 StyleContext
sc(startPos
, length
, initStyle
, styler
);
941 unsigned int recStartPos
;
942 int digitCount
, addrFieldType
;
946 case SCE_HEX_DEFAULT
:
947 if (sc
.atLineStart
&& sc
.Match('%')) {
948 sc
.SetState(SCE_HEX_RECSTART
);
950 ForwardWithinLine(sc
);
953 case SCE_HEX_RECSTART
:
955 recStartPos
= sc
.currentPos
- 1;
957 if (GetTEHexDigitCount(recStartPos
, styler
) == CountTEHexDigitCount(recStartPos
, styler
)) {
958 sc
.SetState(SCE_HEX_BYTECOUNT
);
960 sc
.SetState(SCE_HEX_BYTECOUNT_WRONG
);
963 ForwardWithinLine(sc
, 2);
966 case SCE_HEX_BYTECOUNT
:
967 case SCE_HEX_BYTECOUNT_WRONG
:
968 recStartPos
= sc
.currentPos
- 3;
969 addrFieldType
= GetTEHexAddressFieldType(recStartPos
, styler
);
971 if (addrFieldType
== SCE_HEX_ADDRESSFIELD_UNKNOWN
) {
972 sc
.SetState(SCE_HEX_RECTYPE_UNKNOWN
);
974 sc
.SetState(SCE_HEX_RECTYPE
);
977 ForwardWithinLine(sc
);
980 case SCE_HEX_RECTYPE
:
981 case SCE_HEX_RECTYPE_UNKNOWN
:
982 recStartPos
= sc
.currentPos
- 4;
983 cs1
= CalcTEHexChecksum(recStartPos
, styler
);
984 cs2
= GetTEHexChecksum(recStartPos
, styler
);
986 if (cs1
!= cs2
|| cs1
< 0 || cs2
< 0) {
987 sc
.SetState(SCE_HEX_CHECKSUM_WRONG
);
989 sc
.SetState(SCE_HEX_CHECKSUM
);
992 ForwardWithinLine(sc
, 2);
996 case SCE_HEX_CHECKSUM
:
997 case SCE_HEX_CHECKSUM_WRONG
:
998 recStartPos
= sc
.currentPos
- 6;
999 addrFieldType
= GetTEHexAddressFieldType(recStartPos
, styler
);
1001 sc
.SetState(addrFieldType
);
1002 ForwardWithinLine(sc
, 9);
1005 case SCE_HEX_DATAADDRESS
:
1006 case SCE_HEX_STARTADDRESS
:
1007 case SCE_HEX_ADDRESSFIELD_UNKNOWN
:
1008 recStartPos
= sc
.currentPos
- 15;
1009 digitCount
= GetTEHexDigitCount(recStartPos
, styler
) - 14;
1011 sc
.SetState(SCE_HEX_DATA_ODD
);
1013 for (int i
= 0; i
< digitCount
; i
++) {
1014 if ((i
& 0x3) == 0) {
1015 sc
.SetState(SCE_HEX_DATA_ODD
);
1016 } else if ((i
& 0x3) == 2) {
1017 sc
.SetState(SCE_HEX_DATA_EVEN
);
1020 if (!ForwardWithinLine(sc
)) {
1026 case SCE_HEX_DATA_ODD
:
1027 case SCE_HEX_DATA_EVEN
:
1028 case SCE_HEX_GARBAGE
:
1029 // record finished or line too long
1030 sc
.SetState(SCE_HEX_GARBAGE
);
1031 ForwardWithinLine(sc
);
1035 // prevent endless loop in faulty state
1036 sc
.SetState(SCE_HEX_DEFAULT
);
1043 LexerModule
lmSrec(SCLEX_SREC
, ColouriseSrecDoc
, "srec", 0, NULL
);
1044 LexerModule
lmIHex(SCLEX_IHEX
, ColouriseIHexDoc
, "ihex", FoldIHexDoc
, NULL
);
1045 LexerModule
lmTEHex(SCLEX_TEHEX
, ColouriseTEHexDoc
, "tehex", 0, NULL
);