]> git.sur5r.net Git - cc65/blobdiff - src/ca65/toklist.c
Finished implemenation of commands to delete macros. Added the new commands to
[cc65] / src / ca65 / toklist.c
index dc2712d391c5c67a512c26b5373d51a29fccf21b..44fbd77427953d6a31be8bf209de1ecf772fd435 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998     Ullrich von Bassewitz                                        */
-/*              Wacholderweg 14                                              */
-/*              D-70597 Stuttgart                                            */
-/* EMail:       uz@musoftware.de                                             */
+/* (C) 1998-2011, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 #include <string.h>
 
-#include "mem.h"
+/* common */
+#include "check.h"
+#include "xmalloc.h"
+
+/* ca65 */
+#include "error.h"
+#include "istack.h"
+#include "lineinfo.h"
+#include "nexttok.h"
 #include "scanner.h"
 #include "toklist.h"
 
 TokNode* NewTokNode (void)
 /* Create and return a token node with the current token value */
 {
-    TokNode* T;
 
     /* Allocate memory */
-    unsigned Len = TokHasSVal (Tok)? strlen (SVal) : 0;
-    T = Xmalloc (sizeof (TokNode) + Len);
+    TokNode* N = xmalloc (sizeof (TokNode));
 
     /* Initialize the token contents */
-    T->Next    = 0;
-    T->Tok     = Tok;
-    T->WS      = WS;
-    T->IVal    = IVal;
-    memcpy (T->SVal, SVal, Len);
-    T->SVal [Len] = '\0';
+    N->Next     = 0;
+    SB_Init (&N->T.SVal);
+    CopyToken (&N->T, &CurTok);
 
     /* Return the node */
-    return T;
+    return N;
 }
 
 
 
-void FreeTokNode (TokNode* T)
+void FreeTokNode (TokNode* N)
 /* Free the given token node */
 {
-    Xfree (T);
+    SB_Done (&N->T.SVal);
+    xfree (N);
 }
 
 
 
-void TokSet (TokNode* T)
-/* Set the scanner token from the given token node */
+void TokSet (TokNode* N, unsigned LineInfoSlot)
+/* Set the scanner token from the given token node. The given line info slot
+ * is used to store the position of the token fed into the scanner.
+ */
 {
     /* Set the values */
-    Tok  = T->Tok;
-    WS   = T->WS;
-    IVal = T->IVal;
-    strcpy (SVal, T->SVal);
+    CopyToken (&CurTok, &N->T);
+    SB_Terminate (&CurTok.SVal);
+
+    /* Set the position */
+    GenLineInfo (LineInfoSlot, &CurTok.Pos);
 }
 
 
 
-enum TC TokCmp (const TokNode* T)
+enum TC TokCmp (const TokNode* N)
 /* Compare the token given as parameter against the current token */
 {
-    if (T->Tok != Tok) {
+    if (N->T.Tok != CurTok.Tok) {
        /* Different token */
        return tcDifferent;
     }
 
     /* If the token has string attribute, check it */
-    if (TokHasSVal (T->Tok)) {
-       if (strcmp  (T->SVal, SVal) != 0) {
+    if (TokHasSVal (N->T.Tok)) {
+               if (SB_Compare (&CurTok.SVal, &N->T.SVal) != 0) {
            return tcSameToken;
        }
-    } else if (TokHasIVal (T->Tok)) {
-       if (T->IVal != IVal) {
+    } else if (TokHasIVal (N->T.Tok)) {
+       if (N->T.IVal != CurTok.IVal) {
            return tcSameToken;
        }
     }
@@ -122,8 +129,11 @@ void InitTokList (TokList* T)
     T->Next    = 0;
     T->Root    = 0;
     T->Last    = 0;
-    T->Repeat  = 1;
+    T->RepCount        = 0;
+    T->RepMax  = 1;
     T->Count   = 0;
+    T->Check   = 0;
+    T->Data    = 0;
 }
 
 
@@ -132,7 +142,7 @@ TokList* NewTokList (void)
 /* Create a new, empty token list */
 {
     /* Allocate memory for the list structure */
-    TokList* T = Xmalloc (sizeof (TokList));
+    TokList* T = xmalloc (sizeof (TokList));
 
     /* Initialize the fields */
     InitTokList (T);
@@ -154,8 +164,29 @@ void FreeTokList (TokList* List)
        FreeTokNode (Tmp);
     }
 
+    /* If we have associated data, free it */
+    if (List->Data) {
+       xfree (List->Data);
+    }
+
     /* Free the list structure itself */
-    Xfree (List);
+    xfree (List);
+}
+
+
+
+enum token_t GetTokListTerm (enum token_t Term)
+/* Determine if the following token list is enclosed in curly braces. This is
+ * the case if the next token is the opening brace. If so, skip it and return
+ * a closing brace, otherwise return Term.
+ */
+{
+    if (CurTok.Tok == TOK_LCURLY) {
+        NextTok ();
+        return TOK_RCURLY;
+    } else {
+        return Term;
+    }
 }
 
 
@@ -168,9 +199,9 @@ void AddCurTok (TokList* List)
 
     /* Insert the node into the list */
     if (List->Root == 0) {
-       List->Root = T;
+       List->Root = T;
     } else {
-       List->Last->Next = T;
+       List->Last->Next = T;
     }
     List->Last = T;
 
@@ -180,6 +211,69 @@ void AddCurTok (TokList* List)
 
 
 
+static int ReplayTokList (void* List)
+/* Function that gets the next token from a token list and sets it. This
+ * function may be used together with the PushInput function from the istack
+ * module.
+ */
+{
+    /* Cast the generic pointer to an actual list */
+    TokList* L = List;
+
+    /* Last may never be a NULL pointer, otherwise there's a bug in the code */
+    CHECK (L->Last != 0);
+
+    /* Set the next token from the list */
+    TokSet (L->Last, LI_SLOT_ASM);
+
+    /* If a check function is defined, call it, so it may look at the token
+     * just set and changed it as apropriate.
+     */
+    if (L->Check) {
+       L->Check (L);
+    }
+
+    /* Set the pointer to the next token */
+    L->Last = L->Last->Next;
+
+    /* If this was the last token, decrement the repeat counter. If it goes
+     * zero, delete the list and remove the function from the stack.
+     */
+    if (L->Last == 0) {
+       if (++L->RepCount >= L->RepMax) {
+           /* Done with this list */
+           FreeTokList (L);
+           PopInput ();
+       } else {
+           /* Replay one more time */
+           L->Last = L->Root;
+       }
+    }
+
+    /* We have a token */
+    return 1;
+}
+
+
+
+void PushTokList (TokList* List, const char* Desc)
+/* Push a token list to be used as input for InputFromStack. This includes
+ * several initializations needed in the token list structure, so don't use
+ * PushInput directly.
+ */
+{
+    /* If the list is empty, just delete it and bail out */
+    if (List->Count == 0) {
+       FreeTokList (List);
+       return;
+    }
+
+    /* Reset the last pointer to the first element */
+    List->Last = List->Root;
+
+    /* Insert the list specifying our input function */
+    PushInput (ReplayTokList, List, Desc);
+}