]> git.sur5r.net Git - cc65/commitdiff
Added/finished .MID, .LEFT, .RIGHT
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 8 Jul 2000 14:01:43 +0000 (14:01 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 8 Jul 2000 14:01:43 +0000 (14:01 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@136 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ca65/macro.c
src/ca65/main.c
src/ca65/nexttok.c
src/ca65/nexttok.h
src/ca65/pseudo.c
src/ca65/scanner.c
src/ca65/scanner.h
src/ca65/toklist.c

index 67c6b7b9b934485dfa452169fed07d204b929243..d85fbcc905fd31a71e308982b915b56068805148 100644 (file)
@@ -290,6 +290,9 @@ void MacDef (unsigned Style)
 
     /* Define the macro */
     M = NewMacro (SVal, HashVal, Style);
+
+    /* Switch to raw token mode and skip the macro name */
+    EnterRawTokenMode ();
     NextTok ();
 
     /* If we have a DEFINE style macro, we may have parameters in braces,
@@ -371,7 +374,7 @@ void MacDef (unsigned Style)
            /* May not have end of file in a macro definition */
            if (Tok == TOK_EOF) {
                Error (ERR_ENDMACRO_EXPECTED);
-               return;
+               goto Done;
            }
        } else {
            /* Accept a newline or end of file for new style macros */
@@ -454,6 +457,10 @@ void MacDef (unsigned Style)
     if (Style == MAC_STYLE_CLASSIC) {
        NextTok ();
     }
+
+Done:
+    /* Switch out of raw token mode */
+    LeaveRawTokenMode ();
 }
 
 
@@ -650,7 +657,7 @@ static void StartExpDefine (Macro* M)
 
     /* A define style macro must be called with as many actual parameters
      * as there are formal ones. Get the parameter count.
-     */
+     */                                                 
     unsigned Count = M->ParamCount;
 
     /* Skip the current token */
index 46f7eba390809e25131962240e392e4830467efc..21d6a613eb91c77680819f487ab786c0e09608a4 100644 (file)
@@ -328,33 +328,31 @@ static void OneLine (void)
             * is no colon, it's an assignment.
             */
                    if (Tok == TOK_EQ) {
-               /* Skip the '=' */
-               NextTok ();
-               /* Define the symbol with the expression following the
-                * '='
-                */
-               SymDef (Ident, Expression (), 0);
-               /* Don't allow anything after a symbol definition */
-               Done = 1;
+               /* Skip the '=' */
+               NextTok ();
+               /* Define the symbol with the expression following the '=' */
+               SymDef (Ident, Expression (), 0);
+               /* Don't allow anything after a symbol definition */
+               Done = 1;
            } else {
-               /* Define a label */
-               SymDef (Ident, CurrentPC (), IsZPSeg ());
-               /* Skip the colon. If NoColonLabels is enabled, allow labels
-                * without a colon if there is no whitespace before the
-                * identifier.
-                */
-               if (Tok != TOK_COLON) {
-                   if (HadWS || !NoColonLabels) {
-                       Error (ERR_COLON_EXPECTED);
-                   }
-                   if (Tok == TOK_NAMESPACE) {
-                       /* Smart :: handling */
-                       NextTok ();
-                   }
-               } else {
+               /* Define a label */
+               SymDef (Ident, CurrentPC (), IsZPSeg ());
+               /* Skip the colon. If NoColonLabels is enabled, allow labels
+                * without a colon if there is no whitespace before the
+                * identifier.
+                */
+               if (Tok != TOK_COLON) {
+                   if (HadWS || !NoColonLabels) {
+                       Error (ERR_COLON_EXPECTED);
+                   }
+                   if (Tok == TOK_NAMESPACE) {
+                       /* Smart :: handling */
+                       NextTok ();
+                   }
+               } else {
                    /* Skip the colon */
-                   NextTok ();
-               }
+                   NextTok ();
+               }
            }
        }
     }
index 72c80708a22777dd6076c05ec94e8ce4c9be4326..9504e29280e3ab6cb70521b38a994bf2370a4278 100644 (file)
 
 
 
+/*****************************************************************************/
+/*                                          Data                                    */
+/*****************************************************************************/
+
+
+
+static unsigned RawMode = 0;           /* Raw token mode flag/counter */
+
+
+
 /*****************************************************************************/
 /*                                          Code                                    */
 /*****************************************************************************/
