]> git.sur5r.net Git - cc65/blobdiff - src/ca65/nexttok.c
Fix bug #182
[cc65] / src / ca65 / nexttok.c
index cb76bdb18530d4d5cbebb3b34d0fe9e074670653..1521ed0c25b4e094d1c511e34a3058872d5da3c8 100644 (file)
@@ -1,12 +1,12 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                nexttok.c                                 */
+/*                                 nexttok.c                                 */
 /*                                                                           */
-/*             Get next token and handle token level functions              */
+/*              Get next token and handle token level functions              */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2009, Ullrich von Bassewitz                                      */
+/* (C) 2000-2011, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -42,6 +42,7 @@
 #include "strbuf.h"
 
 /* ca65 */
+#include "condasm.h"
 #include "error.h"
 #include "expr.h"
 #include "global.h"
 
 
 /*****************************************************************************/
-/*                                          Data                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
 
-static unsigned RawMode = 0;           /* Raw token mode flag/counter */
+static unsigned RawMode = 0;            /* Raw token mode flag/counter */
 
 
 
@@ -69,11 +70,11 @@ static unsigned RawMode = 0;                /* Raw token mode flag/counter */
 
 static int LookAtStrCon (void)
 /* Make sure the next token is a string constant. If not, print an error
- * messages skip the remainder of the line and return false. Otherwise return
- * true.
- */
+** messages skip the remainder of the line and return false. Otherwise return
+** true.
+*/
 {
-    if (Tok != TOK_STRCON) {
+    if (CurTok.Tok != TOK_STRCON) {
         Error ("String constant expected");
         SkipUntilSep ();
         return 0;
@@ -85,44 +86,44 @@ static int LookAtStrCon (void)
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
 
 static TokList* CollectTokens (unsigned Start, unsigned Count)
 /* Read a list of tokens that is optionally enclosed in curly braces and
- * terminated by a right paren. For all tokens starting at the one with index
- * Start, and ending at (Start+Count-1), place them into a token list, and
- * return this token list.
- */
+** terminated by a right paren. For all tokens starting at the one with index
+** Start, and ending at (Start+Count-1), place them into a token list, and
+** return this token list.
+*/
 {
 
     /* Create the token list */
     TokList* List = NewTokList ();
 
     /* Determine if the list is enclosed in curly braces. */
-    Token Term = GetTokListTerm (TOK_RPAREN);
+    token_t Term = GetTokListTerm (TOK_RPAREN);
 
     /* Read the token list */
     unsigned Current = 0;
-    while (Tok != Term) {
-
-       /* Check for end of line or end of input */
-       if (TokIsSep (Tok)) {
-           Error ("Unexpected end of line");
-           return List;
-       }
-
-       /* Collect tokens in the given range */
-       if (Current >= Start && Current < Start+Count) {
-           /* Add the current token to the list */
-           AddCurTok (List);
-       }
-
-       /* Get the next token */
-       ++Current;
-       NextTok ();
+    while (CurTok.Tok != Term) {
+
+        /* Check for end of line or end of input */
+        if (TokIsSep (CurTok.Tok)) {
+            Error ("Unexpected end of line");
+            return List;
+        }
+
+        /* Collect tokens in the given range */
+        if (Current >= Start && Current < Start+Count) {
+            /* Add the current token to the list */
+            AddCurTok (List);
+        }
+
+        /* Get the next token */
+        ++Current;
+        NextTok ();
     }
 
     /* Eat the terminator token */
@@ -153,35 +154,36 @@ static void FuncConcat (void)
     /* Concatenate any number of strings */
     while (1) {
 
-       /* Next token must be a string */
+        /* Next token must be a string */
         if (!LookAtStrCon ()) {
             SB_Done (&Buf);
-           return;
-       }
+            return;
+        }
 
         /* Append the string */
-        SB_Append (&Buf, &SVal);
-
-       /* Skip the string token */
-       NextTok ();
-
-       /* Comma means another argument */
-       if (Tok == TOK_COMMA) {
-           NextTok ();
-       } else {
-           /* Done */
-           break;
-       }
+        SB_Append (&Buf, &CurTok.SVal);
+
+        /* Skip the string token */
+        NextTok ();
+
+        /* Comma means another argument */
+        if (CurTok.Tok == TOK_COMMA) {
+            NextTok ();
+        } else {
+            /* Done */
+            break;
+        }
     }
 
     /* We expect a closing parenthesis, but will not skip it but replace it
-     * by the string token just created.
-     */
-    if (Tok != TOK_RPAREN) {
-       Error ("`)' expected");
+    ** by the string token just created.
+    */
+    if (CurTok.Tok != TOK_RPAREN) {
+        Error ("`)' expected");
     } else {
-       Tok = TOK_STRCON;
-       SB_Copy (&SVal, &Buf);
+        CurTok.Tok = TOK_STRCON;
+        SB_Copy (&CurTok.SVal, &Buf);
+        SB_Terminate (&CurTok.SVal);
     }
 
     /* Free the string buffer */
@@ -203,7 +205,7 @@ static void FuncIdent (void)
 /* Handle the .IDENT function */
 {
     StrBuf    Buf = STATIC_STRBUF_INITIALIZER;
-    Token     Id;
+    token_t   Id;
     unsigned  I;
 
     /* Skip it */
@@ -218,25 +220,25 @@ static void FuncIdent (void)
     }
 
     /* Check that the string contains a valid identifier. While doing so,
-     * determine if it is a cheap local, or global one.
-     */
-    SB_Reset (&SVal);
+    ** determine if it is a cheap local, or global one.
+    */
+    SB_Reset (&CurTok.SVal);
 
     /* Check for a cheap local symbol */
-    if (SB_Peek (&SVal) == LocalStart) {
-        SB_Skip (&SVal);
+    if (SB_Peek (&CurTok.SVal) == LocalStart) {
+        SB_Skip (&CurTok.SVal);
         Id = TOK_LOCAL_IDENT;
     } else {
         Id = TOK_IDENT;
     }
 
     /* Next character must be a valid identifier start */
-    if (!IsIdStart (SB_Get (&SVal))) {
+    if (!IsIdStart (SB_Get (&CurTok.SVal))) {
         NoIdent ();
         return;
     }
-    for (I = SB_GetIndex (&SVal); I < SB_GetLen (&SVal); ++I) {
-        if (!IsIdChar (SB_AtUnchecked (&SVal, I))) {
+    for (I = SB_GetIndex (&CurTok.SVal); I < SB_GetLen (&CurTok.SVal); ++I) {
+        if (!IsIdChar (SB_AtUnchecked (&CurTok.SVal, I))) {
             NoIdent ();
             return;
         }
@@ -246,15 +248,16 @@ static void FuncIdent (void)
     }
 
     /* If anything is ok, save and skip the string. Check that the next token
-     * is a right paren, then replace the token by an identifier token.
-     */
-    SB_Copy (&Buf, &SVal);
+    ** is a right paren, then replace the token by an identifier token.
+    */
+    SB_Copy (&Buf, &CurTok.SVal);
     NextTok ();
-    if (Tok != TOK_RPAREN) {
-       Error ("`)' expected");
+    if (CurTok.Tok != TOK_RPAREN) {
+        Error ("`)' expected");
     } else {
-        Tok = Id;
-        SB_Copy (&SVal, &Buf);
+        CurTok.Tok = Id;
+        SB_Copy (&CurTok.SVal, &Buf);
+        SB_Terminate (&CurTok.SVal);
     }
 
     /* Free buffer memory */
@@ -266,8 +269,8 @@ static void FuncIdent (void)
 static void FuncLeft (void)
 /* Handle the .LEFT function */
 {
-    long               Count;
-    TokList*   List;
+    long        Count;
+    TokList*    List;
 
     /* Skip it */
     NextTok ();
@@ -278,7 +281,7 @@ static void FuncLeft (void)
     /* Count argument. Correct negative counts to zero. */
     Count = ConstExpression ();
     if (Count < 0) {
-       Count = 1;
+        Count = 0;
     }
     ConsumeComma ();
 
@@ -286,12 +289,12 @@ static void FuncLeft (void)
     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).
-     */
+    ** 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 */
@@ -306,9 +309,9 @@ static void FuncLeft (void)
 static void FuncMid (void)
 /* Handle the .MID function */
 {
-    long       Start;
-    long               Count;
-    TokList*   List;
+    long        Start;
+    long        Count;
+    TokList*    List;
 
     /* Skip it */
     NextTok ();
@@ -317,20 +320,20 @@ static void FuncMid (void)
     ConsumeLParen ();
 
     /* Start argument. Since the start argument can get negative with
-     * expressions like ".tcount(arg)-2", we correct it to zero silently.
-     */
+    ** expressions like ".tcount(arg)-2", we correct it to zero silently.
+    */
     Start = ConstExpression ();
     if (Start < 0 || Start > 100) {
-       Start = 0;
+        Start = 0;
     }
     ConsumeComma ();
 
     /* Count argument. Similar as above, we will accept negative counts and
-     * correct them to zero silently.
-     */
+    ** correct them to zero silently.
+    */
     Count = ConstExpression ();
     if (Count < 0) {
-       Count = 0;
+        Count = 0;
     }
     ConsumeComma ();
 
@@ -338,12 +341,12 @@ static void FuncMid (void)
     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).
-     */
+    ** 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 */
@@ -358,8 +361,8 @@ static void FuncMid (void)
 static void FuncRight (void)
 /* Handle the .RIGHT function */
 {
-    long               Count;
-    TokList*   List;
+    long        Count;
+    TokList*    List;
 
     /* Skip it */
     NextTok ();
@@ -370,7 +373,7 @@ static void FuncRight (void)
     /* Count argument. Correct negative counts to zero. */
     Count = ConstExpression ();
     if (Count < 0) {
-       Count = 0;
+        Count = 0;
     }
     ConsumeComma ();
 
@@ -379,26 +382,26 @@ static void FuncRight (void)
 
     /* Delete tokens from the list until Count tokens are remaining */
     while (List->Count > (unsigned) Count) {
-       /* Get the first node */
-       TokNode* T = List->Root;
+        /* Get the first node */
+        TokNode* T = List->Root;
 
-       /* Remove it from the list */
-       List->Root = List->Root->Next;
+        /* Remove it from the list */
+        List->Root = List->Root->Next;
 
-       /* Free the node */
-       FreeTokNode (T);
+        /* Free the node */
+        FreeTokNode (T);
 
-       /* Corrent the token counter */
-       List->Count--;
+        /* 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).
-     */
+    ** 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 */
@@ -442,7 +445,7 @@ static void FuncSPrintF (void)
     if (!LookAtStrCon ()) {
         return;
     }
-    SB_Copy (&Format, &SVal);
+    SB_Copy (&Format, &CurTok.SVal);
     NextTok ();
 
     /* Walk over the format string, generating the function result in R */
@@ -471,15 +474,15 @@ static void FuncSPrintF (void)
             break;
         }
 
-        /* Since a format specifier follows, we do expect anotehr argument for
-         * the .sprintf function.
-         */
+        /* Since a format specifier follows, we do expect another argument for
+        ** the .sprintf function.
+        */
         ConsumeComma ();
 
         /* We will copy the format spec into F1 checking for the things we
-         * support, and later use xsprintf to do the actual formatting. This
-         * is easier than adding another printf implementation...
-         */
+        ** support, and later use xsprintf to do the actual formatting. This
+        ** is easier than adding another printf implementation...
+        */
         SB_Clear (&F1);
         SB_AppendChar (&F1, '%');
 
@@ -519,8 +522,8 @@ static void FuncSPrintF (void)
             case 'X':
             case 'x':
                 /* Our ints are actually longs, so we use the 'l' modifier when
-                 * calling xsprintf later. Terminate the format string.
-                 */
+                ** calling xsprintf later. Terminate the format string.
+                */
                 SB_AppendChar (&F1, 'l');
                 SB_AppendChar (&F1, SB_Get (&Format));
                 SB_Terminate (&F1);
@@ -544,11 +547,11 @@ static void FuncSPrintF (void)
                 /* The argument must be a string constant */
                 if (!LookAtStrCon ()) {
                     /* Make it one */
-                    SB_CopyStr (&SVal, "**undefined**");
+                    SB_CopyStr (&CurTok.SVal, "**undefined**");
                 }
 
                 /* Format this argument according to the spec */
-                SB_Printf (&R1, SB_GetConstBuf (&F1), SVal);
+                SB_Printf (&R1, SB_GetConstBuf (&F1), SB_GetConstBuf (&CurTok.SVal));
 
                 /* Skip the string constant */
                 NextTok ();
@@ -573,8 +576,8 @@ static void FuncSPrintF (void)
                 }
 
                 /* Format this argument according to the spec. Be sure to pass
-                 * an int as the char value.
-                 */
+                ** an int as the char value.
+                */
                 SB_Printf (&R1, SB_GetConstBuf (&F1), (int) IVal);
 
                 /* Append the formatted argument to the result */
@@ -594,13 +597,14 @@ static void FuncSPrintF (void)
     SB_Terminate (&R);
 
     /* We expect a closing parenthesis, but will not skip it but replace it
-     * by the string token just created.
-     */
-    if (Tok != TOK_RPAREN) {
-       Error ("`)' expected");
+    ** by the string token just created.
+    */
+    if (CurTok.Tok != TOK_RPAREN) {
+        Error ("`)' expected");
     } else {
-       Tok = TOK_STRCON;
-        SB_Copy (&SVal, &R);
+        CurTok.Tok = TOK_STRCON;
+        SB_Copy (&CurTok.SVal, &R);
+        SB_Terminate (&CurTok.SVal);
     }
 
 
@@ -625,24 +629,42 @@ static void FuncString (void)
     ConsumeLParen ();
 
     /* Accept identifiers or numeric expressions */
-    if (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT) {
-       /* Save the identifier, then skip it */
-               SB_Copy (&Buf, &SVal);
-       NextTok ();
+    if (CurTok.Tok == TOK_LOCAL_IDENT) {
+        /* Save the identifier, then skip it */
+        SB_Copy (&Buf, &CurTok.SVal);
+        NextTok ();
+    } else if (CurTok.Tok == TOK_NAMESPACE || CurTok.Tok == TOK_IDENT) {
+
+        /* Parse a fully qualified symbol name. We cannot use
+        ** ParseScopedSymName here since the name may be invalid.
+        */
+        int NameSpace;
+        do {
+            NameSpace = (CurTok.Tok == TOK_NAMESPACE);
+            if (NameSpace) {
+                SB_AppendStr (&Buf, "::");
+            } else {
+                SB_Append (&Buf, &CurTok.SVal);
+            }
+            NextTok ();
+        } while ((NameSpace != 0 && CurTok.Tok == TOK_IDENT) ||
+                 (NameSpace == 0 && CurTok.Tok == TOK_NAMESPACE));
+
     } else {
-       /* Numeric expression */
-       long Val = ConstExpression ();
-               SB_Printf (&Buf, "%ld", Val);
+        /* Numeric expression */
+        long Val = ConstExpression ();
+        SB_Printf (&Buf, "%ld", Val);
     }
 
     /* We expect a closing parenthesis, but will not skip it but replace it
-     * by the string token just created.
-     */
-    if (Tok != TOK_RPAREN) {
-       Error ("`)' expected");
+    ** by the string token just created.
+    */
+    if (CurTok.Tok != TOK_RPAREN) {
+        Error ("`)' expected");
     } else {
-       Tok = TOK_STRCON;
-       SB_Copy (&SVal, &Buf);
+        CurTok.Tok = TOK_STRCON;
+        SB_Copy (&CurTok.SVal, &Buf);
+        SB_Terminate (&CurTok.SVal);
     }
 
     /* Free string memory */
@@ -657,57 +679,59 @@ void NextTok (void)
     /* Get the next raw token */
     NextRawTok ();
 
-    /* In raw mode, pass the token unchanged */
-    if (RawMode == 0) {
+    /* In raw mode, or when output is suppressed via conditional assembly,
+    ** pass the token unchanged.
+    */
+    if (RawMode == 0 && IfCond) {
 
-       /* Execute token handling functions */
-       switch (Tok) {
+        /* Execute token handling functions */
+        switch (CurTok.Tok) {
 
-           case TOK_CONCAT:
-               FuncConcat ();
-               break;
+            case TOK_CONCAT:
+                FuncConcat ();
+                break;
 
-           case TOK_LEFT:
-               FuncLeft ();
-               break;
+            case TOK_LEFT:
+                FuncLeft ();
+                break;
 
             case TOK_MAKEIDENT:
                 FuncIdent ();
                 break;
 
-           case TOK_MID:
-               FuncMid ();
-               break;
+            case TOK_MID:
+                FuncMid ();
+                break;
 
-           case TOK_RIGHT:
-               FuncRight ();
-               break;
+            case TOK_RIGHT:
+                FuncRight ();
+                break;
 
             case TOK_SPRINTF:
                 FuncSPrintF ();
                 break;
 
-           case TOK_STRING:
-               FuncString ();
-               break;
+            case TOK_STRING:
+                FuncString ();
+                break;
 
-           default:
-               /* Quiet down gcc */
-               break;
+            default:
+                /* Quiet down gcc */
+                break;
 
-       }
+        }
     }
 }
 
 
 
-void Consume (Token Expected, const char* ErrMsg)
+void Consume (token_t Expected, const char* ErrMsg)
 /* Consume Expected, print an error if we don't find it */
 {
-    if (Tok == Expected) {
-       NextTok ();
+    if (CurTok.Tok == Expected) {
+        NextTok ();
     } else {
-               Error ("%s", ErrMsg);
+        Error ("%s", ErrMsg);
     }
 }
 
@@ -720,8 +744,8 @@ void ConsumeSep (void)
     ExpectSep ();
 
     /* If we are at end of line, skip it */
-    if (Tok == TOK_SEP) {
-       NextTok ();
+    if (CurTok.Tok == TOK_SEP) {
+        NextTok ();
     }
 }
 
@@ -754,8 +778,8 @@ void ConsumeComma (void)
 void SkipUntilSep (void)
 /* Skip tokens until we reach a line separator or end of file */
 {
-    while (!TokIsSep (Tok)) {
-       NextTok ();
+    while (!TokIsSep (CurTok.Tok)) {
+        NextTok ();
     }
 }
 
@@ -763,11 +787,11 @@ void SkipUntilSep (void)
 
 void ExpectSep (void)
 /* Check if we've reached a line separator, and output an error if not. Do
- * not skip the line separator.
- */
+** not skip the line separator.
+*/
 {
-    if (!TokIsSep (Tok)) {
-               ErrorSkip ("Unexpected trailing garbage characters");
+    if (!TokIsSep (CurTok.Tok)) {
+        ErrorSkip ("Unexpected trailing garbage characters");
     }
 }
 
@@ -775,11 +799,11 @@ void ExpectSep (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.
- */
+** 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;
 }
@@ -792,6 +816,3 @@ void LeaveRawTokenMode (void)
     PRECONDITION (RawMode > 0);
     --RawMode;
 }
-
-
-