]> git.sur5r.net Git - cc65/blobdiff - src/ca65/scanner.c
Allow conditional directives within .STRUCT7:UNION and .ENUM
[cc65] / src / ca65 / scanner.c
index 8ccc1f6a6f31233f219c5447bce575fb60944ea5..cb4712a65b81fbacf5da17f3e2b3c3b0bc57767a 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (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       */
@@ -42,6 +42,7 @@
 #include <sys/stat.h>
 
 /* common */
+#include "addrsize.h"
 #include "chartype.h"
 #include "check.h"
 #include "fname.h"
@@ -95,7 +96,7 @@ struct InputFile_ {
 /* 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 */
@@ -121,8 +122,9 @@ struct DotKeyword {
     { ".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         },
@@ -152,12 +154,17 @@ struct DotKeyword {
     { ".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   },
@@ -167,6 +174,7 @@ struct DotKeyword {
     { ".FEATURE",      TOK_FEATURE     },
     { ".FILEOPT",      TOK_FILEOPT     },
     { ".FOPT",         TOK_FILEOPT     },
+    { ".FORCEIMPORT",   TOK_FORCEIMPORT },
     { ".FORCEWORD",    TOK_FORCEWORD   },
     { ".GLOBAL",       TOK_GLOBAL      },
     { ".GLOBALZP",     TOK_GLOBALZP    },
@@ -183,6 +191,7 @@ struct DotKeyword {
     { ".IFP02",                TOK_IFP02       },
     { ".IFP816",       TOK_IFP816      },
     { ".IFPC02",       TOK_IFPC02      },
+    { ".IFPSC02",              TOK_IFPSC02     },
     { ".IFREF",                TOK_IFREF       },
     { ".IMPORT",       TOK_IMPORT      },
     { ".IMPORTZP",     TOK_IMPORTZP    },
@@ -200,9 +209,9 @@ struct DotKeyword {
     { ".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         },
@@ -211,7 +220,10 @@ struct DotKeyword {
     { ".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       },
@@ -219,20 +231,27 @@ struct DotKeyword {
     { ".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    },
 };
 
@@ -294,7 +313,7 @@ void NewInputFile (const char* Name)
 
        /* 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
@@ -303,7 +322,7 @@ void NewInputFile (const char* Name)
        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 */
@@ -319,7 +338,7 @@ void NewInputFile (const char* Name)
        /* 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 */
@@ -368,7 +387,7 @@ void DoneInputFile (void)
 
 
 
-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;
@@ -566,13 +585,13 @@ static unsigned ReadStringConst (int StringTerm)
            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;
        }
@@ -638,7 +657,7 @@ Again:
                Tok = TOK_PC;
                return;
            } else {
-               Error (ERR_HEX_DIGIT_EXPECTED);
+               Error ("Hexadecimal digit expected");
            }
        }
 
@@ -646,7 +665,7 @@ Again:
        IVal = 0;
        while (IsXDigit (C)) {
            if (IVal & 0xF0000000) {
-               Error (ERR_NUM_OVERFLOW);
+               Error ("Overflow in hexadecimal number");
                IVal = 0;
            }
            IVal = (IVal << 4) + DigitVal (C);
@@ -664,14 +683,14 @@ Again:
 
        /* 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);
@@ -690,7 +709,7 @@ Again:
        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);
@@ -706,7 +725,6 @@ Again:
     if (C == '.') {
 
        /* Remember and skip the dot */
-       SVal[0] = C;
        NextChar ();
 
        /* Check if it's just a dot */
@@ -718,6 +736,7 @@ Again:
        } else {
 
            /* Read the remainder of the identifier */
+            SVal[0] = '.';
            ReadIdent (1);
 
            /* Dot keyword, search for it */
@@ -729,7 +748,7 @@ Again:
                    Tok = TOK_IDENT;
                } else {
                    /* Invalid pseudo instruction */
-                   Error (ERR_PSEUDO_EXPECTED);
+                   Error ("`%s' is not a recognized control command", SVal);
                    goto Again;
                }
            }
@@ -746,7 +765,7 @@ Again:
 
        /* Start character alone is not enough */
         if (SVal [1] == '\0') {
-           Error (ERR_IDENT_EXPECTED);
+           Error ("Invalid cheap local symbol");
                    goto Again;
        }
 
@@ -763,13 +782,31 @@ 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;
@@ -778,9 +815,14 @@ Again:
                    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;
@@ -837,7 +879,7 @@ CharAgain:
            NextChar ();
            if (C == '&') {
                NextChar ();
-               Tok = TOK_BAND;
+               Tok = TOK_BOOLAND;
            } else {
                Tok = TOK_AND;
            }
@@ -847,7 +889,7 @@ CharAgain:
            NextChar ();
            if (C == '|') {
                NextChar ();
-               Tok = TOK_BOR;
+               Tok = TOK_BOOLOR;
            } else {
                Tok = TOK_OR;
            }
@@ -880,6 +922,11 @@ CharAgain:
                    Tok = TOK_ULABEL;
                    break;
 
+                case '=':
+                    NextChar ();
+                    Tok = TOK_ASSIGN;
+                    break;
+
                default:
                    Tok = TOK_COLON;
                    break;
@@ -946,7 +993,7 @@ CharAgain:
 
        case '!':
            NextChar ();
-           Tok = TOK_BNOT;
+           Tok = TOK_BOOLNOT;
            return;
 
        case '>':
@@ -983,14 +1030,14 @@ CharAgain:
                /* 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 ();
                }
@@ -1041,7 +1088,7 @@ CharAgain:
     /* 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;
 }
@@ -1095,6 +1142,41 @@ int GetSubKey (const char** Keys, unsigned Count)
 
 
 
+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 */
 {