@@ -63,28 +73,28 @@ static TokList* CollectTokens (unsigned Start, unsigned Count)
     unsigned Parens  = 0;
     while (Parens != 0 || Tok != TOK_RPAREN) {
 
-       /* Check for end of line or end of input */
-       if (Tok == TOK_SEP || Tok == TOK_EOF) {
-           Error (ERR_UNEXPECTED_EOL);
-           return List;
-       }
+       /* Check for end of line or end of input */
+       if (Tok == TOK_SEP || Tok == TOK_EOF) {
+           Error (ERR_UNEXPECTED_EOL);
+           return List;
+       }
 
-       /* Collect tokens in the given range */
-       if (Current >= Start && Current < Start+Count) {
-           /* Add the current token to the list */
-           AddCurTok (List);
-       }
+       /* Collect tokens in the given range */
+       if (Current >= Start && Current < Start+Count) {
+           /* Add the current token to the list */
+           AddCurTok (List);
+       }
 
-       /* Check for and count parenthesii */
-       if (Tok == TOK_LPAREN) {
-           ++Parens;
-       } else if (Tok == TOK_RPAREN) {
-           --Parens;
-       }
+       /* Check for and count parenthesii */
+       if (Tok == TOK_LPAREN) {
+           ++Parens;
+       } else if (Tok == TOK_RPAREN) {
+           --Parens;
+       }
 
-       /* Get the next token */
-       ++Current;
-       NextTok ();
+       /* Get the next token */
+       ++Current;
+       NextTok ();
     }
 
     /* Eat the closing paren */
@@ -165,6 +175,47 @@ static void FuncConcat (void)
 
 
 
+static void FuncLeft (void)
+/* Handle the .LEFT function */
+{
+    long               Count;
+    TokList*   List;
+
+    /* Skip it */
+    NextTok ();
+
+    /* Left paren expected */
+    ConsumeLParen ();
+
+    /* Count argument */
+    Count = ConstExpression ();
+    if (Count < 0 || Count > 100) {
+       Error (ERR_RANGE);
+       Count = 1;
+    }
+    ConsumeComma ();
+
+    /* Read the token list */
+    List = CollectTokens (0, (unsigned) Count);
+
+    /* Since we want to insert the list before the now current token, we have
+     * to save the current token in some way and then skip it. To do this, we
+     * will add the current token at the end of the token list (so the list
+     * will never be empty), push the token list, and then skip the current
+     * token. This will replace the current token by the first token from the
+     * list (which will be the old current token in case the list was empty).
+     */
+    AddCurTok (List);
+
+    /* Insert it into the scanner feed */
+    PushTokList (List, ".LEFT");
+
+    /* Skip the current token */
+    NextTok ();
+}
+
+
+
 static void FuncMid (void)
 /* Handle the .MID function */
 {
@@ -181,7 +232,7 @@ static void FuncMid (void)
     /* Start argument */
     Start = ConstExpression ();
     if (Start < 0 || Start > 100) {
-       Error (ERR_RANGE);
+       Error (ERR_RANGE);
        Start = 0;
     }
     ConsumeComma ();
@@ -189,16 +240,84 @@ static void FuncMid (void)
     /* Count argument */
     Count = ConstExpression ();
     if (Count < 0 || Count > 100) {
-       Error (ERR_RANGE);
-       Count = 1;
+       Error (ERR_RANGE);
+       Count = 1;
     }
     ConsumeComma ();
 
     /* Read the token list */
     List = CollectTokens ((unsigned) Start, (unsigned) Count);
 
+    /* Since we want to insert the list before the now current token, we have
+     * to save the current token in some way and then skip it. To do this, we
+     * will add the current token at the end of the token list (so the list
+     * will never be empty), push the token list, and then skip the current
+     * token. This will replace the current token by the first token from the
+     * list (which will be the old current token in case the list was empty).
+     */
+    AddCurTok (List);
+
     /* Insert it into the scanner feed */
     PushTokList (List, ".MID");
+
+    /* Skip the current token */
+    NextTok ();
+}
+
+
+
+static void FuncRight (void)
+/* Handle the .RIGHT function */
+{
+    long               Count;
+    TokList*   List;
+
+    /* Skip it */
+    NextTok ();
+
+    /* Left paren expected */
+    ConsumeLParen ();
+
+    /* Count argument */
+    Count = ConstExpression ();
+    if (Count < 0 || Count > 100) {
+       Error (ERR_RANGE);
+       Count = 1;
+    }
+    ConsumeComma ();
+
+    /* Read the complete token list */
+    List = CollectTokens (0, 9999);
+
+    /* Delete tokens from the list until Count tokens are remaining */
+    while (List->Count > Count) {
+       /* Get the first node */
+       TokNode* T = List->Root;
+
+       /* Remove it from the list */
+       List->Root = List->Root->Next;
+
+       /* Free the node */
+       FreeTokNode (T);
+
+       /* Corrent the token counter */
+       List->Count--;
+    }
+
+    /* Since we want to insert the list before the now current token, we have
+     * to save the current token in some way and then skip it. To do this, we
+     * will add the current token at the end of the token list (so the list
+     * will never be empty), push the token list, and then skip the current
+     * token. This will replace the current token by the first token from the
+     * list (which will be the old current token in case the list was empty).
+     */
+    AddCurTok (List);
+
+    /* Insert it into the scanner feed */
+    PushTokList (List, ".RIGHT");
+
+    /* Skip the current token */
+    NextTok ();
 }
 
 
