X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fscanstrbuf.c;h=f55f52a6454d791172b6d6f68a8a3b1c6b588ff6;hb=112ae0e3db511ddd92e769c11328646ebe2a6240;hp=b441ae3090ccc2af29c5c7c705b055afd03dd11d;hpb=98e3d2815ea06882bab848ed186640e511075951;p=cc65 diff --git a/src/cc65/scanstrbuf.c b/src/cc65/scanstrbuf.c index b441ae309..f55f52a64 100644 --- a/src/cc65/scanstrbuf.c +++ b/src/cc65/scanstrbuf.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2002 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@cc65.org */ +/* (C) 2002-2009, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -56,64 +56,85 @@ static int ParseChar (StrBuf* B) /* Parse a character. Converts \n into EOL, etc. */ { unsigned I; + unsigned Val; int C; /* Check for escape chars */ if ((C = SB_Get (B)) == '\\') { - switch (SB_Get (B)) { + switch (SB_Peek (B)) { + case '?': + C = '?'; + SB_Skip (B); + break; case 'a': C = '\a'; + SB_Skip (B); break; case 'b': C = '\b'; + SB_Skip (B); break; case 'f': C = '\f'; + SB_Skip (B); break; case 'r': C = '\r'; + SB_Skip (B); break; case 'n': C = '\n'; + SB_Skip (B); break; case 't': C = '\t'; + SB_Skip (B); break; case 'v': C = '\v'; + SB_Skip (B); break; case '\"': C = '\"'; + SB_Skip (B); break; case '\'': C = '\''; + SB_Skip (B); break; case '\\': C = '\\'; - break; - case '\?': - C = '\?'; + SB_Skip (B); break; case 'x': case 'X': /* Hex character constant */ + SB_Skip (B); C = HexVal (SB_Get (B)) << 4; C |= HexVal (SB_Get (B)); break; case '0': - /* Octal constant */ - C = 0; - goto Octal; case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': /* Octal constant */ - C = 1; -Octal: I = 0; - while (SB_Peek (B) >= '0' && SB_Peek (B) <= '7' && I++ < 4) { - C = (C << 3) | (SB_Get (B) - '0'); + I = 0; + Val = SB_Get (B) - '0'; + while (SB_Peek (B) >= '0' && SB_Peek (B) <= '7' && ++I <= 3) { + Val = (Val << 3) | (SB_Get (B) - '0'); } + C = (int) Val; + if (Val > 256) { + Error ("Character constant out of range"); + C = ' '; + } break; default: - Error ("Illegal character constant"); + Error ("Illegal character constant 0x%02X", SB_Get (B)); C = ' '; break; } @@ -126,7 +147,7 @@ Octal: I = 0; /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -141,23 +162,32 @@ void SB_SkipWhite (StrBuf* B) -int SB_GetSym (StrBuf* B, char* S) -/* Get a symbol from the string buffer. S must be able to hold MAX_IDENTLEN - * characters. Returns 1 if a symbol was found and 0 otherwise. - */ +int SB_GetSym (StrBuf* B, StrBuf* Ident, const char* SpecialChars) +/* Get a symbol from the string buffer. If SpecialChars is not NULL, it + * points to a string that contains characters allowed within the string in + * addition to letters, digits and the underline. Note: The identifier must + * still begin with a letter. + * Returns 1 if a symbol was found and 0 otherwise but doesn't output any + * errors. + */ { + /* Handle a NULL argument for SpecialChars transparently */ + if (SpecialChars == 0) { + SpecialChars = ""; + } + + /* Clear Ident */ + SB_Clear (Ident); + if (IsIdent (SB_Peek (B))) { - unsigned I = 0; char C = SB_Peek (B); do { - if (I < MAX_IDENTLEN) { - ++I; - *S++ = C; - } + SB_AppendChar (Ident, C); SB_Skip (B); C = SB_Peek (B); - } while (IsIdent (C) || IsDigit (C)); - *S = '\0'; + } while (IsIdent (C) || IsDigit (C) || + (C != '\0' && strchr (SpecialChars, C) != 0)); + SB_Terminate (Ident); return 1; } else { return 0; @@ -167,15 +197,17 @@ int SB_GetSym (StrBuf* B, char* S) int SB_GetString (StrBuf* B, StrBuf* S) -/* Get a string from the string buffer. S will be initialized by the function - * and will return the correctly terminated string on return. The function - * returns 1 if a string was found and 0 otherwise. +/* Get a string from the string buffer. Returns 1 if a string was found and 0 + * otherwise. Errors are only output in case of invalid strings (missing end + * of string). */ { char C; - /* Initialize S */ - *S = AUTO_STRBUF_INITIALIZER; + /* Clear S */ + SB_Clear (S); + + /* A string starts with quote marks */ if (SB_Peek (B) == '\"') { /* String follows, be sure to concatenate strings */ @@ -220,7 +252,7 @@ int SB_GetNumber (StrBuf* B, long* Val) /* Get a number from the string buffer. Accepted formats are decimal, octal, * hex and character constants. Numeric constants may be preceeded by a * minus or plus sign. The function returns 1 if a number was found and - * zero otherwise. + * zero otherwise. Errors are only output for invalid numbers. */ { int Sign; @@ -228,86 +260,90 @@ int SB_GetNumber (StrBuf* B, long* Val) unsigned Base; unsigned DigitVal; + /* Initialize Val */ *Val = 0; - /* Check for a sign */ + /* Handle character constants */ + if (SB_Peek (B) == '\'') { + + /* Character constant */ + SB_Skip (B); + *Val = SignExtendChar (TgtTranslateChar (ParseChar (B))); + if (SB_Peek (B) != '\'') { + Error ("`\'' expected"); + return 0; + } else { + /* Skip the quote */ + SB_Skip (B); + return 1; + } + } + + /* Check for a sign. A sign must be followed by a digit, otherwise it's + * not a number + */ Sign = 1; switch (SB_Peek (B)) { case '-': Sign = -1; /* FALLTHROUGH */ case '+': + if (!IsDigit (SB_LookAt (B, SB_GetIndex (B) + 1))) { + return 0; + } SB_Skip (B); - SB_SkipWhite (B); break; } - /* Check for the different formats */ + /* We must have a digit now, otherwise its not a number */ C = SB_Peek (B); - if (IsDigit (C)) { + if (!IsDigit (C)) { + return 0; + } - if (C == '0') { - /* Hex or octal */ + /* Determine the base */ + if (C == '0') { + /* Hex or octal */ + SB_Skip (B); + if (tolower (SB_Peek (B)) == 'x') { SB_Skip (B); - if (tolower (SB_Peek (B)) == 'x') { - SB_Skip (B); - Base = 16; - if (!IsXDigit (SB_Peek (B))) { - Error ("Invalid hexadecimal number"); - return 0; - } - } else { - Base = 8; + Base = 16; + if (!IsXDigit (SB_Peek (B))) { + Error ("Invalid hexadecimal number"); + return 0; } } else { - Base = 10; + Base = 8; } + } else { + Base = 10; + } - /* Read the number */ - while (IsXDigit (C = SB_Peek (B)) && (DigitVal = HexVal (C)) < Base) { - *Val = (*Val * Base) + DigitVal; - SB_Skip (B); - } + /* Read the number */ + while (IsXDigit (C = SB_Peek (B)) && (DigitVal = HexVal (C)) < Base) { + *Val = (*Val * Base) + DigitVal; + SB_Skip (B); + } - /* Allow optional 'U' and 'L' modifiers */ + /* Allow optional 'U' and 'L' modifiers */ + C = SB_Peek (B); + if (C == 'u' || C == 'U') { + SB_Skip (B); C = SB_Peek (B); - if (C == 'u' || C == 'U') { + if (C == 'l' || C == 'L') { SB_Skip (B); - C = SB_Peek (B); - if (C == 'l' || C == 'L') { - SB_Skip (B); - } - } else if (C == 'l' || C == 'L') { - SB_Skip (B); - C = SB_Peek (B); - if (C == 'u' || C == 'U') { - SB_Skip (B); - } } - - } else if (C == '\'') { - - /* Character constant */ + } else if (C == 'l' || C == 'L') { SB_Skip (B); - *Val = SignExtendChar (TgtTranslateChar (ParseChar (B))); - if (SB_Peek (B) != '\'') { - Error ("`\'' expected"); - return 0; - } else { - /* Skip the quote */ + C = SB_Peek (B); + if (C == 'u' || C == 'U') { SB_Skip (B); } - - } else { - - /* Invalid number */ - Error ("Numeric constant expected"); - return 0; - } /* Success, value read is in Val */ + *Val *= Sign; return 1; }