/* */
/* */
/* */
-/* (C) 1998-2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2003 Ullrich von Bassewitz */
+/* Römerstraße 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include <sys/stat.h>
/* common */
+#include "addrsize.h"
#include "chartype.h"
#include "check.h"
#include "fname.h"
/* Struct to handle textual input data */
typedef struct InputData_ InputData;
struct InputData_ {
- const char* Data; /* Pointer to the data */
+ char* Data; /* Pointer to the data */
const char* Pos; /* Pointer to current position */
int Malloced; /* Memory was malloced */
enum Token Tok; /* Last token */
{ ".A8", TOK_A8 },
{ ".ADDR", TOK_ADDR },
{ ".ALIGN", TOK_ALIGN },
- { ".AND", TOK_BAND },
+ { ".AND", TOK_BOOLAND },
{ ".ASCIIZ", TOK_ASCIIZ },
+ { ".ASSERT", TOK_ASSERT },
{ ".AUTOIMPORT", TOK_AUTOIMPORT },
{ ".BITAND", TOK_AND },
{ ".BITNOT", TOK_NOT },
{ ".ELSE", TOK_ELSE },
{ ".ELSEIF", TOK_ELSEIF },
{ ".END", TOK_END },
+ { ".ENDENUM", TOK_ENDENUM },
{ ".ENDIF", TOK_ENDIF },
{ ".ENDMAC", TOK_ENDMACRO },
{ ".ENDMACRO", TOK_ENDMACRO },
{ ".ENDPROC", TOK_ENDPROC },
{ ".ENDREP", TOK_ENDREP },
{ ".ENDREPEAT", TOK_ENDREP },
+ { ".ENDSCOPE", TOK_ENDSCOPE },
+ { ".ENDSTRUCT", TOK_ENDSTRUCT },
+ { ".ENDUNION", TOK_ENDUNION },
+ { ".ENUM", TOK_ENUM },
{ ".ERROR", TOK_ERROR },
{ ".EXITMAC", TOK_EXITMACRO },
{ ".EXITMACRO", TOK_EXITMACRO },
{ ".FEATURE", TOK_FEATURE },
{ ".FILEOPT", TOK_FILEOPT },
{ ".FOPT", TOK_FILEOPT },
+ { ".FORCEIMPORT", TOK_FORCEIMPORT },
{ ".FORCEWORD", TOK_FORCEWORD },
{ ".GLOBAL", TOK_GLOBAL },
{ ".GLOBALZP", TOK_GLOBALZP },
{ ".IFP02", TOK_IFP02 },
{ ".IFP816", TOK_IFP816 },
{ ".IFPC02", TOK_IFPC02 },
+ { ".IFPSC02", TOK_IFPSC02 },
{ ".IFREF", TOK_IFREF },
{ ".IMPORT", TOK_IMPORT },
{ ".IMPORTZP", TOK_IMPORTZP },
{ ".MATCH", TOK_MATCH },
{ ".MID", TOK_MID },
{ ".MOD", TOK_MOD },
- { ".NOT", TOK_BNOT },
+ { ".NOT", TOK_BOOLNOT },
{ ".NULL", TOK_NULL },
- { ".OR", TOK_BOR },
+ { ".OR", TOK_BOOLOR },
{ ".ORG", TOK_ORG },
{ ".OUT", TOK_OUT },
{ ".P02", TOK_P02 },
{ ".PAGELENGTH", TOK_PAGELENGTH },
{ ".PARAMCOUNT", TOK_PARAMCOUNT },
{ ".PC02", TOK_PC02 },
+ { ".POPSEG", TOK_POPSEG },
{ ".PROC", TOK_PROC },
+ { ".PSC02", TOK_PSC02 },
+ { ".PUSHSEG", TOK_PUSHSEG },
{ ".REF", TOK_REFERENCED },
{ ".REFERENCED", TOK_REFERENCED },
{ ".RELOC", TOK_RELOC },
{ ".RES", TOK_RES },
{ ".RIGHT", TOK_RIGHT },
{ ".RODATA", TOK_RODATA },
+ { ".SCOPE", TOK_SCOPE },
{ ".SEGMENT", TOK_SEGMENT },
+ { ".SETCPU", TOK_SETCPU },
{ ".SHL", TOK_SHL },
{ ".SHR", TOK_SHR },
+ { ".SIZEOF", TOK_SIZEOF },
{ ".SMART", TOK_SMART },
{ ".STRAT", TOK_STRAT },
{ ".STRING", TOK_STRING },
{ ".STRLEN", TOK_STRLEN },
+ { ".STRUCT", TOK_STRUCT },
{ ".SUNPLUS", TOK_SUNPLUS },
+ { ".TAG", TOK_TAG },
{ ".TCOUNT", TOK_TCOUNT },
{ ".TIME", TOK_TIME },
+ { ".UNION", TOK_UNION },
+ { ".VERSION", TOK_VERSION },
{ ".WARNING", TOK_WARNING },
{ ".WORD", TOK_WORD },
{ ".XMATCH", TOK_XMATCH },
- { ".XOR", TOK_BXOR },
+ { ".XOR", TOK_BOOLXOR },
{ ".ZEROPAGE", TOK_ZEROPAGE },
};
/* Error (fatal error if this is the main file) */
if (ICount == 0) {
- Fatal (FAT_CANNOT_OPEN_INPUT, Name, strerror (errno));
+ Fatal ("Cannot open input file `%s': %s", Name, strerror (errno));
}
/* We are on include level. Search for the file in the include
PathName = FindInclude (Name);
if (PathName == 0 || (F = fopen (PathName, "r")) == 0) {
/* Not found or cannot open, print an error and bail out */
- Error (ERR_CANNOT_OPEN_INCLUDE, Name, strerror (errno));
+ Error ("Cannot open include file `%s': %s", Name, strerror (errno));
}
/* Free the allocated memory */
/* Stat the file and remember the values */
struct stat Buf;
if (fstat (fileno (F), &Buf) != 0) {
- Fatal (FAT_CANNOT_STAT_INPUT, Name, strerror (errno));
+ Fatal ("Cannot stat input file `%s': %s", Name, strerror (errno));
}
/* Add the file to the input file table and remember the index */
-void NewInputData (const char* Data, int Malloced)
+void NewInputData (char* Data, int Malloced)
/* Add a chunk of input data to the input stream */
{
InputData* I;
break;
}
if (C == '\n' || C == EOF) {
- Error (ERR_NEWLINE_IN_STRING);
+ Error ("Newline in string constant");
break;
}
/* Check for string length, print an error message once */
if (I == MAX_STR_LEN) {
- Error (ERR_STRING_TOO_LONG);
+ Error ("Maximum string size exceeded");
} else if (I < MAX_STR_LEN) {
SVal [I] = C;
}
Tok = TOK_PC;
return;
} else {
- Error (ERR_HEX_DIGIT_EXPECTED);
+ Error ("Hexadecimal digit expected");
}
}
IVal = 0;
while (IsXDigit (C)) {
if (IVal & 0xF0000000) {
- Error (ERR_NUM_OVERFLOW);
+ Error ("Overflow in hexadecimal number");
IVal = 0;
}
IVal = (IVal << 4) + DigitVal (C);
/* 0 or 1 must follow */
if (!IsBDigit (C)) {
- Error (ERR_01_EXPECTED);
+ Error ("Binary digit expected");
}
/* Read the number */
IVal = 0;
while (IsBDigit (C)) {
if (IVal & 0x80000000) {
- Error (ERR_NUM_OVERFLOW);
+ Error ("Overflow in binary number");
IVal = 0;
}
IVal = (IVal << 1) + DigitVal (C);
IVal = 0;
while (IsDigit (C)) {
if (IVal > (long) (0xFFFFFFFFUL / 10)) {
- Error (ERR_NUM_OVERFLOW);
+ Error ("Overflow in decimal number");
IVal = 0;
}
IVal = (IVal * 10) + DigitVal (C);
if (C == '.') {
/* Remember and skip the dot */
- SVal[0] = C;
NextChar ();
/* Check if it's just a dot */
} else {
/* Read the remainder of the identifier */
+ SVal[0] = '.';
ReadIdent (1);
/* Dot keyword, search for it */
Tok = TOK_IDENT;
} else {
/* Invalid pseudo instruction */
- Error (ERR_PSEUDO_EXPECTED);
+ Error ("`%s' is not a recognized control command", SVal);
goto Again;
}
}
/* Start character alone is not enough */
if (SVal [1] == '\0') {
- Error (ERR_IDENT_EXPECTED);
+ Error ("Invalid cheap local symbol");
goto Again;
}
ReadIdent (0);
/* Check for special names */
- if (SVal [1] == '\0') {
+ if (SVal[1] == '\0') {
switch (toupper (SVal [0])) {
case 'A':
- Tok = TOK_A;
+ if (C == ':') {
+ NextChar ();
+ Tok = TOK_OVERRIDE_ABS;
+ } else {
+ Tok = TOK_A;
+ }
return;
+ case 'F':
+ if (C == ':') {
+ NextChar ();
+ Tok = TOK_OVERRIDE_FAR;
+ } else {
+ Tok = TOK_IDENT;
+ }
+ return;
+
+ case 'S':
+ Tok = TOK_S;
+ return;
+
case 'X':
Tok = TOK_X;
return;
Tok = TOK_Y;
return;
- case 'S':
- Tok = TOK_S;
- return;
+ case 'Z':
+ if (C == ':') {
+ NextChar ();
+ Tok = TOK_OVERRIDE_ZP;
+ } else {
+ Tok = TOK_IDENT;
+ }
+ return;
default:
Tok = TOK_IDENT;
NextChar ();
if (C == '&') {
NextChar ();
- Tok = TOK_BAND;
+ Tok = TOK_BOOLAND;
} else {
Tok = TOK_AND;
}
NextChar ();
if (C == '|') {
NextChar ();
- Tok = TOK_BOR;
+ Tok = TOK_BOOLOR;
} else {
Tok = TOK_OR;
}
Tok = TOK_ULABEL;
break;
+ case '=':
+ NextChar ();
+ Tok = TOK_ASSIGN;
+ break;
+
default:
Tok = TOK_COLON;
break;
case '!':
NextChar ();
- Tok = TOK_BNOT;
+ Tok = TOK_BOOLNOT;
return;
case '>':
/* Always a character constant */
NextChar ();
if (C == '\n' || C == EOF) {
- Error (ERR_ILLEGAL_CHARCON);
+ Error ("Illegal character constant");
goto CharAgain;
}
IVal = C;
Tok = TOK_CHARCON;
NextChar ();
if (C != '\'') {
- Error (ERR_ILLEGAL_CHARCON);
+ Error ("Illegal character constant");
} else {
NextChar ();
}
/* If we go here, we could not identify the current character. Skip it
* and try again.
*/
- Error (ERR_INVALID_CHAR, C & 0xFF);
+ Error ("Invalid input character: 0x%02X", C & 0xFF);
NextChar ();
goto Again;
}
+unsigned char ParseAddrSize (void)
+/* Check if the next token is a keyword that denotes an address size specifier.
+ * If so, return the corresponding address size constant, otherwise output an
+ * error message and return ADDR_SIZE_DEFAULT.
+ */
+{
+ static const char* Keys[] = {
+ "DIRECT", "ZEROPAGE", "ZP",
+ "ABSOLUTE", "ABS", "NEAR",
+ "FAR",
+ };
+
+ /* Check for an identifier */
+ if (Tok != TOK_IDENT) {
+ Error ("Address size specifier expected");
+ return ADDR_SIZE_DEFAULT;
+ }
+
+ /* Search for the attribute */
+ switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) {
+ case 0:
+ case 1:
+ case 2: return ADDR_SIZE_ZP;
+ case 3:
+ case 4:
+ case 5: return ADDR_SIZE_ABS;
+ case 6: return ADDR_SIZE_FAR;
+ default:
+ Error ("Address size specifier expected");
+ return ADDR_SIZE_DEFAULT;
+ }
+}
+
+
+
void InitScanner (const char* InFile)
/* Initialize the scanner, open the given input file */
{