home *** CD-ROM | disk | FTP | other *** search
- /* -----------------------------------------------------------------------------
-
- ScanLib ©1996 Dietmar Eilert
-
- GoldED syntax parser example library (uses a syntax cache). Dice:
-
- DMAKE
-
- -------------------------------------------------------------------------------
-
- */
-
- #include "defs.h"
-
- /// "Header stuff"
-
- // Buffer handles are allocated for each text buffer to keep track of ressources:
-
- struct BufferHandle {
-
- struct EditConfig *bh_EditConfig; // pointer to text data
- struct GlobalConfig *bh_GlobalConfig; // editor configuration
- struct SyntaxChunk *bh_SyntaxStack; // parser output
- struct RefreshRequest bh_RefreshRequest; // display refresh request
- };
-
- #define EMPTY_STACK ((struct SyntaxChunk *)~0) // empty stack flag
-
- ///
- /// "Prototype"
-
- // library functions
-
- Prototype LibCall struct ParserData *MountScanner(void);
- Prototype LibCall ULONG StartScanner(__A0 struct GlobalConfig *, __A1 struct EditConfig *, __D0 struct SyntaxChunk *);
- Prototype LibCall ULONG CloseScanner(__D0 ULONG);
- Prototype LibCall void FlushScanner(__D0 ULONG);
- Prototype LibCall void SetupScanner(__A0 struct GlobalConfig *);
- Prototype LibCall struct RefreshRequest *BriefScanner(__D0 ULONG, __A0 struct ScannerNotify *);
- Prototype LibCall struct SyntaxChunk *ParseLine (__D0 ULONG, __A0 struct LineNode *, __D1 ULONG);
- Prototype LibCall void UnparseLines(__A0 struct LineNode *, __D0 ULONG);
- Prototype LibCall void ParseSection(__D0 ULONG, __A0 struct LineNode *, __D1 ULONG);
-
- // private functions
-
- Prototype struct SyntaxChunk *ParseString(UBYTE *, UWORD, ULONG);
- Prototype struct SyntaxChunk *DupStack(struct SyntaxChunk *);
-
- ///
- /// "Library functions"
-
- /* ------------------------------- MountScanner --------------------------------
-
- Called by the editor before first usage of a scanner. Return a description of
- our abilities.
-
- */
-
- LibCall struct ParserData *
- MountScanner()
- {
- static UBYTE version[] = "$VER: Comments 2.2 (" __COMMODORE_DATE__ ")";
-
- static struct ParserData parserData;
-
- // syntax elements understood by parser
-
- static UBYTE *levelNames[] = {
-
- "Standard text",
- "C++ comment ('//...')",
- NULL
- };
-
- static UBYTE *example[] = {
-
- "/* Simple ANSI C example */ ",
- " ",
- "#include <defs.h> ",
- " ",
- "int ",
- "main(int argc, char **argv) ",
- "{ ",
- " // anybody at home ? ",
- " ",
- " puts(\"Hello world !\"); ",
- "} ",
-
- NULL
- };
-
- // color suggestions
-
- static ULONG levelColors[] = {
-
- MAKE_RGB4(0, 0, 0),
- MAKE_RGB4(15, 15, 0),
- };
-
- parserData.pd_Release = SCANLIBVERSION;
- parserData.pd_Version = 1;
- parserData.pd_Serial = 0;
- parserData.pd_Info = "Comments 2.2";
- parserData.pd_Levels = 2;
- parserData.pd_Names = levelNames;
- parserData.pd_Colors = levelColors;
- parserData.pd_Flags = SCPRF_SYNTAXCACHE;
- parserData.pd_Example = example;
-
- return(&parserData);
- }
-
-
- /* ------------------------------- StartScanner --------------------------------
-
- Called by the editor after a new text buffer has been created. We allocate a
- buffer to hold text-specific data. The buffer address is returned as handle.
-
- */
-
- LibCall ULONG
- StartScanner(__A0 struct GlobalConfig *globalConfigPtr, __A1 struct EditConfig *editConfigPtr, __D0 struct SyntaxChunk *syntaxStack)
- {
- struct BufferHandle *handle;
-
- if (handle = AllocVec(sizeof(struct BufferHandle), MEMF_PUBLIC | MEMF_CLEAR)) {
-
- handle->bh_GlobalConfig = globalConfigPtr;
- handle->bh_EditConfig = editConfigPtr;
- handle->bh_SyntaxStack = syntaxStack;
- }
-
- return((ULONG)handle);
- }
-
-
- /* ------------------------------- CloseScanner --------------------------------
-
- Called by the editor if a text buffer is about to be closed. Deallocate buffer
- specific 'global' data.
-
- */
-
- LibCall ULONG
- CloseScanner(__D0 ULONG scanID)
- {
- if (scanID) {
-
- struct BufferHandle *handle = (struct BufferHandle *)scanID;
-
- FreeVec(handle);
- }
-
- return(0);
- }
-
-
- /* ------------------------------- FlushScanner --------------------------------
-
- Called by the editor in low memory situations: we are supposed to free as much
- memory as possible.
-
- */
-
- LibCall void
- FlushScanner(__D0 ULONG scanID)
- {
- struct BufferHandle *handle;
- struct EditConfig *config;
- struct LineNode *lineNode;
-
- handle = (struct BufferHandle *)scanID;
- config = handle->bh_EditConfig;
-
- if (lineNode = config->TextNodes)
- UnparseLines(lineNode, config->Lines);
- }
-
-
- /* ------------------------------- SetupScanner --------------------------------
-
- Called by the editor if the user wants to change the scanner's configuration.
- We do not support user configuration (parserData.pd_Flags: SCPRF_CONFIGWIN flag
- unset).
-
- */
-
- LibCall void
- SetupScanner(__A0 globalConfigPtr)
- {
- ;
- }
-
-
- /* ------------------------------- BriefScanner --------------------------------
-
- Called to notify a context scanner if lines have been added, deleted or
- modified. We aren't a context scanner (parserData.pd_Flags: SCPRF_CONTEXT
- flag unset), so we won't ever have to request additional display requests:
- the editor's built-in refresh of damage regions is sufficient.
-
- */
-
- LibCall struct RefreshRequest *
- BriefScanner(__D0 ULONG scanID, __A0 struct ScannerNotify *notify)
- {
- return(NULL);
- }
-
-
- /* --------------------------------- ParseLine ---------------------------------
-
- Parse a line, build a syntax description
-
- */
-
- LibCall struct SyntaxChunk *
- ParseLine(__D0 ULONG scanID, __A0 struct LineNode *lineNode, __D1 ULONG line)
- {
- if (IS_FOLD(lineNode))
-
- return(NULL);
-
- else if (lineNode->Len) {
-
- // line not yet parsed ?
-
- if (lineNode->UserData == NULL) {
-
- struct SyntaxChunk *syntaxStack = ParseString(lineNode->Text, lineNode->Len, scanID);
-
- if (syntaxStack == EMPTY_STACK)
- lineNode->UserData = EMPTY_STACK;
- else
- lineNode->UserData = DupStack(syntaxStack);
- }
-
- if (lineNode->UserData == EMPTY_STACK)
- return((struct SyntaxChunk *)NULL);
- else
- return((struct SyntaxChunk *)lineNode->UserData);
- }
- else
- return(NULL);
- }
-
- /* -------------------------------- UnparseLines -------------------------------
-
- Called by the editor if lines are to be deleted. We are supposed to free
- private data attached to the lines.
-
- */
-
- LibCall void
- UnparseLines(__A0 struct LineNode *lineNode, __D0 ULONG lines)
- {
- while (lines--) {
-
- // free syntax cache
-
- if (lineNode->UserData) {
-
- if (lineNode->UserData != (APTR)EMPTY_STACK)
- FreeVec((APTR)lineNode->UserData);
-
- lineNode->UserData = NULL;
- }
-
- // free folded subblock
-
- if (IS_FOLD(lineNode)) {
-
- struct Fold *fold = (struct Fold *)lineNode->SpecialInfo;
-
- UnparseLines(fold->TextNodes, fold->Lines);
- }
-
- ++lineNode;
- }
- }
-
- /* -------------------------------- ParseSection -------------------------------
-
- Called by the editor if lines are to be displayed. The scanner is encouraged to
- preparse the lines.
-
- */
-
- LibCall void
- ParseSection(__D0 ULONG scanID, __A0 struct LineNode *lineNode, __D1 ULONG lines)
- {
- while (lines--) {
-
- // fold headers have to be ignored
-
- if (IS_FOLD(lineNode) == FALSE) {
-
- // line not yet parsed ?
-
- if (lineNode->Len)
- if (lineNode->UserData == NULL)
- lineNode->UserData = DupStack(ParseString(lineNode->Text, lineNode->Len, scanID));
- }
-
- ++lineNode;
- }
- }
-
- ///
- /// "private"
-
- /* -------------------------------- ParseString --------------------------------
-
- Parse a string, build a syntax description. This is a simple example only:
- C++-Comments (// ....) are highlighted. Return EMPTY_STACK in case there is
- nothing to highlight.
-
- */
-
- struct SyntaxChunk *
- ParseString(UBYTE *text, UWORD len, ULONG scanID)
- {
- if (len) {
-
- BOOL inString;
- UWORD indent;
-
- // leading spaces have to be ignored
-
- for (indent = 0; len && (*text == 32); ++indent, --len)
- ++text;
-
- // trailing spaces have to be ignored
-
- while (len && (text[len - 1] == 32))
- --len;
-
- // check whether line containes a C++comment
-
- for (inString = FALSE; len >= 2; ++text, ++indent, --len) {
-
- if (*text == 34)
-
- inString = !inString;
-
- else if (inString == FALSE) {
-
- if ((text[0] == '/') && (text[1] == '/')) {
-
- struct SyntaxChunk *syntaxStack = ((struct BufferHandle *)scanID)->bh_SyntaxStack;
-
- syntaxStack[0].sc_Level = 1;
- syntaxStack[0].sc_Start = indent;
- syntaxStack[0].sc_End = indent + len - 1;
-
- syntaxStack[1].sc_Start = FALSE;
- syntaxStack[1].sc_End = FALSE;
- syntaxStack[1].sc_Level = FALSE;
-
- return(syntaxStack);
- }
- }
- }
- }
-
- return(EMPTY_STACK);
- }
-
- /* --------------------------------- DupStack ----------------------------------
-
- Duplicate syntax stack (to be FreeVec'ed). Return NULL in case of failure.
-
- */
-
- struct SyntaxChunk *
- DupStack(syntaxStack)
-
- struct SyntaxChunk *syntaxStack;
- {
- if (syntaxStack && (syntaxStack != EMPTY_STACK)) {
-
- struct SyntaxChunk *chunk;
- UWORD elements;
-
- // determine stack size
-
- for (elements = 0, chunk = syntaxStack; chunk->sc_Level; ++chunk)
- ++elements;
-
- // create copy of syntax stack (to be attached to a text line by the caller)
-
- if (elements) {
-
- ULONG size = (++elements) * sizeof(struct SyntaxChunk);
-
- chunk = syntaxStack;
-
- if (syntaxStack = AllocVec(size, MEMF_PUBLIC))
- movmem(chunk, syntaxStack, size);
- }
- else
- syntaxStack = EMPTY_STACK;
- }
-
- return(syntaxStack);
- }
-
-
- ///
-