]> git.sur5r.net Git - cc65/commitdiff
Working
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 8 Apr 2002 18:52:47 +0000 (18:52 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 8 Apr 2002 18:52:47 +0000 (18:52 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1230 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/sim65/main.c
src/sim65/make/gcc.mak
src/sim65/scanner.c [new file with mode: 0644]
src/sim65/scanner.h [new file with mode: 0644]

index ec865bfdb3a126708581012c315d7a7eae98478a..51c64faae889d55499bc8485ac8f6f33cc0e0bb9 100644 (file)
 #include "chippath.h"
 #include "cpucore.h"
 #include "cputype.h"
+#include "error.h"
 #include "global.h"
 #include "memory.h"
+#include "scanner.h"
+
 
 
 /*****************************************************************************/
@@ -65,12 +68,16 @@ static void Usage (void)
     fprintf (stderr,
             "Usage: %s [options] file\n"
             "Short options:\n"
+                    "  -C name\t\tUse simulator config file\n"
+             "  -L dir\t\tSet a chip directory search path\n"
                     "  -V\t\t\tPrint the simulator version number\n"
                     "  -d\t\t\tDebug mode\n"
                     "  -h\t\t\tHelp (this text)\n"
                     "  -v\t\t\tIncrease verbosity\n"
-            "\n"
-            "Long options:\n"
+            "\n"
+            "Long options:\n"
+             "  --chipdir dir\t\tSet a chip directory search path\n"
+                    "  --config name\t\tUse simulator config file\n"
                     "  --cpu type\t\tSet cpu type\n"
                     "  --debug\t\tDebug mode\n"
             "  --help\t\tHelp (this text)\n"
@@ -81,6 +88,14 @@ static void Usage (void)
 
 
 
+static void OptChipDir (const char* Opt attribute ((unused)), const char* Arg)
+/* Handle the --chipdir option */
+{
+    AddChipPath (Arg);
+}
+
+
+
 static void OptCPU (const char* Opt, const char* Arg)
 /* Handle the --cpu option */
 {
@@ -95,8 +110,19 @@ static void OptCPU (const char* Opt, const char* Arg)
 
 
 
+static void OptConfig (const char* Opt attribute ((unused)), const char* Arg)
+/* Define the config file */
+{
+    if (CfgAvail ()) {
+       Error ("Cannot use -C twice");
+    }
+    CfgSetName (Arg);
+}
+
+
+
 static void OptDebug (const char* Opt attribute ((unused)),
-                     const char* Arg attribute ((unused)))
+                     const char* Arg attribute ((unused)))
 /* Simulator debug mode */
 {
     Debug = 1;
@@ -128,7 +154,7 @@ static void OptVersion (const char* Opt attribute ((unused)),
 /* Print the assembler version */
 {
     fprintf (stderr,
-                    "cc65 V%u.%u.%u\n",
+                    "sim65 V%u.%u.%u\n", 
                     VER_MAJOR, VER_MINOR, VER_PATCH);
 }
 
@@ -138,9 +164,11 @@ int main (int argc, char* argv[])
 {
     /* Program long options */
     static const LongOpt OptTab[] = {
+               { "--chipdir",          1,      OptChipDir              },
+               { "--config",           1,      OptConfig               },
         { "--cpu",                     1,      OptCPU                  },
                { "--debug",            0,      OptDebug                },
-       { "--help",             0,      OptHelp                 },
+       { "--help",             0,      OptHelp                 },
        { "--verbose",          0,      OptVerbose              },
        { "--version",          0,      OptVersion              },
     };
@@ -173,7 +201,7 @@ int main (int argc, char* argv[])
                    OptDebug (Arg, 0);
                    break;
 
-               case 'h':
+               case 'h':
                case '?':
                    OptHelp (Arg, 0);
                    break;
@@ -182,6 +210,14 @@ int main (int argc, char* argv[])
                    OptVerbose (Arg, 0);
                    break;
 
+               case 'C':
+                   OptConfig (Arg, GetArg (&I, 2));
+                   break;
+
+               case 'L':
+                   OptChipDir (Arg, GetArg (&I, 2));
+                   break;
+
                        case 'V':
                            OptVersion (Arg, 0);
                            break;
@@ -202,6 +238,14 @@ int main (int argc, char* argv[])
        ++I;
     }
 
+    /* Check if we have a valid configuration */
+    if (!CfgAvail ()) {
+               Error ("Simulator configuration missing");
+    }
+
+    /* Read the config file */
+//    CfgRead ();
+
     /* Initialize modules */
     AddChipPath ("chips");
     LoadChipLibrary ("ram.so");
index aab8d3974b8c1b765c11e33132f0877841fc0b91..c665851903eef38f37a6d46380f44a3ba9f85188 100644 (file)
@@ -18,7 +18,8 @@ OBJS =        chip.o          \
         error.o         \
        global.o        \
        main.o          \
-        memory.o
+        memory.o        \
+        scanner.o
 
 LIBS = $(COMMON)/common.a
 
diff --git a/src/sim65/scanner.c b/src/sim65/scanner.c
new file mode 100644 (file)
index 0000000..ed71c74
--- /dev/null
@@ -0,0 +1,516 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                scanner.c                                 */
+/*                                                                           */
+/*            Configuration file scanner for the sim65 6502 simulator        */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (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       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+/* common */
+#include "xsprintf.h"
+
+/* sim65 */
+#include "error.h"
+#include "scanner.h"
+
+
+
+/*****************************************************************************/
+/*                                          Data                                    */
+/*****************************************************************************/
+
+
+
+/* Current token and attributes */
+cfgtok_t               CfgTok;
+char                           CfgSVal [CFG_MAX_IDENT_LEN+1];
+unsigned long           CfgIVal;
+
+/* Error location */
+unsigned               CfgErrorLine;
+unsigned               CfgErrorCol;
+
+/* Input sources for the configuration */
+static const char*             CfgName         = 0;
+static const char*      CfgBuf                 = 0;
+
+/* Other input stuff */
+static int                     C               = ' ';
+static unsigned                InputLine       = 1;
+static unsigned                InputCol        = 0;
+static FILE*                   InputFile       = 0;
+
+
+
+/*****************************************************************************/
+/*                             Error handling                               */
+/*****************************************************************************/
+
+
+
+void CfgWarning (const char* Format, ...)
+/* Print a warning message adding file name and line number of the config file */
+{
+    char Buf [512];
+    va_list ap;
+
+    va_start (ap, Format);
+    xvsprintf (Buf, sizeof (Buf), Format, ap);
+    va_end (ap);
+
+    Warning ("%s(%u): %s", CfgGetName(), CfgErrorLine, Buf);
+}
+
+
+
+void CfgError (const char* Format, ...)
+/* Print an error message adding file name and line number of the config file */
+{
+    char Buf [512];
+    va_list ap;
+
+    va_start (ap, Format);
+    xvsprintf (Buf, sizeof (Buf), Format, ap);
+    va_end (ap);
+
+    Error ("%s(%u): %s", CfgGetName(), CfgErrorLine, Buf);
+}
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+static void NextChar (void)
+/* Read the next character from the input file */
+{
+    if (CfgBuf) {
+       /* Read from buffer */
+       C = (unsigned char)(*CfgBuf);
+       if (C == 0) {
+           C = EOF;
+       } else {
+           ++CfgBuf;
+       }
+    } else {
+       /* Read from the file */
+       C = getc (InputFile);
+    }
+
+    /* Count columns */
+    if (C != EOF) {
+       ++InputCol;
+    }
+
+    /* Count lines */
+    if (C == '\n') {
+       ++InputLine;
+       InputCol = 0;
+    }
+}
+
+
+
+static unsigned DigitVal (int C)
+/* Return the value for a numeric digit */
+{
+    if (isdigit (C)) {
+       return C - '0';
+    } else {
+       return toupper (C) - 'A' + 10;
+    }
+}
+
+
+
+void CfgNextTok (void)
+/* Read the next token from the input stream */
+{
+    unsigned I;
+
+
+Again:
+    /* Skip whitespace */
+    while (isspace (C)) {
+       NextChar ();
+    }
+
+    /* Remember the current position */
+    CfgErrorLine = InputLine;
+    CfgErrorCol  = InputCol;
+
+    /* Identifier? */
+    if (C == '_' || isalpha (C)) {
+
+       /* Read the identifier */
+       I = 0;
+       while (C == '_' || isalnum (C)) {
+           if (I < CFG_MAX_IDENT_LEN) {
+               CfgSVal [I++] = C;
+           }
+           NextChar ();
+       }
+       CfgSVal [I] = '\0';
+       CfgTok = CFGTOK_IDENT;
+       return;
+    }
+
+    /* Hex number? */
+    if (C == '$') {
+       NextChar ();
+       if (!isxdigit (C)) {
+           Error ("%s(%u): Hex digit expected", CfgName, InputLine);
+       }
+       CfgIVal = 0;
+       while (isxdigit (C)) {
+                   CfgIVal = CfgIVal * 16 + DigitVal (C);
+           NextChar ();
+       }
+       CfgTok = CFGTOK_INTCON;
+       return;
+    }
+
+    /* Decimal number? */
+    if (isdigit (C)) {
+       CfgIVal = 0;
+       while (isdigit (C)) {
+                   CfgIVal = CfgIVal * 10 + DigitVal (C);
+           NextChar ();
+       }
+       CfgTok = CFGTOK_INTCON;
+       return;
+    }
+
+    /* Other characters */
+    switch (C) {
+
+       case '{':
+           NextChar ();
+           CfgTok = CFGTOK_LCURLY;
+           break;
+
+       case '}':
+           NextChar ();
+           CfgTok = CFGTOK_RCURLY;
+           break;
+
+       case ';':
+           NextChar ();
+           CfgTok = CFGTOK_SEMI;
+           break;
+
+       case '.':
+           NextChar ();
+           CfgTok = CFGTOK_DOT;
+           break;
+
+       case ',':
+           NextChar ();
+           CfgTok = CFGTOK_COMMA;
+           break;
+
+       case '=':
+           NextChar ();
+           CfgTok = CFGTOK_EQ;
+           break;
+
+        case ':':
+           NextChar ();
+           CfgTok = CFGTOK_COLON;
+           break;
+
+        case '\"':
+           NextChar ();
+           I = 0;
+           while (C != '\"') {
+               if (C == EOF || C == '\n') {
+                   Error ("%s(%u): Unterminated string", CfgName, InputLine);
+               }
+               if (I < CFG_MAX_IDENT_LEN) {
+                   CfgSVal [I++] = C;
+               }
+               NextChar ();
+           }
+                   NextChar ();
+           CfgSVal [I] = '\0';
+           CfgTok = CFGTOK_STRCON;
+           break;
+
+        case '#':
+           /* Comment */
+           while (C != '\n' && C != EOF) {
+               NextChar ();
+           }
+           if (C != EOF) {
+               goto Again;
+           }
+           CfgTok = CFGTOK_EOF;
+           break;
+
+        case EOF:
+           CfgTok = CFGTOK_EOF;
+           break;
+
+       default:
+           Error ("%s(%u): Invalid character `%c'", CfgName, InputLine, C);
+
+    }
+}
+
+
+
+void CfgConsume (cfgtok_t T, const char* Msg)
+/* Skip a token, print an error message if not found */
+{
+    if (CfgTok != T) {
+               CfgError (Msg);
+    }
+    CfgNextTok ();
+}
+
+
+
+void CfgConsumeSemi (void)
+/* Consume a semicolon */
+{
+    CfgConsume (CFGTOK_SEMI, "`;' expected");
+}
+
+
+
+void CfgConsumeColon (void)
+/* Consume a colon */
+{
+    CfgConsume (CFGTOK_COLON, "`:' expected");
+}
+
+
+
+void CfgOptionalComma (void)
+/* Consume a comma if there is one */
+{
+    if (CfgTok == CFGTOK_COMMA) {
+               CfgNextTok ();
+    }
+}
+
+
+
+void CfgOptionalAssign (void)
+/* Consume an equal sign if there is one */
+{
+    if (CfgTok == CFGTOK_EQ) {
+               CfgNextTok ();
+    }
+}
+
+
+
+void CfgAssureInt (void)
+/* Make sure the next token is an integer */
+{
+    if (CfgTok != CFGTOK_INTCON) {
+               CfgError ("Integer constant expected");
+    }
+}
+
+
+
+void CfgAssureStr (void)
+/* Make sure the next token is a string constant */
+{
+    if (CfgTok != CFGTOK_STRCON) {
+               CfgError ("String constant expected");
+    }
+}
+
+
+
+void CfgAssureIdent (void)
+/* Make sure the next token is an identifier */
+{
+    if (CfgTok != CFGTOK_IDENT) {
+               CfgError ("Identifier expected");
+    }
+}
+
+
+
+void CfgRangeCheck (unsigned long Lo, unsigned long Hi)
+/* Check the range of CfgIVal */
+{
+    if (CfgIVal < Lo || CfgIVal > Hi) {
+       CfgError ("Range error");
+    }
+}
+
+
+
+void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name)
+/* Map an identifier to one of the special tokens in the table */
+{
+    unsigned I;
+
+    /* We need an identifier */
+    if (CfgTok == CFGTOK_IDENT) {
+
+       /* Make it upper case */
+       I = 0;
+       while (CfgSVal [I]) {
+           CfgSVal [I] = toupper (CfgSVal [I]);
+           ++I;
+       }
+
+               /* Linear search */
+       for (I = 0; I < Size; ++I) {
+           if (strcmp (CfgSVal, Table [I].Ident) == 0) {
+               CfgTok = Table [I].Tok;
+               return;
+           }
+       }
+
+    }
+
+    /* Not found or no identifier */
+    Error ("%s(%u): %s expected", CfgName, InputLine, Name);
+}
+
+
+
+void CfgBoolToken (void)
+/* Map an identifier or integer to a boolean token */
+{
+    static const IdentTok Booleans [] = {
+               {   "YES",      CFGTOK_TRUE     },
+       {   "NO",       CFGTOK_FALSE    },
+        {   "TRUE",     CFGTOK_TRUE     },
+        {   "FALSE",    CFGTOK_FALSE    },
+    };
+
+    /* If we have an identifier, map it to a boolean token */
+    if (CfgTok == CFGTOK_IDENT) {
+       CfgSpecialToken (Booleans, ENTRY_COUNT (Booleans), "Boolean");
+    } else {
+       /* We expected an integer here */
+       if (CfgTok != CFGTOK_INTCON) {
+           CfgError ("Boolean value expected");
+       }
+       CfgTok = (CfgIVal == 0)? CFGTOK_FALSE : CFGTOK_TRUE;
+    }
+}
+
+
+
+void CfgSetName (const char* Name)
+/* Set a name for a config file */
+{
+    CfgName = Name;
+}
+
+
+
+const char* CfgGetName (void)
+/* Get the name of the config file */
+{
+    if (CfgName) {
+       return CfgName;
+    } else if (CfgBuf) {
+       return "[builtin config]";
+    } else {
+       return "";
+    }
+}
+
+
+
+void CfgSetBuf (const char* Buf)
+/* Set a memory buffer for the config */
+{
+    CfgBuf = Buf;
+}
+
+
+
+int CfgAvail (void)
+/* Return true if we have a configuration available */
+{
+    return CfgName != 0 || CfgBuf != 0;
+}
+
+
+
+void CfgOpenInput (void)
+/* Open the input file if we have one */
+{
+    /* If we have a config name given, open the file, otherwise we will read
+     * from a buffer.
+     */
+    if (!CfgBuf) {
+
+       /* Open the file */
+       InputFile = fopen (CfgName, "r");
+       if (InputFile == 0) {
+           Error ("Cannot open `%s': %s", CfgName, strerror (errno));
+       }
+
+    }
+
+    /* Initialize variables */
+    C         = ' ';
+    InputLine = 1;
+    InputCol  = 0;
+
+    /* Start the ball rolling ... */
+    CfgNextTok ();
+}
+
+
+
+void CfgCloseInput (void)
+/* Close the input file if we have one */
+{
+    /* Close the input file if we had one */
+    if (InputFile) {
+        (void) fclose (InputFile);
+       InputFile = 0;
+    }
+}
+
+
+
diff --git a/src/sim65/scanner.h b/src/sim65/scanner.h
new file mode 100644 (file)
index 0000000..db8142e
--- /dev/null
@@ -0,0 +1,164 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                scanner.h                                 */
+/*                                                                           */
+/*            Configuration file scanner for the sim65 6502 simulator        */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (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       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef SCANNER_H
+#define SCANNER_H
+
+
+
+/*****************************************************************************/
+/*                                          Data                                    */
+/*****************************************************************************/
+
+
+
+/* Config file tokens */
+typedef enum {
+    CFGTOK_NONE,
+    CFGTOK_INTCON,
+    CFGTOK_STRCON,
+    CFGTOK_IDENT,
+    CFGTOK_LCURLY,
+    CFGTOK_RCURLY,
+    CFGTOK_SEMI,
+    CFGTOK_COMMA,
+    CFGTOK_EQ,
+    CFGTOK_COLON,
+    CFGTOK_DOT,
+    CFGTOK_EOF,
+
+    /* Special identifiers */
+    CFGTOK_TRUE,
+    CFGTOK_FALSE
+               
+} cfgtok_t;
+
+
+
+/* Mapping table entry, special identifier --> token */
+typedef struct IdentTok IdentTok;
+struct IdentTok {
+    const char*        Ident;          /* Identifier */
+    cfgtok_t   Tok;            /* Token for identifier */
+};
+#define ENTRY_COUNT(s)         (sizeof (s) / sizeof (s [0]))
+
+
+
+/* Current token and attributes */
+#define CFG_MAX_IDENT_LEN  255
+extern cfgtok_t                CfgTok;
+extern char                    CfgSVal [CFG_MAX_IDENT_LEN+1];
+extern unsigned long   CfgIVal;
+
+/* Error location */
+extern unsigned                CfgErrorLine;
+extern unsigned                CfgErrorCol;
+
+
+
+/*****************************************************************************/
+/*                                          Code                                    */
+/*****************************************************************************/
+
+
+
+void CfgWarning (const char* Format, ...) attribute((format(printf,1,2)));
+/* Print a warning message adding file name and line number of the config file */
+
+void CfgError (const char* Format, ...) attribute((format(printf,1,2)));
+/* Print an error message adding file name and line number of the config file */
+
+void CfgNextTok (void);
+/* Read the next token from the input stream */
+
+void CfgConsume (cfgtok_t T, const char* Msg);
+/* Skip a token, print an error message if not found */
+
+void CfgConsumeSemi (void);
+/* Consume a semicolon */
+
+void CfgConsumeColon (void);
+/* Consume a colon */
+
+void CfgOptionalComma (void);
+/* Consume a comma if there is one */
+
+void CfgOptionalAssign (void);
+/* Consume an equal sign if there is one */
+
+void CfgAssureInt (void);
+/* Make sure the next token is an integer */
+
+void CfgAssureStr (void);
+/* Make sure the next token is a string constant */
+
+void CfgAssureIdent (void);
+/* Make sure the next token is an identifier */
+
+void CfgRangeCheck (unsigned long Lo, unsigned long Hi);
+/* Check the range of CfgIVal */
+
+void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name);
+/* Map an identifier to one of the special tokens in the table */
+
+void CfgBoolToken (void);
+/* Map an identifier or integer to a boolean token */
+
+void CfgSetName (const char* Name);
+/* Set a name for a config file */
+
+const char* CfgGetName (void);
+/* Get the name of the config file */
+
+void CfgSetBuf (const char* Buf);
+/* Set a memory buffer for the config */
+
+int CfgAvail (void);
+/* Return true if we have a configuration available */
+
+void CfgOpenInput (void);
+/* Open the input file if we have one */
+
+void CfgCloseInput (void);
+/* Close the input file if we have one */
+
+
+
+/* End of scanner.h */
+#endif
+
+
+