diff options
| -rw-r--r-- | doc/ScintillaHistory.html | 5 | ||||
| -rw-r--r-- | include/SciLexer.h | 14 | ||||
| -rw-r--r-- | include/Scintilla.iface | 16 | ||||
| -rw-r--r-- | lexers/LexHex.cxx | 360 | ||||
| -rw-r--r-- | src/Catalogue.cxx | 1 | ||||
| -rw-r--r-- | win32/scintilla.mak | 3 | 
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) | 
