From d92676ef602f6abfa43cf47741f7559fdef28fe6 Mon Sep 17 00:00:00 2001 From: cuz Date: Mon, 30 Sep 2002 18:46:08 +0000 Subject: [PATCH] Add SB_GetNumber to scanstrbuf.c. Rewrite of CharMapPragma in pragma.c Fixed bug in scanner.c: Invalid octal constants containing the numbers 8 and 9 were accepted by the compiler. Moved SignExtendChar from scanner.c to datatype.c. git-svn-id: svn://svn.cc65.org/cc65/trunk@1416 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/datatype.c | 14 +++++- src/cc65/datatype.h | 11 +++-- src/cc65/pragma.c | 46 ++++++++++++-------- src/cc65/scanner.c | 54 +++++++++++------------ src/cc65/scanstrbuf.c | 99 +++++++++++++++++++++++++++++++++++++++++++ src/cc65/scanstrbuf.h | 6 +++ 6 files changed, 178 insertions(+), 52 deletions(-) diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 01778b5f8..bc3ae194f 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ +/* (C) 1998-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ @@ -135,6 +135,18 @@ void TypeFree (type* T) +int SignExtendChar (int C) +/* Do correct sign extension of a character */ +{ + if (SignedChars && (C & 0x80) != 0) { + return C | ~0xFF; + } else { + return C & 0xFF; + } +} + + + type GetDefaultChar (void) /* Return the default char type (signed/unsigned) depending on the settings */ { diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index a750afff2..2d4ac21bb 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2002 Ullrich von Bassewitz */ +/* Wacholderweg 14 */ +/* D-70597 Stuttgart */ +/* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -180,6 +180,9 @@ type* TypeAlloc (unsigned Len); void TypeFree (type* Type); /* Free a type string */ +int SignExtendChar (int C); +/* Do correct sign extension of a character */ + type GetDefaultChar (void); /* Return the default char type (signed/unsigned) depending on the settings */ diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index b26ef7bc8..f4c38491b 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -175,7 +175,7 @@ static void SegNamePragma (StrBuf* B, segment_t Seg) } else { Error ("String literal expected"); - } + } /* Call the string buf destructor */ DoneStrBuf (&S); @@ -186,33 +186,37 @@ static void SegNamePragma (StrBuf* B, segment_t Seg) static void CharMapPragma (StrBuf* B) /* Change the character map */ { - unsigned Index, C; - - ExprDesc Val; + long Index, C; /* Read the character index */ - ConstIntExpr (&Val); - if (Val.ConstVal < 1 || Val.ConstVal > 255) { - Error ("Character index out of range"); - Index = 'A'; - } else { - Index = Val.ConstVal; + if (!SB_GetNumber (B, &Index)) { + return; + } + if (Index < 1 || Index > 255) { + Error ("Character index out of range"); + return; } /* Comma follows */ - ConsumeComma (); + SB_SkipWhite (B); + if (SB_Get (B) != ',') { + Error ("Comma expected"); + return; + } + SB_SkipWhite (B); /* Read the character code */ - ConstIntExpr (&Val); - if (Val.ConstVal < 1 || Val.ConstVal > 255) { + if (!SB_GetNumber (B, &C)) { + return; + } + if (C < 1 || C > 255) { Error ("Character code out of range"); - C = 'A'; - } else { - C = Val.ConstVal; + return; } /* Remap the character */ - TgtTranslateSet (Index, C); + printf ("Translating %04lX to %04lX\n", Index, C); + TgtTranslateSet ((unsigned) Index, (unsigned char) C); } @@ -346,9 +350,15 @@ static void ParsePragma (void) Error ("')' expected"); return; } + SB_SkipWhite (&B); + + /* Allow an optional semicolon to be compatible with the old syntax */ + if (SB_Peek (&B) == ';') { + SB_Skip (&B); + SB_SkipWhite (&B); + } /* Make sure nothing follows */ - SB_SkipWhite (&B); if (SB_Peek (&B) != '\0') { Error ("Unexpected input following pragma directive"); } diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index b6321780e..967a7fb13 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -237,18 +237,6 @@ static void SetTok (int tok) -static int SignExtendChar (int C) -/* Do correct sign extension of a character */ -{ - if (SignedChars && (C & 0x80) != 0) { - return C | ~0xFF; - } else { - return C & 0xFF; - } -} - - - static int ParseChar (void) /* Parse a character. Converts \n into EOL, etc. */ { @@ -387,7 +375,7 @@ static void StringConst (void) void NextToken (void) /* Get next token from input stream */ -{ +{ ident token; /* We have to skip white space here before shifting tokens, since the @@ -419,11 +407,12 @@ void NextToken (void) /* A number */ int HaveSuffix; /* True if we have a type suffix */ unsigned types; /* Possible types */ - unsigned base; - unsigned long k; /* Value */ + unsigned Base; + unsigned DigitVal; + unsigned long k; /* Value */ k = 0; - base = 10; + Base = 10; types = IT_INT | IT_LONG | IT_ULONG; if (CurC == '0') { @@ -432,23 +421,30 @@ void NextToken (void) /* gobble 0 and examin next char */ NextChar (); if (toupper (CurC) == 'X') { - base = 16; - NextTok.Type = type_uint; + Base = 16; + NextTok.Type = type_uint; NextChar (); /* gobble "x" */ } else { - base = 8; + Base = 8; } } - while (1) { - if (IsDigit (CurC)) { - k = k * base + (CurC - '0'); - } else if (base == 16 && IsXDigit (CurC)) { - k = (k << 4) + HexVal (CurC); - } else { - break; /* not digit */ - } - NextChar (); /* gobble char */ - } + while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) { + k = k * Base + DigitVal; + NextChar (); + } + /* Check for errorneous digits */ + if (Base == 8 && IsDigit (CurC)) { + Error ("Numeric constant contains digits beyond the radix"); + /* Do error recovery */ + do { + NextChar (); + } while (IsDigit (CurC)); + } else if (Base != 16 && IsXDigit (CurC)) { + Error ("Nondigits in number and not hexadecimal"); + do { + NextChar (); + } while (IsXDigit (CurC)); + } /* Check for a suffix */ HaveSuffix = 1; diff --git a/src/cc65/scanstrbuf.c b/src/cc65/scanstrbuf.c index 82418f763..39c15e4e5 100644 --- a/src/cc65/scanstrbuf.c +++ b/src/cc65/scanstrbuf.c @@ -35,8 +35,10 @@ /* common */ #include "chartype.h" +#include "tgttrans.h" /* cc65 */ +#include "datatype.h" #include "error.h" #include "hexval.h" #include "ident.h" @@ -209,3 +211,100 @@ int SB_GetString (StrBuf* B, StrBuf* S) +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. + */ +{ + int Sign; + char C; + unsigned Base; + unsigned DigitVal; + + /* Initialize Val */ + *Val = 0; + + /* Check for a sign */ + Sign = 1; + switch (SB_Peek (B)) { + case '-': + Sign = -1; + /* FALLTHROUGH */ + case '+': + SB_Skip (B); + SB_SkipWhite (B); + break; + } + + /* Check for the different formats */ + C = SB_Peek (B); + if (IsDigit (C)) { + + if (C == '0') { + /* Hex or octal */ + 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; + } + } else { + Base = 10; + } + + /* 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 */ + C = SB_Peek (B); + if (C == 'u' || C == 'U') { + 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 */ + SB_Skip (B); + *Val = SignExtendChar (TgtTranslateChar (ParseChar (B))); + if (SB_Peek (B) != '\'') { + Error ("`\'' expected"); + return 0; + } else { + /* Skip the quote */ + SB_Skip (B); + } + + } else { + + /* Invalid number */ + Error ("Numeric constant expected"); + return 0; + + } + + /* Success, value read is in Val */ + return 1; +} + + + diff --git a/src/cc65/scanstrbuf.h b/src/cc65/scanstrbuf.h index 9bd971441..29002052e 100644 --- a/src/cc65/scanstrbuf.h +++ b/src/cc65/scanstrbuf.h @@ -63,6 +63,12 @@ int SB_GetString (StrBuf* B, StrBuf* S); * returns 1 if a string was found and 0 otherwise. */ +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. + */