@@ -244,25 +363,37 @@ void NextTok (void)
     /* Get the next raw token */
     NextRawTok ();
 
-    /* Check for token handling functions */
-    switch (Tok) {
+    /* In raw mode, pass the token unchanged */
+    if (RawMode == 0) {
+
+       /* Execute token handling functions */
+       switch (Tok) {
 
-       case TOK_CONCAT:
-           FuncConcat ();
-           break;
+           case TOK_CONCAT:
+               FuncConcat ();
+               break;
 
-       case TOK_MID:
-           FuncMid ();
-           break;
+           case TOK_LEFT:
+               FuncLeft ();
+               break;
 
-       case TOK_STRING:
-           FuncString ();
-           break;
+           case TOK_MID:
+               FuncMid ();
+               break;
 
-       default:
-           /* Quiet down gcc */
-           break;
+           case TOK_RIGHT:
+               FuncRight ();
+               break;
 
+           case TOK_STRING:
+               FuncString ();
+               break;
+
+           default:
+               /* Quiet down gcc */
+               break;
+
+       }
     }
 }
 
@@ -321,7 +452,7 @@ void ConsumeComma (void)
 
 
 void SkipUntilSep (void)
-/* Skip tokens until we reach a line separator */
+/* Skip tokens until we reach a line separator or end of file */
 {
     while (Tok != TOK_SEP && Tok != TOK_EOF) {
        NextTok ();
@@ -330,3 +461,25 @@ void SkipUntilSep (void)
 
 
 
+void EnterRawTokenMode (void)
+/* Enter raw token mode. In raw mode, token handling functions are not
+ * executed, but the function tokens are passed untouched to the upper
+ * layer. Raw token mode is used when storing macro tokens for later
+ * use.
+ * Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
+ */
+{
+    ++RawMode;
+}
+
+
+
+void LeaveRawTokenMode (void)
+/* Leave raw token mode. */
+{
+    PRECONDITION (RawMode > 0);
+    --RawMode;
+}
+
+
+
index bc63b699e7a6413f01b0240176e063d4d4240656..cb38da7bc360daf0c8f3b94d3e8f095fee53c3bc 100644 (file)
@@ -67,7 +67,18 @@ void ConsumeComma (void);
 /* Consume a comma */
 
 void SkipUntilSep (void);
-/* Skip tokens until we reach a line separator */
+/* Skip tokens until we reach a line separator or end of file */
+
+void EnterRawTokenMode (void);
+/* Enter raw token mode. In raw mode, token handling functions are not
+ * executed, but the function tokens are passed untouched to the upper
+ * layer. Raw token mode is used when storing macro tokens for later
+ * use.
+ * Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested.
+ */
+
+void LeaveRawTokenMode (void);
+/* Leave raw token mode. */
 
 
 
index c00d75a9ccaf6854efe8939bd6d2ca929fd1e95c..ea222968f0dd7f9f21514a5bd909a15dde9d3db2 100644 (file)
@@ -75,6 +75,16 @@ static char Keyword [sizeof (SVal)+1] = ".";
 
 
 static void DoUnexpected (void);
+/* Got an unexpected keyword */
+
+static void DoInvalid (void);
+/* Handle a token that is invalid here, since it should have been handled on
+ * a much lower level of the expression hierarchy. Getting this sort of token
+ * means that the lower level code has bugs.
+ * This function differs to DoUnexpected in that the latter may be triggered
+ * by the user by using keywords in the wrong location. DoUnexpected is not
+ * an error in the assembler itself, while DoInvalid is.
+ */
 
 
 
@@ -696,6 +706,20 @@ static void DoInclude (void)
 
 
 
+static void DoInvalid (void)
+/* Handle a token that is invalid here, since it should have been handled on
+ * a much lower level of the expression hierarchy. Getting this sort of token
+ * means that the lower level code has bugs.
+ * This function differs to DoUnexpected in that the latter may be triggered
+ * by the user by using keywords in the wrong location. DoUnexpected is not
+ * an error in the assembler itself, while DoInvalid is.
+ */
+{
+    Internal ("Unexpected token: %s", Keyword);
+}
+
+
+
 static void DoLineCont (void)
 /* Switch the use of line continuations */
 {
@@ -788,16 +812,6 @@ static void DoMacro (void)
 
 
 
-static void DoMid (void)
-/* Handle .MID - this should never happen, since the keyword is actually
- * handled on a much lower level of the expression hierarchy.
- */
-{
-    Internal ("Unexpected token: .MID");
-}
-
-
-
 static void DoNull (void)
 /* Switch to the NULL segment */
 {
@@ -1121,6 +1135,7 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoImportZP      },
     { ccNone,          DoIncBin        },
     { ccNone,          DoInclude       },
+    { ccNone,          DoInvalid       },      /* .LEFT */
     { ccNone,          DoLineCont      },
     { ccNone,          DoList          },
     { ccNone,                  DoListBytes     },
@@ -1129,7 +1144,7 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoMacPack       },
     { ccNone,          DoMacro         },
     { ccNone,                  DoUnexpected    },      /* .MATCH */
-    { ccNone,                  DoMid           },
+    { ccNone,                  DoInvalid       },      /* .MID */
     { ccNone,          DoNull          },
     { ccNone,          DoOrg           },
     { ccNone,          DoOut           },
@@ -1143,6 +1158,7 @@ static CtrlDesc CtrlCmdTab [] = {
     { ccNone,          DoReloc         },
     { ccNone,          DoRepeat        },
     { ccNone,          DoRes           },
+    { ccNone,          DoInvalid       },      /* .RIGHT */
     { ccNone,          DoROData        },
     { ccNone,          DoSegment       },
     { ccNone,          DoSmart         },
index 357144aa140b3ce392565b41959ec3036bc5a6ad..c737f6c6fa08c7c843451aa9e09025a71a5b75e1 100644 (file)
@@ -184,6 +184,7 @@ struct DotKeyword {
     { "IMPORTZP",      TOK_IMPORTZP    },
     { "INCBIN",                TOK_INCBIN      },
     { "INCLUDE",       TOK_INCLUDE     },
+    { "LEFT",          TOK_LEFT        },
     { "LINECONT",      TOK_LINECONT    },
     { "LIST",          TOK_LIST        },
     { "LISTBYTES",     TOK_LISTBYTES   },
@@ -212,6 +213,7 @@ struct DotKeyword {
     { "RELOC",         TOK_RELOC       },
     { "REPEAT",                TOK_REPEAT      },
     { "RES",           TOK_RES         },
+    { "RIGHT",         TOK_RIGHT       },
     { "RODATA",                TOK_RODATA      },
     { "SEGMENT",       TOK_SEGMENT     },
     { "SHL",           TOK_SHL         },
index f28e30d47d99b7c988f08c0c0771a97f669673b4..dea58299424fdd5cb9e06a2d4ab651910ec631b4 100644 (file)
@@ -161,6 +161,7 @@ enum Token {
     TOK_IMPORTZP,
     TOK_INCBIN,
     TOK_INCLUDE,
+    TOK_LEFT,
     TOK_LINECONT,
     TOK_LIST,
     TOK_LISTBYTES,
@@ -182,7 +183,8 @@ enum Token {
     TOK_REFERENCED,
     TOK_RELOC,
     TOK_REPEAT,
-    TOK_RES,
+    TOK_RES, 
+    TOK_RIGHT,
     TOK_RODATA,
     TOK_SEGMENT,
     TOK_SMART,
index fc4eec608ad28915e7caadbad9aaf19ccf4af7f1..ab93a6766a55e743e1349a8888c0694a333ae858 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "../common/xmalloc.h"
 
+#include "error.h"
 #include "istack.h"
 #include "scanner.h"
 #include "toklist.h"
@@ -191,9 +192,15 @@ static int ReplayTokList (void* List)
     /* 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);
 
+    /* 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.
      */