/* */
/* */
/* */
-/* (C) 1998-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* common */
#include "chartype.h"
+#include "fp.h"
#include "tgttrans.h"
/* cc65 */
#include "scanner.h"
#include "standard.h"
#include "symtab.h"
-#include "util.h"
/*****************************************************************************/
-/* data */
+/* data */
/*****************************************************************************/
unsigned char Tok; /* The token */
unsigned char Std; /* Token supported in which standards? */
} Keywords [] = {
- { "_Pragma", TOK_PRAGMA, TT_C99 | TT_CC65 },
+ { "_Pragma", TOK_PRAGMA, TT_C89 | TT_C99 | TT_CC65 }, /* !! */
{ "__AX__", TOK_AX, TT_C89 | TT_C99 | TT_CC65 },
{ "__A__", TOK_A, TT_C89 | TT_C99 | TT_CC65 },
{ "__EAX__", TOK_EAX, TT_C89 | TT_C99 | TT_CC65 },
{ "__Y__", TOK_Y, TT_C89 | TT_C99 | TT_CC65 },
{ "__asm__", TOK_ASM, TT_C89 | TT_C99 | TT_CC65 },
{ "__attribute__", TOK_ATTRIBUTE, TT_C89 | TT_C99 | TT_CC65 },
+ { "__cdecl__", TOK_CDECL, TT_C89 | TT_C99 | TT_CC65 },
{ "__far__", TOK_FAR, TT_C89 | TT_C99 | TT_CC65 },
{ "__fastcall__", TOK_FASTCALL, TT_C89 | TT_C99 | TT_CC65 },
+ { "__inline__", TOK_INLINE, TT_C89 | TT_C99 | TT_CC65 },
{ "__near__", TOK_NEAR, TT_C89 | TT_C99 | TT_CC65 },
{ "asm", TOK_ASM, TT_CC65 },
{ "auto", TOK_AUTO, TT_C89 | TT_C99 | TT_CC65 },
{ "break", TOK_BREAK, TT_C89 | TT_C99 | TT_CC65 },
{ "case", TOK_CASE, TT_C89 | TT_C99 | TT_CC65 },
+ { "cdecl", TOK_CDECL, TT_CC65 },
{ "char", TOK_CHAR, TT_C89 | TT_C99 | TT_CC65 },
{ "const", TOK_CONST, TT_C89 | TT_C99 | TT_CC65 },
{ "continue", TOK_CONTINUE, TT_C89 | TT_C99 | TT_CC65 },
{ "for", TOK_FOR, TT_C89 | TT_C99 | TT_CC65 },
{ "goto", TOK_GOTO, TT_C89 | TT_C99 | TT_CC65 },
{ "if", TOK_IF, TT_C89 | TT_C99 | TT_CC65 },
+ { "inline", TOK_INLINE, TT_C99 | TT_CC65 },
{ "int", TOK_INT, TT_C89 | TT_C99 | TT_CC65 },
{ "long", TOK_LONG, TT_C89 | TT_C99 | TT_CC65 },
{ "near", TOK_NEAR, TT_CC65 },
*/
{
while (1) {
- while (CurC == 0) {
+ while (CurC == '\0') {
if (NextLine () == 0) {
return 0;
}
-void SymName (char* s)
-/* Get symbol from input stream */
+int TokIsFuncSpec (const Token* T)
+/* Return true if the token is a function specifier */
{
- unsigned k = 0;
+ return (T->Tok == TOK_INLINE) ||
+ (T->Tok == TOK_FASTCALL) || (T->Tok == TOK_CDECL) ||
+ (T->Tok == TOK_NEAR) || (T->Tok == TOK_FAR);
+}
+
+
+
+void SymName (char* S)
+/* Read a symbol from the input stream. The first character must have been
+ * checked before calling this function. The buffer is expected to be at
+ * least of size MAX_IDENTLEN+1.
+ */
+{
+ unsigned Len = 0;
do {
- if (k != MAX_IDENTLEN) {
- ++k;
- *s++ = CurC;
- }
+ if (Len < MAX_IDENTLEN) {
+ ++Len;
+ *S++ = CurC;
+ }
NextChar ();
} while (IsIdent (CurC) || IsDigit (CurC));
- *s = '\0';
+ *S = '\0';
}
-int IsSym (char *s)
-/* Get symbol from input stream or return 0 if not a symbol. */
+int IsSym (char* S)
+/* If a symbol follows, read it and return 1, otherwise return 0 */
{
if (IsIdent (CurC)) {
- SymName (s);
+ SymName (S);
return 1;
} else {
return 0;
static int ParseChar (void)
-/* Parse a character. Converts \n into EOL, etc. */
+/* Parse a character. Converts escape chars into character codes. */
{
- int I;
- unsigned Val;
int C;
+ int HadError;
/* Check for escape chars */
if (CurC == '\\') {
case 'x':
case 'X':
/* Hex character constant */
- NextChar ();
- Val = HexVal (CurC) << 4;
- NextChar ();
- C = Val | HexVal (CurC); /* Do not translate */
+ if (!IsXDigit (NextC)) {
+ Error ("\\x used with no following hex digits");
+ C = ' ';
+ } else {
+ HadError = 0;
+ C = 0;
+ while (IsXDigit (NextC)) {
+ if ((C << 4) >= 256) {
+ if (!HadError) {
+ Error ("Hex character constant out of range");
+ HadError = 1;
+ }
+ } else {
+ C = (C << 4) | HexVal (NextC);
+ }
+ NextChar ();
+ }
+ }
break;
case '0':
case '1':
case '5':
case '6':
case '7':
- /* Octal constant */
- I = 0;
- Val = CurC - '0';
- while (NextC >= '0' && NextC <= '7' && ++I <= 3) {
- NextChar ();
- Val = (Val << 3) | (CurC - '0');
- }
- C = (int) Val;
- if (Val >= 256) {
- Error ("Character constant out of range");
- C = ' ';
- }
- break;
+ /* Octal constant */
+ HadError = 0;
+ C = HexVal (CurC);
+ while (IsODigit (NextC)) {
+ if ((C << 3) >= 256) {
+ if (!HadError) {
+ Error ("Octal character constant out of range");
+ HadError = 1;
+ }
+ } else {
+ C = (C << 3) | HexVal (NextC);
+ }
+ NextChar ();
+ }
+ break;
default:
Error ("Illegal character constant");
- C = ' ';
+ C = ' ';
/* Try to do error recovery, otherwise the compiler will spit
* out thousands of errors in this place and abort.
*/
static void StringConst (void)
/* Parse a quoted string */
{
- NextTok.IVal = GetLiteralPoolOffs ();
+ /* String buffer */
+ StrBuf S = AUTO_STRBUF_INITIALIZER;
+
+ /* Assume next token is a string constant */
NextTok.Tok = TOK_SCONST;
- /* Be sure to concatenate strings */
- while (CurC == '\"') {
+ /* Concatenate strings. If at least one of the concenated strings is a wide
+ * character literal, the whole string is a wide char literal, otherwise
+ * it's a normal string literal.
+ */
+ while (1) {
- /* Skip the quote char */
- NextChar ();
+ /* Check if this is a normal or a wide char string */
+ if (CurC == 'L' && NextC == '\"') {
+ /* Wide character literal */
+ NextTok.Tok = TOK_WCSCONST;
+ NextChar ();
+ NextChar ();
+ } else if (CurC == '\"') {
+ /* Skip the quote char */
+ NextChar ();
+ } else {
+ /* No string */
+ break;
+ }
- while (CurC != '\"') {
- if (CurC == '\0') {
- Error ("Unexpected newline");
- break;
- }
- AddLiteralChar (ParseChar ());
- }
+ /* Read until end of string */
+ while (CurC != '\"') {
+ if (CurC == '\0') {
+ Error ("Unexpected newline");
+ break;
+ }
+ SB_AppendChar (&S, ParseChar ());
+ }
- /* Skip closing quote char if there was one */
+ /* Skip closing quote char if there was one */
NextChar ();
/* Skip white space, read new input */
}
/* Terminate the string */
- AddLiteralChar ('\0');
+ SB_AppendChar (&S, '\0');
+
+ /* Add the whole string to the literal pool */
+ NextTok.SVal = AddLiteralStr (&S);
+
+ /* Free the buffer */
+ SB_Done (&S);
}
{
unsigned Base; /* Temporary number base */
unsigned Prefix; /* Base according to prefix */
- StrBuf S;
+ StrBuf S = STATIC_STRBUF_INITIALIZER;
int IsFloat;
char C;
unsigned DigitVal;
* before converting it, so we can determine if it's a float or an
* integer.
*/
- InitStrBuf (&S);
while (IsXDigit (CurC) && HexVal (CurC) < Base) {
SB_AppendChar (&S, CurC);
NextChar ();
}
/* We don't need the string buffer any longer */
- DoneStrBuf (&S);
+ SB_Done (&S);
/* Distinguish between integer and floating point constants */
if (!IsFloat) {
} else {
/* Float constant */
- double FVal = IVal; /* Convert to float */
+ Double FVal = FP_D_FromInt (IVal); /* Convert to double */
/* Check for a fractional part and read it */
if (CurC == '.') {
- unsigned Digits;
- unsigned long Frac;
- unsigned long Scale;
+ Double Scale;
/* Skip the dot */
NextChar ();
- /* Read fractional digits. Since we support only 32 bit floats
- * with a maximum of 7 fractional digits, we read the fractional
- * part as integer with up to 8 digits and drop the remainder.
- * This avoids an overflow of Frac and Scale.
- */
- Digits = 0;
- Frac = 0;
- Scale = 1;
+ /* Read fractional digits */
+ Scale = FP_D_Make (1.0);
while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) {
- if (Digits < 8) {
- Frac = Frac * Base + DigitVal;
- ++Digits;
- Scale *= Base;
- }
+ /* Get the value of this digit */
+ Double FracVal = FP_D_Div (FP_D_FromInt (DigitVal * Base), Scale);
+ /* Add it to the float value */
+ FVal = FP_D_Add (FVal, FracVal);
+ /* Scale base */
+ Scale = FP_D_Mul (Scale, FP_D_FromInt (DigitVal));
+ /* Skip the digit */
NextChar ();
}
-
- /* Scale the fractional part and add it */
- if (Frac) {
- FVal += ((double) Frac) / ((double) Scale);
- }
}
/* Check for an exponent and read it */
if ((Base == 16 && toupper (CurC) == 'F') ||
(Base == 10 && toupper (CurC) == 'E')) {
- int Sign;
unsigned Digits;
unsigned Exp;
NextChar ();
/* Read an optional sign */
- Sign = 1;
if (CurC == '-') {
- Sign = -1;
+ NextChar ();
+ } else if (CurC == '+') {
NextChar ();
}
/* Scale the exponent and adjust the value accordingly */
if (Exp) {
- FVal *= pow (10, Exp);
+ FVal = FP_D_Mul (FVal, FP_D_Make (pow (10, Exp)));
}
}
return;
}
+ /* Check for wide character literals */
+ if (CurC == 'L' && NextC == '\"') {
+ StringConst ();
+ return;
+ }
+
+ /* Check for keywords and identifiers */
if (IsSym (token)) {
/* Check for a keyword */
if (token[0] == '_' && token[1] == '_') {
/* Special symbols */
if (strcmp (token+2, "FILE__") == 0) {
- NextTok.IVal = AddLiteral (GetCurrentFile());
+ NextTok.SVal = AddLiteral (GetCurrentFile());
NextTok.Tok = TOK_SCONST;
return;
} else if (strcmp (token+2, "LINE__") == 0) {
} else if (strcmp (token+2, "func__") == 0) {
/* __func__ is only defined in functions */
if (CurrentFunc) {
- NextTok.IVal = AddLiteral (F_GetFuncName (CurrentFunc));
+ NextTok.SVal = AddLiteral (F_GetFuncName (CurrentFunc));
NextTok.Tok = TOK_SCONST;
return;
}
NextToken ();
return 1;
} else {
- Error (ErrorMsg);
+ Error ("%s", ErrorMsg);
return 0;
}
}