mirror of
https://github.com/cc65/cc65.git
synced 2024-12-28 06:30:16 +00:00
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
This commit is contained in:
parent
2df5db1f04
commit
d92676ef60
@ -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 */
|
||||
{
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user