/*****************************************************************************/
/* */
-/* 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 */
#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 */
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;
/*****************************************************************************/
-/* 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 */
/* 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 */
/* Handle the .IDENT function */
{
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
- Token Id;
+ token_t Id;
unsigned I;
/* Skip it */
}
/* 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;
}
}
/* 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 */
static void FuncLeft (void)
/* Handle the .LEFT function */
{
- long Count;
- TokList* List;
+ long Count;
+ TokList* List;
/* Skip it */
NextTok ();
/* Count argument. Correct negative counts to zero. */
Count = ConstExpression ();
if (Count < 0) {
- Count = 1;
+ Count = 0;
}
ConsumeComma ();
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 */
static void FuncMid (void)
/* Handle the .MID function */
{
- long Start;
- long Count;
- TokList* List;
+ long Start;
+ long Count;
+ TokList* List;
/* Skip it */
NextTok ();
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 ();
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 */
static void FuncRight (void)
/* Handle the .RIGHT function */
{
- long Count;
- TokList* List;
+ long Count;
+ TokList* List;
/* Skip it */
NextTok ();
/* Count argument. Correct negative counts to zero. */
Count = ConstExpression ();
if (Count < 0) {
- Count = 0;
+ Count = 0;
}
ConsumeComma ();
/* 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 */
if (!LookAtStrCon ()) {
return;
}
- SB_Copy (&Format, &SVal);
+ SB_Copy (&Format, &CurTok.SVal);
NextTok ();
/* Walk over the format string, generating the function result in R */
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, '%');
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);
/* 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 ();
}
/* 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 */
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);
}
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 */
/* 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);
}
}
ExpectSep ();
/* If we are at end of line, skip it */
- if (Tok == TOK_SEP) {
- NextTok ();
+ if (CurTok.Tok == TOK_SEP) {
+ NextTok ();
}
}
void SkipUntilSep (void)
/* Skip tokens until we reach a line separator or end of file */
{
- while (!TokIsSep (Tok)) {
- NextTok ();
+ while (!TokIsSep (CurTok.Tok)) {
+ NextTok ();
}
}
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");
}
}
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;
}
PRECONDITION (RawMode > 0);
--RawMode;
}
-
-
-