X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fca65%2Fnexttok.c;h=1521ed0c25b4e094d1c511e34a3058872d5da3c8;hb=c3d083fe334d59ae18b874c626881477551d0c5d;hp=cb76bdb18530d4d5cbebb3b34d0fe9e074670653;hpb=85f96a7d6f65cf84aec22762818a96261323b1ce;p=cc65 diff --git a/src/ca65/nexttok.c b/src/ca65/nexttok.c index cb76bdb18..1521ed0c2 100644 --- a/src/ca65/nexttok.c +++ b/src/ca65/nexttok.c @@ -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" @@ -52,12 +53,12 @@ /*****************************************************************************/ -/* 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; } - - -