X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fscanner.c;h=b27ec62c5f7661c79f8cfc9e7ba29ba9a9686f74;hb=0807da74bd7c3ebe3e6e75129a07a810b17174b2;hp=69db9f23f1a947d6def34e741494e71be40475b5;hpb=53dd513176425872128ef26031d00952ef7a0628;p=cc65 diff --git a/src/ld65/scanner.c b/src/ld65/scanner.c index 69db9f23f..b27ec62c5 100644 --- a/src/ld65/scanner.c +++ b/src/ld65/scanner.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2009, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -39,6 +39,12 @@ #include #include +/* common */ +#include "chartype.h" +#include "strbuf.h" +#include "xsprintf.h" + +/* ld65 */ #include "global.h" #include "error.h" #include "scanner.h" @@ -52,8 +58,8 @@ /* Current token and attributes */ -unsigned CfgTok; -char CfgSVal [CFG_MAX_IDENT_LEN+1]; +cfgtok_t CfgTok; +StrBuf CfgSVal = STATIC_STRBUF_INITIALIZER; unsigned long CfgIVal; /* Error location */ @@ -65,7 +71,7 @@ static const char* CfgName = 0; static const char* CfgBuf = 0; /* Other input stuff */ -static int C = ' '; +static int C = ' '; static unsigned InputLine = 1; static unsigned InputCol = 0; static FILE* InputFile = 0; @@ -73,7 +79,7 @@ static FILE* InputFile = 0; /*****************************************************************************/ -/* Error handling */ +/* Error handling */ /*****************************************************************************/ @@ -81,15 +87,15 @@ static FILE* InputFile = 0; void CfgWarning (const char* Format, ...) /* Print a warning message adding file name and line number of the config file */ { - char Buf [512]; + StrBuf Buf = STATIC_STRBUF_INITIALIZER; va_list ap; + va_start (ap, Format); -#ifdef __WATCOMC__ - _vbprintf (Buf, sizeof (Buf), Format, ap); -#else - vsnprintf (Buf, sizeof (Buf), Format, ap); -#endif - Warning ("%s(%u): %s", CfgName, CfgErrorLine, Buf); + SB_VPrintf (&Buf, Format, ap); + va_end (ap); + + Warning ("%s(%u): %s", CfgGetName(), CfgErrorLine, SB_GetConstBuf (&Buf)); + SB_Done (&Buf); } @@ -97,15 +103,15 @@ void CfgWarning (const char* Format, ...) void CfgError (const char* Format, ...) /* Print an error message adding file name and line number of the config file */ { - char Buf [512]; + StrBuf Buf = STATIC_STRBUF_INITIALIZER; va_list ap; + va_start (ap, Format); -#ifdef __WATCOMC__ - _vbprintf (Buf, sizeof (Buf), Format, ap); -#else - vsnprintf (Buf, sizeof (Buf), Format, ap); -#endif - Error ("%s(%u): %s", CfgName, CfgErrorLine, Buf); + SB_VPrintf (&Buf, Format, ap); + va_end (ap); + + Error ("%s(%u): %s", CfgGetName(), CfgErrorLine, SB_GetConstBuf (&Buf)); + SB_Done (&Buf); } @@ -123,7 +129,7 @@ static void NextChar (void) /* Read from buffer */ C = (unsigned char)(*CfgBuf); if (C == 0) { - C = EOF; + C = EOF; } else { ++CfgBuf; } @@ -158,12 +164,75 @@ static unsigned DigitVal (int C) -void CfgNextTok (void) -/* Read the next token from the input stream */ +static void StrVal (void) +/* Parse a string value and expand escape sequences */ { - unsigned I; + /* Skip the starting double quotes */ + NextChar (); + + /* Read input chars */ + SB_Clear (&CfgSVal); + while (C != '\"') { + switch (C) { + + case EOF: + case '\n': + CfgError ("Unterminated string"); + break; + + case '%': + NextChar (); + switch (C) { + + case EOF: + case '\n': + case '\"': + CfgError ("Unterminated '%%' escape sequence"); + break; + + case '%': + SB_AppendChar (&CfgSVal, '%'); + NextChar (); + break; + + case 'O': + /* Replace by output file */ + if (OutputName) { + SB_AppendStr (&CfgSVal, OutputName); + } + NextChar (); + break; + + default: + CfgWarning ("Unkown escape sequence `%%%c'", C); + SB_AppendChar (&CfgSVal, '%'); + SB_AppendChar (&CfgSVal, C); + NextChar (); + break; + } + break; + + default: + SB_AppendChar (&CfgSVal, C); + NextChar (); + } + } + /* Skip the terminating double quotes */ + NextChar (); + /* Terminate the string */ + SB_Terminate (&CfgSVal); + + /* We've read a string value */ + CfgTok = CFGTOK_STRCON; +} + + + +void CfgNextTok (void) +/* Read the next token from the input stream */ +{ Again: /* Skip whitespace */ while (isspace (C)) { @@ -175,17 +244,15 @@ Again: CfgErrorCol = InputCol; /* Identifier? */ - if (C == '_' || isalpha (C)) { + if (C == '_' || IsAlpha (C)) { /* Read the identifier */ - I = 0; - while (C == '_' || isalnum (C)) { - if (I < CFG_MAX_IDENT_LEN) { - CfgSVal [I++] = C; - } + SB_Clear (&CfgSVal); + while (C == '_' || IsAlNum (C)) { + SB_AppendChar (&CfgSVal, C); NextChar (); } - CfgSVal [I] = '\0'; + SB_Terminate (&CfgSVal); CfgTok = CFGTOK_IDENT; return; } @@ -194,7 +261,7 @@ Again: if (C == '$') { NextChar (); if (!isxdigit (C)) { - Error ("%s(%u): Hex digit expected", CfgName, InputLine); + CfgError ("Hex digit expected"); } CfgIVal = 0; while (isxdigit (C)) { @@ -219,6 +286,36 @@ Again: /* Other characters */ switch (C) { + case '-': + NextChar (); + CfgTok = CFGTOK_MINUS; + break; + + case '+': + NextChar (); + CfgTok = CFGTOK_PLUS; + break; + + case '*': + NextChar (); + CfgTok = CFGTOK_MUL; + break; + + case '/': + NextChar (); + CfgTok = CFGTOK_DIV; + break; + + case '(': + NextChar (); + CfgTok = CFGTOK_LPAR; + break; + + case ')': + NextChar (); + CfgTok = CFGTOK_RPAR; + break; + case '{': NextChar (); CfgTok = CFGTOK_LCURLY; @@ -252,23 +349,10 @@ Again: case ':': NextChar (); CfgTok = CFGTOK_COLON; - break; + break; case '\"': - NextChar (); - I = 0; - while (C != '\"') { - if (C == EOF || C == '\n') { - Error ("%s(%u): Unterminated string", CfgName, InputLine); - } - if (I < CFG_MAX_IDENT_LEN) { - CfgSVal [I++] = C; - } - NextChar (); - } - NextChar (); - CfgSVal [I] = '\0'; - CfgTok = CFGTOK_STRCON; + StrVal (); break; case '#': @@ -289,13 +373,13 @@ Again: case 'O': NextChar (); if (OutputName) { - strncpy (CfgSVal, OutputName, CFG_MAX_IDENT_LEN); - CfgSVal [CFG_MAX_IDENT_LEN] = '\0'; + SB_CopyStr (&CfgSVal, OutputName); } else { - CfgSVal [0] = '\0'; + SB_Clear (&CfgSVal); } + SB_Terminate (&CfgSVal); CfgTok = CFGTOK_STRCON; - break; + break; case 'S': NextChar (); @@ -313,18 +397,18 @@ Again: break; default: - Error ("%s(%u): Invalid character `%c'", CfgName, InputLine, C); + CfgError ("Invalid character `%c'", C); } } -void CfgConsume (unsigned T, const char* Msg) +void CfgConsume (cfgtok_t T, const char* Msg) /* Skip a token, print an error message if not found */ { if (CfgTok != T) { - CfgError (Msg); + CfgError ("%s", Msg); } CfgNextTok (); } @@ -416,16 +500,12 @@ void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name) if (CfgTok == CFGTOK_IDENT) { /* Make it upper case */ - I = 0; - while (CfgSVal [I]) { - CfgSVal [I] = toupper (CfgSVal [I]); - ++I; - } + SB_ToUpper (&CfgSVal); /* Linear search */ for (I = 0; I < Size; ++I) { - if (strcmp (CfgSVal, Table [I].Ident) == 0) { - CfgTok = Table [I].Tok; + if (SB_CompareStr (&CfgSVal, Table[I].Ident) == 0) { + CfgTok = Table[I].Tok; return; } } @@ -433,7 +513,7 @@ void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name) } /* Not found or no identifier */ - Error ("%s(%u): %s expected", CfgName, InputLine, Name); + CfgError ("%s expected", Name); } @@ -473,7 +553,13 @@ void CfgSetName (const char* Name) const char* CfgGetName (void) /* Get the name of the config file */ { - return CfgName? CfgName : ""; + if (CfgName) { + return CfgName; + } else if (CfgBuf) { + return "[builtin config]"; + } else { + return ""; + } } @@ -533,3 +619,4 @@ void CfgCloseInput (void) +