aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/ScintillaHistory.html5
-rw-r--r--include/SciLexer.h14
-rw-r--r--include/Scintilla.iface16
-rw-r--r--lexers/LexHex.cxx360
-rw-r--r--src/Catalogue.cxx1
-rw-r--r--win32/scintilla.mak3
6 files changed, 399 insertions, 0 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index a1cb40b68..340bcc234 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -463,6 +463,7 @@
</tr><tr>
<td>Erik Angelin</td>
<td>Yusuf Ramazan Karagöz</td>
+ <td>Markus Heidelberg</td>
</tr>
</table>
<p>
@@ -482,6 +483,10 @@
Released 2 December 2014.
</li>
<li>
+ Lexer added for Motorola S-Record files.
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/1091/">Feature #1091.</a>
+ </li>
+ <li>
C++ folder allows folding on square brackets '['.
<a href="http://sourceforge.net/p/scintilla/feature-requests/1087/">Feature #1087.</a>
</li>
diff --git a/include/SciLexer.h b/include/SciLexer.h
index dc75a98b6..b2539eb91 100644
--- a/include/SciLexer.h
+++ b/include/SciLexer.h
@@ -129,6 +129,7 @@
#define SCLEX_DMIS 114
#define SCLEX_REGISTRY 115
#define SCLEX_BIBTEX 116
+#define SCLEX_SREC 117
#define SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0
#define SCE_P_COMMENTLINE 1
@@ -1741,6 +1742,19 @@
#define SCE_BIBTEX_PARAMETER 4
#define SCE_BIBTEX_VALUE 5
#define SCE_BIBTEX_COMMENT 6
+#define SCE_SREC_DEFAULT 0
+#define SCE_SREC_RECSTART 1
+#define SCE_SREC_RECTYPE 2
+#define SCE_SREC_BYTECOUNT 3
+#define SCE_SREC_BYTECOUNT_WRONG 4
+#define SCE_SREC_NOADDRESS 5
+#define SCE_SREC_DATAADDRESS 6
+#define SCE_SREC_RECCOUNT 7
+#define SCE_SREC_STARTADDRESS 8
+#define SCE_SREC_DATA_ODD 9
+#define SCE_SREC_DATA_EVEN 10
+#define SCE_SREC_CHECKSUM 11
+#define SCE_SREC_CHECKSUM_WRONG 12
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */
#endif
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index ca54c65ee..803028022 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -2719,6 +2719,7 @@ val SCLEX_AS=113
val SCLEX_DMIS=114
val SCLEX_REGISTRY=115
val SCLEX_BIBTEX=116
+val SCLEX_SREC=117
# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
# value assigned in sequence from SCLEX_AUTOMATIC+1.
@@ -4542,6 +4543,21 @@ val SCE_BIBTEX_KEY=3
val SCE_BIBTEX_PARAMETER=4
val SCE_BIBTEX_VALUE=5
val SCE_BIBTEX_COMMENT=6
+# Lexical state for SCLEX_SREC
+lex Srec=SCLEX_SREC SCE_SREC_
+val SCE_SREC_DEFAULT=0
+val SCE_SREC_RECSTART=1
+val SCE_SREC_RECTYPE=2
+val SCE_SREC_BYTECOUNT=3
+val SCE_SREC_BYTECOUNT_WRONG=4
+val SCE_SREC_NOADDRESS=5
+val SCE_SREC_DATAADDRESS=6
+val SCE_SREC_RECCOUNT=7
+val SCE_SREC_STARTADDRESS=8
+val SCE_SREC_DATA_ODD=9
+val SCE_SREC_DATA_EVEN=10
+val SCE_SREC_CHECKSUM=11
+val SCE_SREC_CHECKSUM_WRONG=12
# Events
diff --git a/lexers/LexHex.cxx b/lexers/LexHex.cxx
new file mode 100644
index 000000000..ff4aec3a8
--- /dev/null
+++ b/lexers/LexHex.cxx
@@ -0,0 +1,360 @@
+// Scintilla source code edit control
+/** @file LexHex.cxx
+ ** Lexer for Motorola S-Record.
+ **
+ ** Written by Markus Heidelberg
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+/*
+ * Motorola S-Record file format
+ * ===============================
+ *
+ * Each record (line) is built as follows:
+ *
+ * field size states
+ *
+ * +----------+
+ * | start | 1 ('S') SCE_SREC_RECSTART
+ * +----------+
+ * | type | 1 SCE_SREC_RECTYPE
+ * +----------+
+ * | count | 2 SCE_SREC_BYTECOUNT, SCE_SREC_BYTECOUNT_WRONG
+ * +----------+
+ * | address | 4/6/8 SCE_SREC_NOADDRESS, SCE_SREC_DATAADDRESS, SCE_SREC_RECCOUNT, SCE_SREC_STARTADDRESS
+ * +----------+
+ * | data | 0..500 SCE_SREC_DATA_ODD, SCE_SREC_DATA_EVEN
+ * +----------+
+ * | checksum | 2 SCE_SREC_CHECKSUM, SCE_SREC_CHECKSUM_WRONG
+ * +----------+
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "ILexer.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#include "WordList.h"
+#include "LexAccessor.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "CharacterSet.h"
+#include "LexerModule.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// prototypes for general helper functions
+static inline bool IsNewline(const int ch);
+static int GetHexaChar(char hd1, char hd2);
+static int GetHexaChar(unsigned int pos, Accessor &styler);
+static bool ForwardWithinLine(StyleContext &sc, int nb = 1);
+
+// prototypes for file format specific helper functions
+static unsigned int GetSrecRecStartPosition(unsigned int pos, Accessor &styler);
+static int GetSrecByteCount(unsigned int recStartPos, Accessor &styler);
+static int CountSrecByteCount(unsigned int recStartPos, Accessor &styler);
+static int GetSrecAddressFieldSize(unsigned int recStartPos, Accessor &styler);
+static int GetSrecAddressFieldType(unsigned int recStartPos, Accessor &styler);
+static int GetSrecChecksum(unsigned int recStartPos, Accessor &styler);
+static int CalcSrecChecksum(unsigned int recStartPos, Accessor &styler);
+
+static inline bool IsNewline(const int ch)
+{
+ return (ch == '\n' || ch == '\r');
+}
+
+static int GetHexaChar(char hd1, char hd2)
+{
+ int hexValue = 0;
+
+ if (hd1 >= '0' && hd1 <= '9') {
+ hexValue += 16 * (hd1 - '0');
+ } else if (hd1 >= 'A' && hd1 <= 'F') {
+ hexValue += 16 * (hd1 - 'A' + 10);
+ } else if (hd1 >= 'a' && hd1 <= 'f') {
+ hexValue += 16 * (hd1 - 'a' + 10);
+ } else {
+ return -1;
+ }
+
+ if (hd2 >= '0' && hd2 <= '9') {
+ hexValue += hd2 - '0';
+ } else if (hd2 >= 'A' && hd2 <= 'F') {
+ hexValue += hd2 - 'A' + 10;
+ } else if (hd2 >= 'a' && hd2 <= 'f') {
+ hexValue += hd2 - 'a' + 10;
+ } else {
+ return -1;
+ }
+
+ return hexValue;
+}
+
+static int GetHexaChar(unsigned int pos, Accessor &styler)
+{
+ char highNibble, lowNibble;
+
+ highNibble = styler.SafeGetCharAt(pos);
+ lowNibble = styler.SafeGetCharAt(pos + 1);
+
+ return GetHexaChar(highNibble, lowNibble);
+}
+
+// Forward <nb> characters, but abort (and return false) if hitting the line
+// end. Return true if forwarding within the line was possible.
+// Avoids influence on highlighting of the subsequent line if the current line
+// is malformed (too short).
+static bool ForwardWithinLine(StyleContext &sc, int nb)
+{
+ for (int i = 0; i < nb; i++) {
+ if (sc.atLineEnd) {
+ // line is too short
+ sc.SetState(SCE_SREC_DEFAULT);
+ sc.Forward();
+ return false;
+ } else {
+ sc.Forward();
+ }
+ }
+
+ return true;
+}
+
+// Get the position of the record "start" field (first character in line) in
+// the record around position <pos>.
+static unsigned int GetSrecRecStartPosition(unsigned int pos, Accessor &styler)
+{
+ while (styler.SafeGetCharAt(pos) != 'S') {
+ pos--;
+ }
+
+ return pos;
+}
+
+// Get the value of the "byte count" field, it counts the number of bytes in
+// the subsequent fields ("address", "data" and "checksum" fields).
+static int GetSrecByteCount(unsigned int recStartPos, Accessor &styler)
+{
+ int val;
+
+ val = GetHexaChar(recStartPos + 2, styler);
+ if (val < 0) {
+ val = 0;
+ }
+
+ return val;
+}
+
+// Count the number of digit pairs in this record from "address" field to end
+// of line. Has to be equal to the "byte count" field value.
+static int CountSrecByteCount(unsigned int recStartPos, Accessor &styler)
+{
+ unsigned int pos;
+
+ // start counting at "address" field
+ pos = recStartPos + 4;
+
+ while (!IsNewline(styler.SafeGetCharAt(pos, '\n'))) {
+ pos++;
+ }
+
+ // divide by 2 because of digit pairs
+ // Round up if odd (digit pair incomplete), this way the byte count is
+ // considered to be valid if the checksum is incomplete.
+ return ((pos - (recStartPos + 4)) + 1) / 2;
+}
+
+// Get the size of the "address" field.
+static int GetSrecAddressFieldSize(unsigned int recStartPos, Accessor &styler)
+{
+ switch (styler.SafeGetCharAt(recStartPos + 1)) {
+ case '0':
+ case '1':
+ case '5':
+ case '9':
+ return 2; // 16 bit
+
+ case '2':
+ case '6':
+ case '8':
+ return 3; // 24 bit
+
+ case '3':
+ case '7':
+ return 4; // 32 bit
+
+ default:
+ return 0;
+ }
+}
+
+// Get the type of the "address" field content.
+static int GetSrecAddressFieldType(unsigned int recStartPos, Accessor &styler)
+{
+ switch (styler.SafeGetCharAt(recStartPos + 1)) {
+ case '0':
+ return SCE_SREC_NOADDRESS;
+
+ case '1':
+ case '2':
+ case '3':
+ return SCE_SREC_DATAADDRESS;
+
+ case '5':
+ case '6':
+ return SCE_SREC_RECCOUNT;
+
+ case '7':
+ case '8':
+ case '9':
+ return SCE_SREC_STARTADDRESS;
+
+ default:
+ return SCE_SREC_DEFAULT;
+ }
+}
+
+// Get the value of the "checksum" field.
+static int GetSrecChecksum(unsigned int recStartPos, Accessor &styler)
+{
+ int byteCount;
+
+ byteCount = GetSrecByteCount(recStartPos, styler);
+
+ return GetHexaChar(recStartPos + 2 + byteCount * 2, styler);
+}
+
+// Calculate the checksum of the record.
+static int CalcSrecChecksum(unsigned int recStartPos, Accessor &styler)
+{
+ int byteCount;
+ unsigned int cs = 0;
+
+ byteCount = GetSrecByteCount(recStartPos, styler);
+
+ // sum over "byte count", "address" and "data" fields
+ for (unsigned int pos = recStartPos + 2; pos < recStartPos + 2 + byteCount * 2; pos += 2) {
+ int val = GetHexaChar(pos, styler);
+
+ if (val < 0) {
+ return val;
+ }
+
+ cs += val;
+ }
+
+ // low byte of one's complement
+ return (~cs) & 0xFF;
+}
+
+static void ColouriseSrecDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler)
+{
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ while (sc.More()) {
+ unsigned int recStartPos;
+ int byteCount, addrFieldSize, addrFieldType, dataFieldSize;
+ int cs1, cs2;
+
+ switch (sc.state) {
+ case SCE_SREC_DEFAULT:
+ if (sc.atLineStart && sc.Match('S')) {
+ sc.SetState(SCE_SREC_RECSTART);
+ }
+ ForwardWithinLine(sc);
+ break;
+
+ case SCE_SREC_RECSTART:
+ sc.SetState(SCE_SREC_RECTYPE);
+ ForwardWithinLine(sc);
+ break;
+
+ case SCE_SREC_RECTYPE:
+ recStartPos = sc.currentPos - 2;
+ byteCount = GetSrecByteCount(recStartPos, styler);
+
+ if (byteCount == CountSrecByteCount(recStartPos, styler)) {
+ sc.SetState(SCE_SREC_BYTECOUNT);
+ } else {
+ sc.SetState(SCE_SREC_BYTECOUNT_WRONG);
+ }
+
+ ForwardWithinLine(sc, 2);
+ break;
+
+ case SCE_SREC_BYTECOUNT:
+ case SCE_SREC_BYTECOUNT_WRONG:
+ recStartPos = sc.currentPos - 4;
+ addrFieldSize = GetSrecAddressFieldSize(recStartPos, styler);
+ addrFieldType = GetSrecAddressFieldType(recStartPos, styler);
+
+ if (addrFieldSize > 0) {
+ sc.SetState(addrFieldType);
+ ForwardWithinLine(sc, addrFieldSize * 2);
+ } else {
+ // malformed
+ sc.SetState(SCE_SREC_DEFAULT);
+ ForwardWithinLine(sc);
+ }
+ break;
+
+ case SCE_SREC_NOADDRESS:
+ case SCE_SREC_DATAADDRESS:
+ case SCE_SREC_RECCOUNT:
+ case SCE_SREC_STARTADDRESS:
+ recStartPos = GetSrecRecStartPosition(sc.currentPos, styler);
+ byteCount = GetSrecByteCount(recStartPos, styler);
+ addrFieldSize = GetSrecAddressFieldSize(recStartPos, styler);
+ dataFieldSize = byteCount - addrFieldSize - 1; // -1 for checksum field
+
+ sc.SetState(SCE_SREC_DATA_ODD);
+
+ for (int i = 0; i < dataFieldSize * 2; i++) {
+ if ((i & 0x3) == 0) {
+ sc.SetState(SCE_SREC_DATA_ODD);
+ } else if ((i & 0x3) == 2) {
+ sc.SetState(SCE_SREC_DATA_EVEN);
+ }
+
+ if (!ForwardWithinLine(sc)) {
+ break;
+ }
+ }
+ break;
+
+ case SCE_SREC_DATA_ODD:
+ case SCE_SREC_DATA_EVEN:
+ recStartPos = GetSrecRecStartPosition(sc.currentPos, styler);
+ cs1 = CalcSrecChecksum(recStartPos, styler);
+ cs2 = GetSrecChecksum(recStartPos, styler);
+
+ if (cs1 != cs2 || cs1 < 0 || cs2 < 0) {
+ sc.SetState(SCE_SREC_CHECKSUM_WRONG);
+ } else {
+ sc.SetState(SCE_SREC_CHECKSUM);
+ }
+
+ ForwardWithinLine(sc, 2);
+ break;
+
+ case SCE_SREC_CHECKSUM:
+ case SCE_SREC_CHECKSUM_WRONG:
+ // record finished
+ sc.SetState(SCE_SREC_DEFAULT);
+ ForwardWithinLine(sc);
+ break;
+ }
+ }
+ sc.Complete();
+}
+
+LexerModule lmSrec(SCLEX_SREC, ColouriseSrecDoc, "srec", 0, NULL);
diff --git a/src/Catalogue.cxx b/src/Catalogue.cxx
index 3fd006f7a..e2377e14c 100644
--- a/src/Catalogue.cxx
+++ b/src/Catalogue.cxx
@@ -174,6 +174,7 @@ int Scintilla_LinkLexers() {
LINK_LEXER(lmSpecman);
LINK_LEXER(lmSpice);
LINK_LEXER(lmSQL);
+ LINK_LEXER(lmSrec);
LINK_LEXER(lmSTTXT);
LINK_LEXER(lmTACL);
LINK_LEXER(lmTADS3);
diff --git a/win32/scintilla.mak b/win32/scintilla.mak
index 43679cbc7..e1c5277bc 100644
--- a/win32/scintilla.mak
+++ b/win32/scintilla.mak
@@ -136,6 +136,7 @@ LEXOBJS=\
$(DIR_O)\LexGAP.obj \
$(DIR_O)\LexGui4Cli.obj \
$(DIR_O)\LexHaskell.obj \
+ $(DIR_O)\LexHex.obj \
$(DIR_O)\LexHTML.obj \
$(DIR_O)\LexInno.obj \
$(DIR_O)\LexKix.obj \
@@ -530,6 +531,8 @@ $(DIR_O)\LexGui4Cli.obj: ..\lexers\LexGui4Cli.cxx $(LEX_HEADERS)
$(DIR_O)\LexHaskell.obj: ..\lexers\LexHaskell.cxx $(LEX_HEADERS)
+$(DIR_O)\LexHex.obj: ..\lexers\LexHex.cxx $(LEX_HEADERS)
+
$(DIR_O)\LexHTML.obj: ..\lexers\LexHTML.cxx $(LEX_HEADERS)
$(DIR_O)\LexInno.obj: ..\lexers\LexInno.cxx $(LEX_HEADERS)