home *** CD-ROM | disk | FTP | other *** search
/ Amiga Times / AmigaTimes.iso / programme / GoldED / developer / examples / syntax / example_cached / funcs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-06  |  10.3 KB  |  410 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.  ScanLib ©1996 Dietmar Eilert
  4.  
  5.  GoldED syntax parser example library (uses a syntax cache). Dice:
  6.  
  7.  DMAKE
  8.  
  9.  -------------------------------------------------------------------------------
  10.  
  11. */
  12.  
  13. #include "defs.h"
  14.  
  15. /// "Header stuff"
  16.  
  17. // Buffer handles are allocated for each text buffer to keep track of ressources:
  18.  
  19. struct BufferHandle {
  20.  
  21.     struct EditConfig     *bh_EditConfig;            // pointer to text data
  22.     struct GlobalConfig   *bh_GlobalConfig;          // editor configuration
  23.     struct SyntaxChunk    *bh_SyntaxStack;           // parser output
  24.     struct RefreshRequest  bh_RefreshRequest;        // display refresh request
  25. };
  26.  
  27. #define EMPTY_STACK ((struct SyntaxChunk *)~0)       // empty stack flag
  28.  
  29. ///
  30. /// "Prototype"
  31.  
  32. // library functions
  33.  
  34. Prototype LibCall struct ParserData     *MountScanner(void);
  35. Prototype LibCall ULONG                  StartScanner(__A0 struct GlobalConfig *, __A1 struct EditConfig *, __D0 struct SyntaxChunk *);
  36. Prototype LibCall ULONG                  CloseScanner(__D0 ULONG);
  37. Prototype LibCall void                   FlushScanner(__D0 ULONG);
  38. Prototype LibCall void                   SetupScanner(__A0 struct GlobalConfig  *);
  39. Prototype LibCall struct RefreshRequest *BriefScanner(__D0 ULONG, __A0 struct ScannerNotify *);
  40. Prototype LibCall struct SyntaxChunk    *ParseLine   (__D0 ULONG, __A0 struct LineNode *, __D1 ULONG);
  41. Prototype LibCall void                   UnparseLines(__A0 struct LineNode *, __D0 ULONG);
  42. Prototype LibCall void                   ParseSection(__D0 ULONG, __A0 struct LineNode *, __D1 ULONG);
  43.  
  44. // private functions
  45.  
  46. Prototype struct SyntaxChunk *ParseString(UBYTE *, UWORD, ULONG);
  47. Prototype struct SyntaxChunk *DupStack(struct SyntaxChunk *);
  48.  
  49. ///
  50. /// "Library functions"
  51.  
  52. /* ------------------------------- MountScanner --------------------------------
  53.  
  54.  Called by the editor before first usage of a scanner. Return a description of
  55.  our abilities.
  56.  
  57. */
  58.  
  59. LibCall struct ParserData *
  60. MountScanner()
  61. {
  62.     static UBYTE version[] = "$VER: Comments 2.2 (" __COMMODORE_DATE__ ")";
  63.  
  64.     static struct ParserData parserData;
  65.  
  66.     // syntax elements understood by parser
  67.  
  68.     static UBYTE *levelNames[] = {
  69.  
  70.         "Standard text",
  71.         "C++ comment ('//...')",
  72.         NULL
  73.     };
  74.  
  75.     static UBYTE *example[] = {
  76.  
  77.         "/* Simple ANSI C example */    ",
  78.         "                               ",
  79.         "#include <defs.h>              ",
  80.         "                               ",
  81.         "int                            ",
  82.         "main(int argc, char **argv)    ",
  83.         "{                              ",
  84.         "   // anybody at home ?        ",
  85.         "                               ",
  86.         "   puts(\"Hello world !\");    ",
  87.         "}                              ",
  88.  
  89.         NULL
  90.     };
  91.  
  92.     // color suggestions
  93.  
  94.     static ULONG levelColors[] = {
  95.  
  96.         MAKE_RGB4(0,  0,  0),
  97.         MAKE_RGB4(15, 15, 0),
  98.     };
  99.  
  100.     parserData.pd_Release  = SCANLIBVERSION;
  101.     parserData.pd_Version  = 1;
  102.     parserData.pd_Serial   = 0;
  103.     parserData.pd_Info     = "Comments 2.2";
  104.     parserData.pd_Levels   = 2;
  105.     parserData.pd_Names    = levelNames;
  106.     parserData.pd_Colors   = levelColors;
  107.     parserData.pd_Flags    = SCPRF_SYNTAXCACHE;
  108.     parserData.pd_Example  = example;
  109.  
  110.     return(&parserData);
  111. }
  112.  
  113.  
  114. /* ------------------------------- StartScanner --------------------------------
  115.  
  116.  Called by the editor after a new text buffer has been created. We allocate a
  117.  buffer to hold text-specific data. The buffer address is returned as handle.
  118.  
  119. */
  120.  
  121. LibCall ULONG
  122. StartScanner(__A0 struct GlobalConfig *globalConfigPtr, __A1 struct EditConfig *editConfigPtr, __D0 struct SyntaxChunk *syntaxStack)
  123. {
  124.     struct BufferHandle *handle;
  125.  
  126.     if (handle = AllocVec(sizeof(struct BufferHandle), MEMF_PUBLIC | MEMF_CLEAR)) {
  127.  
  128.         handle->bh_GlobalConfig = globalConfigPtr;
  129.         handle->bh_EditConfig   = editConfigPtr;
  130.         handle->bh_SyntaxStack  = syntaxStack;
  131.     }
  132.  
  133.     return((ULONG)handle);
  134. }
  135.  
  136.  
  137. /* ------------------------------- CloseScanner --------------------------------
  138.  
  139.  Called by the editor if a text buffer is about to be closed. Deallocate buffer
  140.  specific 'global' data.
  141.  
  142. */
  143.  
  144. LibCall ULONG
  145. CloseScanner(__D0 ULONG scanID)
  146. {
  147.     if (scanID) {
  148.  
  149.         struct BufferHandle *handle = (struct BufferHandle *)scanID;
  150.  
  151.         FreeVec(handle);
  152.     }
  153.  
  154.     return(0);
  155. }
  156.  
  157.  
  158. /* ------------------------------- FlushScanner --------------------------------
  159.  
  160.  Called by the editor in low memory situations: we are supposed to free as much
  161.  memory as possible.
  162.  
  163. */
  164.  
  165. LibCall void
  166. FlushScanner(__D0 ULONG scanID)
  167. {
  168.     struct BufferHandle *handle;
  169.     struct EditConfig   *config;
  170.     struct LineNode     *lineNode;
  171.  
  172.     handle = (struct BufferHandle *)scanID;
  173.     config = handle->bh_EditConfig;
  174.  
  175.     if (lineNode = config->TextNodes)
  176.         UnparseLines(lineNode, config->Lines);
  177. }
  178.  
  179.  
  180. /* ------------------------------- SetupScanner --------------------------------
  181.  
  182.  Called by the editor if the user wants to change the scanner's configuration.
  183.  We do not support user configuration (parserData.pd_Flags: SCPRF_CONFIGWIN flag
  184.  unset).
  185.  
  186. */
  187.  
  188. LibCall void
  189. SetupScanner(__A0 globalConfigPtr)
  190. {
  191.     ;
  192. }
  193.  
  194.  
  195. /* ------------------------------- BriefScanner --------------------------------
  196.  
  197.  Called to notify a context scanner if lines have been added, deleted or
  198.  modified. We aren't a context scanner (parserData.pd_Flags: SCPRF_CONTEXT
  199.  flag unset), so we won't ever have to request additional display requests:
  200.  the editor's built-in refresh of damage regions is sufficient.
  201.  
  202. */
  203.  
  204. LibCall struct RefreshRequest *
  205. BriefScanner(__D0 ULONG scanID, __A0 struct ScannerNotify *notify)
  206. {
  207.     return(NULL);
  208. }
  209.  
  210.  
  211. /* --------------------------------- ParseLine ---------------------------------
  212.  
  213.  Parse a line, build a syntax description
  214.  
  215. */
  216.  
  217. LibCall struct SyntaxChunk *
  218. ParseLine(__D0 ULONG scanID, __A0 struct LineNode *lineNode, __D1 ULONG line)
  219. {
  220.     if (IS_FOLD(lineNode))
  221.  
  222.         return(NULL);
  223.  
  224.     else if (lineNode->Len) {
  225.  
  226.         // line not yet parsed ?
  227.  
  228.         if (lineNode->UserData == NULL) {
  229.  
  230.             struct SyntaxChunk *syntaxStack = ParseString(lineNode->Text, lineNode->Len, scanID);
  231.  
  232.             if (syntaxStack == EMPTY_STACK)
  233.                 lineNode->UserData = EMPTY_STACK;
  234.             else
  235.                 lineNode->UserData = DupStack(syntaxStack);
  236.         }
  237.  
  238.         if (lineNode->UserData == EMPTY_STACK)
  239.             return((struct SyntaxChunk *)NULL);
  240.         else
  241.             return((struct SyntaxChunk *)lineNode->UserData);
  242.     }
  243.     else
  244.         return(NULL);
  245. }
  246.  
  247. /* -------------------------------- UnparseLines -------------------------------
  248.  
  249.  Called by the editor if lines are to be deleted. We are supposed to free
  250.  private data attached to the lines.
  251.  
  252. */
  253.  
  254. LibCall void
  255. UnparseLines(__A0  struct LineNode *lineNode, __D0 ULONG lines)
  256. {
  257.     while (lines--) {
  258.  
  259.         // free syntax cache
  260.  
  261.         if (lineNode->UserData) {
  262.  
  263.             if (lineNode->UserData != (APTR)EMPTY_STACK)
  264.                 FreeVec((APTR)lineNode->UserData);
  265.  
  266.             lineNode->UserData = NULL;
  267.         }
  268.  
  269.         // free folded subblock
  270.  
  271.         if (IS_FOLD(lineNode)) {
  272.  
  273.             struct Fold *fold = (struct Fold *)lineNode->SpecialInfo;
  274.  
  275.             UnparseLines(fold->TextNodes, fold->Lines);
  276.         }
  277.  
  278.         ++lineNode;
  279.     }
  280. }
  281.  
  282. /* -------------------------------- ParseSection -------------------------------
  283.  
  284.  Called by the editor if lines are to be displayed. The scanner is encouraged to
  285.  preparse the lines.
  286.  
  287. */
  288.  
  289. LibCall void
  290. ParseSection(__D0 ULONG scanID, __A0  struct LineNode *lineNode, __D1 ULONG lines)
  291. {
  292.     while (lines--) {
  293.  
  294.         // fold headers have to be ignored
  295.  
  296.         if (IS_FOLD(lineNode) == FALSE) {
  297.  
  298.             // line not yet parsed ?
  299.  
  300.             if (lineNode->Len)
  301.                 if (lineNode->UserData == NULL)
  302.                     lineNode->UserData = DupStack(ParseString(lineNode->Text, lineNode->Len, scanID));
  303.         }
  304.  
  305.         ++lineNode;
  306.     }
  307. }
  308.  
  309. ///
  310. /// "private"
  311.  
  312. /* -------------------------------- ParseString --------------------------------
  313.  
  314.  Parse a string, build a syntax description. This is a simple example only:
  315.  C++-Comments (// ....) are highlighted. Return EMPTY_STACK in case there is
  316.  nothing to highlight.
  317.  
  318. */
  319.  
  320. struct SyntaxChunk *
  321. ParseString(UBYTE *text, UWORD len, ULONG scanID)
  322. {
  323.     if (len) {
  324.  
  325.         BOOL  inString;
  326.         UWORD indent;
  327.  
  328.         // leading spaces have to be ignored
  329.  
  330.         for (indent = 0; len && (*text == 32); ++indent, --len)
  331.             ++text;
  332.  
  333.         // trailing spaces have to be ignored
  334.  
  335.         while (len && (text[len - 1] == 32))
  336.             --len;
  337.  
  338.         // check whether line containes a C++comment
  339.  
  340.         for (inString = FALSE; len >= 2; ++text, ++indent, --len) {
  341.  
  342.             if (*text == 34)
  343.  
  344.                 inString = !inString;
  345.  
  346.             else if (inString == FALSE) {
  347.  
  348.                 if ((text[0] == '/') && (text[1] == '/')) {
  349.  
  350.                     struct SyntaxChunk *syntaxStack = ((struct BufferHandle *)scanID)->bh_SyntaxStack;
  351.  
  352.                     syntaxStack[0].sc_Level = 1;
  353.                     syntaxStack[0].sc_Start = indent;
  354.                     syntaxStack[0].sc_End   = indent + len - 1;
  355.  
  356.                     syntaxStack[1].sc_Start = FALSE;
  357.                     syntaxStack[1].sc_End   = FALSE;
  358.                     syntaxStack[1].sc_Level = FALSE;
  359.  
  360.                     return(syntaxStack);
  361.                 }
  362.             }
  363.         }
  364.     }
  365.  
  366.     return(EMPTY_STACK);
  367. }
  368.  
  369. /* --------------------------------- DupStack ----------------------------------
  370.  
  371.  Duplicate syntax stack (to be FreeVec'ed). Return NULL in case of failure.
  372.  
  373. */
  374.  
  375. struct SyntaxChunk *
  376. DupStack(syntaxStack)
  377.  
  378. struct SyntaxChunk *syntaxStack;
  379. {
  380.     if (syntaxStack && (syntaxStack != EMPTY_STACK)) {
  381.  
  382.         struct SyntaxChunk *chunk;
  383.         UWORD               elements;
  384.  
  385.         // determine stack size
  386.  
  387.         for (elements = 0, chunk = syntaxStack; chunk->sc_Level; ++chunk)
  388.             ++elements;
  389.  
  390.         // create copy of syntax stack (to be attached to a text line by the caller)
  391.  
  392.         if (elements) {
  393.  
  394.             ULONG size = (++elements) * sizeof(struct SyntaxChunk);
  395.  
  396.             chunk = syntaxStack;
  397.  
  398.             if (syntaxStack = AllocVec(size, MEMF_PUBLIC))
  399.                 movmem(chunk, syntaxStack, size);
  400.         }
  401.         else
  402.             syntaxStack = EMPTY_STACK;
  403.     }
  404.  
  405.     return(syntaxStack);
  406. }
  407.  
  408.  
  409. ///
  410.