]> git.sur5r.net Git - cc65/commitdiff
Some basic support for the 65C02 CPU.
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 14 Jun 2000 08:18:19 +0000 (08:18 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Wed, 14 Jun 2000 08:18:19 +0000 (08:18 +0000)
Use the command line module from common/ and support long options.
Rename the include module to incpath (as in the assembler).

git-svn-id: svn://svn.cc65.org/cc65/trunk@67 b7a2c559-68d2-44c3-8de9-860c34a00d81

16 files changed:
src/cc65/codegen.c
src/cc65/compile.c
src/cc65/cpu.c [new file with mode: 0644]
src/cc65/cpu.h [new file with mode: 0644]
src/cc65/include.c [deleted file]
src/cc65/include.h [deleted file]
src/cc65/incpath.c [new file with mode: 0644]
src/cc65/incpath.h [new file with mode: 0644]
src/cc65/io.c
src/cc65/io.h
src/cc65/main.c
src/cc65/make/gcc.mak
src/cc65/make/watcom.mak
src/cc65/optimize.c
src/cc65/preproc.c
src/cc65/scanner.c

index 6b3fc32a9c2a22048054bcc47a16c7592152b93f..3704aebf50fd476d2e2190d670f623a84aba01d0 100644 (file)
@@ -41,6 +41,7 @@
 #include "asmcode.h"
 #include "asmlabel.h"
 #include "check.h"
+#include "cpu.h"
 #include "error.h"
 #include "global.h"
 #include "io.h"
@@ -157,6 +158,11 @@ void g_preamble (void)
     AddCodeLine (".fopt\t\tcompiler,\"cc65 v %u.%u.%u\"", VER_MAJOR, VER_MINOR, VER_PATCH);
     AddEmptyLine ();
 
+    /* If we're producing code for some other CPU, switch the command set */
+    if (CPU == CPU_65C02) {
+       AddCodeLine (".pc02");
+    }
+
     /* Allow auto import for runtime library routines */
     AddCodeLine (".autoimport\ton");
 
@@ -920,7 +926,7 @@ void g_getind (unsigned flags, unsigned offs)
 }
 
 
-                                                        
+
 void g_leasp (int offs)
 /* Fetch the address of the specified symbol into the primary register */
 {
@@ -3096,14 +3102,26 @@ void g_inc (unsigned flags, unsigned long val)
 
        case CF_CHAR:
            if (flags & CF_FORCECHAR) {
-               AddCodeLine ("\tclc");
-               AddCodeLine ("\tadc\t#$%02X", val & 0xFF);
+               if (CPU == CPU_65C02 && val <= 2) {
+                   while (val--) {
+                       AddCodeLine ("\tina");
+                   }
+               } else {
+                   AddCodeLine ("\tclc");
+                   AddCodeLine ("\tadc\t#$%02X", val & 0xFF);
+               }
                break;
            }
            /* FALLTHROUGH */
 
        case CF_INT:
-           if (FavourSize) {
+           if (CPU == CPU_65C02 && val == 1) {
+               AddCodeLine ("\tina");
+               AddCodeLine ("\tbne\t*+3");
+               AddCodeLine ("\tinx");
+               /* Tell the optimizer that the X register may be invalid */
+               AddCodeHint ("x:!");
+           } else if (FavourSize) {
                /* Use jsr calls */
                if (val <= 8) {
                    AddCodeLine ("\tjsr\tincax%u", val);
@@ -3172,8 +3190,14 @@ void g_dec (unsigned flags, unsigned long val)
 
        case CF_CHAR:
            if (flags & CF_FORCECHAR) {
-               AddCodeLine ("\tsec");
-               AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
+               if (CPU == CPU_65C02 && val <= 2) {
+                   while (val--) {
+                       AddCodeLine ("\tdea");
+                   }
+               } else {
+                   AddCodeLine ("\tsec");
+                   AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
+               }
                break;
            }
            /* FALLTHROUGH */
index 5225d9b68511de25633c2211a05db08ca8438391..31c88fd3a521c7f1e9cd8b94ec4236e84b08fa8e 100644 (file)
@@ -44,7 +44,7 @@
 #include "expr.h"
 #include "function.h"
 #include "global.h"
-#include "include.h"
+#include "incpath.h"
 #include "io.h"
 #include "litpool.h"
 #include "macrotab.h"
diff --git a/src/cc65/cpu.c b/src/cc65/cpu.c
new file mode 100644 (file)
index 0000000..98e92e3
--- /dev/null
@@ -0,0 +1,50 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                  cpu.c                                   */
+/*                                                                           */
+/*                          CPU type definitions                            */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2000     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 "cpu.h"
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+/* Current CPU */
+CPUType        CPU = CPU_6502;
+
+
+
diff --git a/src/cc65/cpu.h b/src/cc65/cpu.h
new file mode 100644 (file)
index 0000000..003bce9
--- /dev/null
@@ -0,0 +1,63 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                  cpu.h                                   */
+/*                                                                           */
+/*                          CPU type definitions                            */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2000     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 CPU_H
+#define CPU_H
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+/* Supported CPUs */
+typedef enum CPUType {
+    CPU_6502,
+    CPU_65C02
+} CPUType;
+
+/* Current CPU */
+extern CPUType CPU;
+
+
+
+/* End of cpu.h */
+
+#endif
+
+
+
diff --git a/src/cc65/include.c b/src/cc65/include.c
deleted file mode 100644 (file)
index e68227f..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * include.c - Include file handling for cc65
- *
- * Ullrich von Bassewitz, 18.08.1998
- */
-
-
-
-#include <stdio.h>
-#include <string.h>
-#if defined(_MSC_VER)
-/* Microsoft compiler */
-#  include <io.h>
-#  define R_OK 4
-#else
-/* Anyone else */
-#  include <unistd.h>
-#endif
-
-#include "mem.h"
-#include "include.h"
-
-
-
-/*****************************************************************************/
-/*                                  data                                    */
-/*****************************************************************************/
-
-
-
-static char* SysIncludePath  = 0;
-static char* UserIncludePath = 0;
-
-
-
-/*****************************************************************************/
-/*                                  code                                    */
-/*****************************************************************************/
-
-
-
-static char* Add (char* Orig, const char* New)
-/* Create a new path from Orig and New, delete Orig, return the result */
-{
-    unsigned OrigLen, NewLen;
-    char* NewPath;
-
-    /* Get the length of the original string */
-    OrigLen = Orig? strlen (Orig) : 0;
-
-    /* Get the length of the new path */
-    NewLen = strlen (New);
-
-    /* Check for a trailing path separator and remove it */
-    if (NewLen > 0 && (New [NewLen-1] == '\\' || New [NewLen-1] == '/')) {
-       --NewLen;
-    }
-
-    /* Allocate memory for the new string */
-    NewPath = xmalloc (OrigLen + NewLen + 2);
-
-    /* Copy the strings */
-    memcpy (NewPath, Orig, OrigLen);
-    memcpy (NewPath+OrigLen, New, NewLen);
-    NewPath [OrigLen+NewLen+0] = ';';
-    NewPath [OrigLen+NewLen+1] = '\0';
-
-    /* Delete the original path */
-    xfree (Orig);
-
-    /* Return the new path */
-    return NewPath;
-}
-
-
-
-static char* Find (const char* Path, const char* File)
-/* Search for a file in a list of directories. If found, return the complete
- * name including the path in a malloced data area, if not found, return 0.
- */
-{
-    const char* P;
-    int Max;
-    char PathName [FILENAME_MAX];
-
-    /* Initialize variables */
-    Max = sizeof (PathName) - strlen (File) - 2;
-    if (Max < 0) {
-       return 0;
-    }
-    P = Path;
-
-    /* Handle a NULL pointer as replacement for an empty string */
-    if (P == 0) {
-       P = "";
-    }
-
-    /* Start the search */
-    while (*P) {
-        /* Copy the next path element into the buffer */
-       int Count = 0;
-       while (*P != '\0' && *P != ';' && Count < Max) {
-           PathName [Count++] = *P++;
-       }
-
-       /* Add a path separator and the filename */
-       if (Count) {
-           PathName [Count++] = '/';
-       }
-       strcpy (PathName + Count, File);
-
-       /* Check if this file exists */
-       if (access (PathName, R_OK) == 0) {
-           /* The file exists */
-           return xstrdup (PathName);
-       }
-
-       /* Skip a list separator if we have one */
-       if (*P == ';') {
-           ++P;
-       }
-    }
-
-    /* Not found */
-    return 0;
-}
-
-
-
-void AddIncludePath (const char* NewPath, unsigned Where)
-/* Add a new include path to the existing one */
-{
-    /* Allow a NULL path */
-    if (NewPath) {
-       if (Where & INC_SYS) {
-           SysIncludePath = Add (SysIncludePath, NewPath);
-       }
-       if (Where & INC_USER) {
-           UserIncludePath = Add (UserIncludePath, NewPath);
-       }
-    }
-}
-
-
-
-char* FindInclude (const char* Name, unsigned Where)
-/* Find an include file. Return a pointer to a malloced area that contains
- * the complete path, if found, return 0 otherwise.
- */
-{
-    if (Where & INC_SYS) {
-       /* Search in the system include directories */
-       return Find (SysIncludePath, Name);
-    }
-    if (Where & INC_USER) {
-       /* Search in the user include directories */
-       return Find (UserIncludePath, Name);
-    }
-    return 0;
-}
-
-
-
-
diff --git a/src/cc65/include.h b/src/cc65/include.h
deleted file mode 100644 (file)
index 9d0b074..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * include.h - Include file handling for cc65
- *
- * Ullrich von Bassewitz, 18.08.1998
- */
-
-
-
-#ifndef INCLUDE_H
-#define INCLUDE_H
-
-
-
-/*****************************************************************************/
-/*                                  data                                    */
-/*****************************************************************************/
-
-
-
-#define INC_SYS                0x0001          /* Add to system include path */
-#define INC_USER       0x0002          /* Add to user include path */
-
-
-
-/*****************************************************************************/
-/*                                  code                                    */
-/*****************************************************************************/
-
-
-
-void AddIncludePath (const char* NewPath, unsigned Where);
-/* Add a new include path to the existing one */
-
-char* FindInclude (const char* Name, unsigned Where);
-/* Find an include file. Return a pointer to a malloced area that contains
- * the complete path, if found, return 0 otherwise.
- */
-
-
-
-/* End of include.h */
-#endif
-
-
-
diff --git a/src/cc65/incpath.c b/src/cc65/incpath.c
new file mode 100644 (file)
index 0000000..0349c25
--- /dev/null
@@ -0,0 +1,190 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                incpath.c                                 */
+/*                                                                           */
+/*                     Include path handling for cc65                       */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2000      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 <stdio.h>
+#include <string.h>
+#if defined(_MSC_VER)
+/* Microsoft compiler */
+#  include <io.h>
+#  define R_OK 4
+#else
+/* Anyone else */
+#  include <unistd.h>
+#endif
+
+#include "mem.h"
+#include "incpath.h"
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+static char* SysIncludePath  = 0;
+static char* UserIncludePath = 0;
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+static char* Add (char* Orig, const char* New)
+/* Create a new path from Orig and New, delete Orig, return the result */
+{
+    unsigned OrigLen, NewLen;
+    char* NewPath;
+
+    /* Get the length of the original string */
+    OrigLen = Orig? strlen (Orig) : 0;
+
+    /* Get the length of the new path */
+    NewLen = strlen (New);
+
+    /* Check for a trailing path separator and remove it */
+    if (NewLen > 0 && (New [NewLen-1] == '\\' || New [NewLen-1] == '/')) {
+       --NewLen;
+    }
+
+    /* Allocate memory for the new string */
+    NewPath = xmalloc (OrigLen + NewLen + 2);
+
+    /* Copy the strings */
+    memcpy (NewPath, Orig, OrigLen);
+    memcpy (NewPath+OrigLen, New, NewLen);
+    NewPath [OrigLen+NewLen+0] = ';';
+    NewPath [OrigLen+NewLen+1] = '\0';
+
+    /* Delete the original path */
+    xfree (Orig);
+
+    /* Return the new path */
+    return NewPath;
+}
+
+
+
+static char* Find (const char* Path, const char* File)
+/* Search for a file in a list of directories. If found, return the complete
+ * name including the path in a malloced data area, if not found, return 0.
+ */
+{
+    const char* P;
+    int Max;
+    char PathName [FILENAME_MAX];
+
+    /* Initialize variables */
+    Max = sizeof (PathName) - strlen (File) - 2;
+    if (Max < 0) {
+       return 0;
+    }
+    P = Path;
+
+    /* Handle a NULL pointer as replacement for an empty string */
+    if (P == 0) {
+       P = "";
+    }
+
+    /* Start the search */
+    while (*P) {
+        /* Copy the next path element into the buffer */
+       int Count = 0;
+       while (*P != '\0' && *P != ';' && Count < Max) {
+           PathName [Count++] = *P++;
+       }
+
+       /* Add a path separator and the filename */
+       if (Count) {
+           PathName [Count++] = '/';
+       }
+       strcpy (PathName + Count, File);
+
+       /* Check if this file exists */
+       if (access (PathName, R_OK) == 0) {
+           /* The file exists */
+           return xstrdup (PathName);
+       }
+
+       /* Skip a list separator if we have one */
+       if (*P == ';') {
+           ++P;
+       }
+    }
+
+    /* Not found */
+    return 0;
+}
+
+
+
+void AddIncludePath (const char* NewPath, unsigned Where)
+/* Add a new include path to the existing one */
+{
+    /* Allow a NULL path */
+    if (NewPath) {
+       if (Where & INC_SYS) {
+           SysIncludePath = Add (SysIncludePath, NewPath);
+       }
+       if (Where & INC_USER) {
+           UserIncludePath = Add (UserIncludePath, NewPath);
+       }
+    }
+}
+
+
+
+char* FindInclude (const char* Name, unsigned Where)
+/* Find an include file. Return a pointer to a malloced area that contains
+ * the complete path, if found, return 0 otherwise.
+ */
+{
+    if (Where & INC_SYS) {
+       /* Search in the system include directories */
+       return Find (SysIncludePath, Name);
+    }
+    if (Where & INC_USER) {
+       /* Search in the user include directories */
+       return Find (UserIncludePath, Name);
+    }
+    return 0;
+}
+
+
+
diff --git a/src/cc65/incpath.h b/src/cc65/incpath.h
new file mode 100644 (file)
index 0000000..6e83de2
--- /dev/null
@@ -0,0 +1,72 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                incpath.h                                 */
+/*                                                                           */
+/*                     Include path handling for cc65                       */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2000      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 INCPATH_H
+#define INCPATH_H
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+#define INC_SYS                0x0001          /* Add to system include path */
+#define INC_USER       0x0002          /* Add to user include path */
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+void AddIncludePath (const char* NewPath, unsigned Where);
+/* Add a new include path to the existing one */
+
+char* FindInclude (const char* Name, unsigned Where);
+/* Find an include file. Return a pointer to a malloced area that contains
+ * the complete path, if found, return 0 otherwise.
+ */
+
+
+
+/* End of incpath.h */
+#endif
+
+
+
index 517aa9520c299e69c5a1f54afdb68a796476a6e8..c94d8b8631ad0259058f78c9c51103e1642fed15 100644 (file)
@@ -112,7 +112,7 @@ static void CloseInclude (void)
 
 
 
-int readline (void)
+int NextLine (void)
 /* Get a line from the current input.  Returns -1 on end of file. */
 {
     unsigned   Len;
index aa836700e0a7fd8977f189419589e23b71308c1f..46671c0d124d94b9fb8cd21ff51593576ff77fe5 100644 (file)
@@ -73,7 +73,7 @@ int gch (void);
  * pointer (no end of line check is performed).
  */
 
-int readline (void);
+int NextLine (void);
 /* Get a line from the current input.  Returns -1 on end of file. */
 
 
index e86f6590052036663e3593343263a1dd535d83b9..e23e2f33a49b85ca290470c7374227761f0dc097 100644 (file)
@@ -1,4 +1,37 @@
-/* CC65 main program */
+/*****************************************************************************/
+/*                                                                           */
+/*                                 main.c                                   */
+/*                                                                           */
+/*                            cc65 main program                             */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2000      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 <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
 
+#include "../common/cmdline.h"
 #include "../common/version.h"
 
 #include "asmcode.h"
 #include "compile.h"
+#include "cpu.h"
 #include "error.h"
 #include "global.h"
-#include "include.h"
+#include "incpath.h"
 #include "io.h"
 #include "macrotab.h"
 #include "mem.h"
@@ -50,57 +85,46 @@ static const char* TargetNames [] = {
 
 
 
-static void usage (int ExitCode)
+static void Usage (void)
 {
-    fputs ("Usage: cc65 [options] file\n"
-          "\t-d\t\tDebug mode\n"
-          "\t-g\t\tAdd debug info to object files\n"
-          "\t-h\t\tPrint this help\n"
-          "\t-j\t\tDefault characters are signed\n"
-          "\t-o name\t\tName the output file\n"
-          "\t-tx\t\tSet target system x\n"
-          "\t-v\t\tVerbose mode\n"
-          "\t-A\t\tStrict ANSI mode\n"
-          "\t-Cl\t\tMake local variables static\n"
-          "\t-Dsym[=defn]\tDefine a symbol\n"
-          "\t-I path\t\tSet include directory\n"
-          "\t-O\t\tOptimize code\n"
-          "\t-Oi\t\tOptimize code, inline more code\n"
-          "\t-Or\t\tEnable register variables\n"
-          "\t-Os\t\tInline some known functions\n"
-          "\t-T\t\tInclude source as comment\n"
-          "\t-V\t\tPrint version number\n"
-          "\t-W\t\tSuppress warnings\n",
-          stderr);
-    exit (ExitCode);
-}
-
-
-
-static char* GetArg (int* ArgNum, char* argv [], unsigned Len)
-/* Get an option argument */
-{
-    char* Arg = argv [*ArgNum];
-    if (Arg [Len] != '\0') {
-       /* Argument appended */
-       return Arg + Len;
-    } else {
-       /* Separate argument */
-       Arg = argv [*ArgNum + 1];
-       if (Arg == 0) {
-           /* End of arguments */
-           fprintf (stderr, "Option requires an argument: %s\n", argv [*ArgNum]);
-           exit (EXIT_FAILURE);
-       }
-       ++(*ArgNum);
-       return Arg;
-    }
+    fprintf (stderr,
+            "Usage: cc65 [options] file\n"
+            "Short options:\n"
+                    "  -d\t\t\tDebug mode\n"
+                    "  -g\t\t\tAdd debug info to object file\n"
+                    "  -h\t\t\tPrint this help\n"
+                    "  -j\t\t\tDefault characters are signed\n"
+                    "  -o name\t\tName the output file\n"
+                    "  -t sys\t\tSet the target system\n"
+                    "  -v\t\t\tIncrease verbosity\n"
+                    "  -A\t\t\tStrict ANSI mode\n"
+                    "  -Cl\t\t\tMake local variables static\n"
+                    "  -Dsym[=defn]\t\tDefine a symbol\n"
+                    "  -I path\t\tSet an include directory search path\n"
+                    "  -O\t\t\tOptimize code\n"
+                    "  -Oi\t\t\tOptimize code, inline more code\n"
+                    "  -Or\t\t\tEnable register variables\n"
+                    "  -Os\t\t\tInline some known functions\n"
+                    "  -T\t\t\tInclude source as comment\n"
+                    "  -V\t\t\tPrint the compiler version number\n"
+                    "  -W\t\t\tSuppress warnings\n"
+            "\n"
+            "Long options:\n"
+                    "  --ansi\t\tStrict ANSI mode\n"
+                    "  --cpu type\t\tSet cpu type\n"
+                    "  --debug-info\t\tAdd debug info to object file\n"
+            "  --help\t\tHelp (this text)\n"
+                    "  --include-dir dir\tSet an include directory search path\n"
+                    "  --signed-chars\tDefault characters are signed\n"
+                    "  --target sys\t\tSet the target system\n"
+                    "  --verbose\t\tIncrease verbosity\n"
+                    "  --version\t\tPrint the compiler version number\n");
 }
 
 
 
-/* Define a CBM system */
 static void cbmsys (const char* sys)
+/* Define a CBM system */
 {
     AddNumericMacro ("__CBM__", 1);
     AddNumericMacro (sys, 1);
@@ -133,8 +157,8 @@ static int MapSys (const char* Name)
 
 
 
-/* Define a target system */
 static void SetSys (const char* Sys)
+/* Define a target system */
 {
     switch (Target = MapSys (Sys)) {
 
@@ -142,7 +166,7 @@ static void SetSys (const char* Sys)
            break;
 
        case TGT_ATARI:
-           AddNumericMacro ("__ATARI__", 1);
+           AddNumericMacro ("__ATARI__", 1);
            break;
 
        case TGT_C64:
@@ -184,21 +208,12 @@ static void SetSys (const char* Sys)
 
        default:
            fputs ("Unknown system type\n", stderr);
-           usage (EXIT_FAILURE);
+           exit (EXIT_FAILURE);
     }
 }
 
 
 
-static void InvSym (const char* Def)
-/* Print an error about an invalid macro definition and die */
-{
-    fprintf (stderr, "Invalid macro definition: `%s'\n", Def);
-    exit (EXIT_FAILURE);
-}
-
-
-
 static void DefineSym (const char* Def)
 /* Define a symbol on the command line */
 {
@@ -206,7 +221,7 @@ static void DefineSym (const char* Def)
 
     /* The symbol must start with a character or underline */
     if (Def [0] != '_' && !isalpha (Def [0])) {
-       InvSym (Def);
+       InvDef (Def);
     }
 
     /* Check the symbol name */
@@ -217,7 +232,7 @@ static void DefineSym (const char* Def)
     /* Do we have a value given? */
     if (*P != '=') {
        if (*P != '\0') {
-           InvSym (Def);
+           InvDef (Def);
        }
        /* No value given. Define the macro with the value 1 */
        AddNumericMacro (Def, 1);
@@ -236,29 +251,147 @@ static void DefineSym (const char* Def)
        /* Define this as a macro */
        AddTextMacro (S, Q);
 
-       /* Release the allocated memory */
-       xfree (S);
+       /* Release the allocated memory */
+       xfree (S);
+    }
+}
+
+
+
+static void OptAnsi (const char* Opt, const char* Arg)
+/* Compile in strict ANSI mode */
+{
+    ANSI = 1;
+}
+
+
+
+static void OptCPU (const char* Opt, const char* Arg)
+/* Handle the --cpu option */
+{
+    if (Arg == 0) {
+       NeedArg (Opt);
+    }
+    if (strcmp (Arg, "6502") == 0) {
+               CPU = CPU_6502;
+    } else if (strcmp (Arg, "65C02") == 0) {
+       CPU = CPU_65C02;
+    } else {
+       fprintf (stderr, "Invalid CPU: `%s'\n", Arg);
+       exit (EXIT_FAILURE);
+    }
+}
+
+
+
+static void OptDebugInfo (const char* Opt, const char* Arg)
+/* Add debug info to the object file */
+{
+    DebugInfo = 1;
+}
+
+
+
+static void OptHelp (const char* Opt, const char* Arg)
+/* Print usage information and exit */
+{
+    Usage ();
+    exit (EXIT_SUCCESS);
+}
+
+
+
+static void OptIncludeDir (const char* Opt, const char* Arg)
+/* Add an include search path */
+{
+    if (Arg == 0) {
+       NeedArg (Opt);
+    }
+    AddIncludePath (Arg, INC_SYS | INC_USER);
+}
+
+
+
+static void OptSignedChars (const char* Opt, const char* Arg)
+/* Make default characters signed */
+{
+    SignedChars = 1;
+}
+
+
+
+static void OptTarget (const char* Opt, const char* Arg)
+/* Set the target system */
+{
+    if (Arg == 0) {
+       NeedArg (Opt);
     }
+    SetSys (Arg);
+}
+
+
+
+static void OptVerbose (const char* Opt, const char* Arg)
+/* Increase verbosity */
+{
+    ++Verbose;
 }
 
 
 
-int main (int argc, char **argv)
+static void OptVersion (const char* Opt, const char* Arg)
+/* Print the assembler version */
 {
-    int i;
-    char *argp;
+    fprintf (stderr,
+                    "cc65 V%u.%u.%u\n",
+                    VER_MAJOR, VER_MINOR, VER_PATCH);
+}
+
+
+
+int main (int argc, char* argv[])
+{
+    /* Program long options */
+    static const LongOpt OptTab[] = {
+       { "--ansi",             0,      OptAnsi                 },
+        { "--cpu",                     1,      OptCPU                  },
+       { "--debug-info",       0,      OptDebugInfo            },
+       { "--help",             0,      OptHelp                 },
+       { "--include-dir",      1,      OptIncludeDir           },
+       { "--signed-chars",     0,      OptSignedChars          },
+       { "--target",           1,      OptTarget               },
+       { "--verbose",          0,      OptVerbose              },
+       { "--version",          0,      OptVersion              },
+    };
+
+    int I;
     char out_name [256];
-    char* p;
 
     /* Initialize the output file name */
     out_name [0] = '\0';
 
     fin = NULL;
 
+    /* Initialize the cmdline module */
+    InitCmdLine (argc, argv);
+
     /* Parse the command line */
-    for (i = 1; i < argc; i++) {
-       if (*(argp = argv[i]) == '-') {
-           switch (argp[1]) {
+    I = 1;
+    while (I < argc) {
+
+       const char* P;
+
+               /* Get the argument */
+               const char* Arg = argv [I];
+
+               /* Check for an option */
+               if (Arg [0] == '-') {
+
+                   switch (Arg [1]) {
+
+               case '-':
+                   LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
+                   break;
 
                case 'd':       /* debug mode */
                    Debug = 1;
@@ -266,68 +399,68 @@ int main (int argc, char **argv)
 
                case 'h':
                case '?':
-                   usage (EXIT_SUCCESS);
+                   OptHelp (Arg, 0);
                    break;
 
                case 'g':
-                   DebugInfo = 1;
+                   OptDebugInfo (Arg, 0);
                    break;
 
                case 'j':
-                   SignedChars = 1;
+                   OptSignedChars (Arg, 0);
                    break;
 
-               case 'o':
-                   strcpy (out_name, GetArg (&i, argv, 2));
+               case 'o':
+                   strcpy (out_name, GetArg (&I, 2));
                    break;
 
                case 't':
-                   SetSys (GetArg (&i, argv, 2));
+                   OptTarget (Arg, GetArg (&I, 2));
                    break;
 
                case 'v':
-                   ++Verbose;
+                   OptVerbose (Arg, 0);
                    break;
 
                case 'A':
-                   ANSI = 1;
+                   OptAnsi (Arg, 0);
                    break;
 
                case 'C':
-                   p = argp + 2;
-                   while (*p) {
-                       switch (*p++) {
-                           case 'l':
-                               LocalsAreStatic = 1;
-                               break;
-                       }
+                           P = Arg + 2;
+                   while (*P) {
+                       switch (*P++) {
+                           case 'l':
+                               LocalsAreStatic = 1;
+                               break;
+                       }
                    }
                    break;
 
                case 'D':
-                   DefineSym (GetArg (&i, argv, 2));
+                   DefineSym (GetArg (&I, 2));
                    break;
 
                case 'I':
-                   AddIncludePath (GetArg (&i, argv, 2), INC_SYS | INC_USER);
+                   OptIncludeDir (Arg, GetArg (&I, 2));
                    break;
 
                case 'O':
                    Optimize = 1;
-                   p = argp + 2;
-                   while (*p) {
-                       switch (*p++) {
-                           case 'f':
-                               sscanf (p, "%lx", (long*) &OptDisable);
-                               break;
-                           case 'i':
-                               FavourSize = 0;
-                               break;
-                           case 'r':
-                               EnableRegVars = 1;
+                   P = Arg + 2;
+                   while (*P) {
+                       switch (*P++) {
+                           case 'f':
+                               sscanf (P, "%lx", (long*) &OptDisable);
+                               break;
+                           case 'i':
+                               FavourSize = 0;
+                               break;
+                           case 'r':
+                               EnableRegVars = 1;
                                break;
                            case 's':
-                               InlineStdFuncs = 1;
+                               InlineStdFuncs = 1;
                                break;
                        }
                    }
@@ -338,8 +471,7 @@ int main (int argc, char **argv)
                    break;
 
                case 'V':
-                   fprintf (stderr, "cc65 V%u.%u.%u\n",
-                            VER_MAJOR, VER_MINOR, VER_PATCH);
+                   OptVersion (Arg, 0);
                    break;
 
                case 'W':
@@ -347,21 +479,26 @@ int main (int argc, char **argv)
                    break;
 
                default:
-                   fprintf (stderr, "Invalid option %s\n", argp);
-                   usage (EXIT_FAILURE);
+                           UnknownOption (Arg);
+                   break;
            }
        } else {
            if (fin) {
                fprintf (stderr, "additional file specs ignored\n");
            } else {
-               fin = xstrdup (argp);
+               fin = xstrdup (Arg);
                inp = fopen (fin, "r");
                if (inp == 0) {
                    Fatal (FAT_CANNOT_OPEN_INPUT, strerror (errno));
                }
            }
        }
+
+       /* Next argument */
+       ++I;
     }
+
+    /* Did we have a file spec on the command line? */
     if (!fin) {
        fprintf (stderr, "%s: No input files\n", argv [0]);
        exit (EXIT_FAILURE);
@@ -370,8 +507,10 @@ int main (int argc, char **argv)
     /* Create the output file name. We should really have
      * some checks for string overflow, but I'll drop this because of the
      * additional code size it would need (as in other places). Sigh.
+     * #### To be removed
      */
     if (out_name [0] == '\0') {
+       char* p;
        /* No output name given, create default */
        strcpy (out_name, fin);
        if ((p = strrchr (out_name, '.'))) {
@@ -414,3 +553,4 @@ int main (int argc, char **argv)
 }
 
 
+
index d30ffd4443004c8be5b58f125fb73d7ba071b6d7..1b1519c170c0f3cce11183a53841b6a918e61ced 100644 (file)
@@ -16,6 +16,7 @@ OBJS =        anonname.o      \
        check.o         \
        codegen.o       \
        compile.o       \
+       cpu.o           \
        ctrans.o        \
        datatype.o      \
        declare.o       \
@@ -26,7 +27,7 @@ OBJS =        anonname.o      \
        global.o        \
        goto.o          \
        ident.o         \
-       include.o       \
+       incpath.o       \
        io.o            \
        litpool.o       \
        locals.o        \
index a0d6625ea6557b16e1fbf8c8f5f6fe6156d9d374..9e758ebe93c011a536c9605e296b489683419cce 100644 (file)
@@ -70,6 +70,7 @@ OBJS =        anonname.obj    \
        check.obj       \
        codegen.obj     \
        compile.obj     \
+       cpu.obj         \
        ctrans.obj      \
        datatype.obj    \
        declare.obj     \
@@ -80,7 +81,7 @@ OBJS =        anonname.obj    \
        global.obj      \
        goto.obj        \
        ident.obj       \
-       include.obj     \
+       incpath.obj     \
        io.obj          \
        litpool.obj     \
        locals.obj      \
@@ -126,6 +127,7 @@ FILE asmline.obj
 FILE check.obj
 FILE codegen.obj
 FILE compile.obj
+FILE cpu.obj
 FILE ctrans.obj
 FILE datatype.obj
 FILE declare.obj
@@ -136,7 +138,7 @@ FILE function.obj
 FILE global.obj
 FILE goto.obj
 FILE ident.obj
-FILE include.obj
+FILE incpath.obj
 FILE io.obj
 FILE litpool.obj
 FILE locals.obj
index ac8480cef0599242120a9b884e1d4c59fc16b21e..8302ebdc2bb2905c2d707a64ad1ac375ee64fb4c 100644 (file)
@@ -40,6 +40,7 @@
 #include "asmlabel.h"
 #include "asmline.h"
 #include "check.h"
+#include "cpu.h"
 #include "error.h"
 #include "global.h"
 #include "io.h"
@@ -123,10 +124,14 @@ static const struct {
     { "\tcmp\t",                 0,    REG_A,      REG_NONE      },
     { "\tcpx\t",                 0,    REG_X,      REG_NONE      },
     { "\tcpy\t",                 0,    REG_Y,      REG_NONE      },
+    { "\tdea",           1,    REG_A,      REG_NONE      },
+    { "\tdec\ta",        1,    REG_A,      REG_NONE      },
     { "\tdec\t",                 0,    REG_NONE,   REG_NONE      },
     { "\tdex",                   1,    REG_X,      REG_NONE      },
     { "\tdey",                   1,    REG_Y,      REG_NONE      },
     { "\teor\t",                 0,    REG_A,      REG_NONE      },
+    { "\tina",           1,    REG_A,      REG_NONE      },
+    { "\tinc\ta",        1,    REG_A,      REG_NONE      },
     { "\tinc\t",                 0,    REG_NONE,   REG_NONE      },
     { "\tinx",                   1,    REG_X,      REG_NONE      },
     { "\tiny",                   1,    REG_Y,      REG_NONE      },
@@ -164,6 +169,7 @@ static const struct {
     { "\tsta\t",                 0,    REG_A,      REG_NONE      },
     { "\tstx\t",                 0,    REG_X,      REG_NONE      },
     { "\tsty\t",                 0,    REG_Y,      REG_NONE      },
+    { "\tstz\t",         0,    REG_NONE,   REG_NONE      },
     { "\ttax",                   1,    REG_A,      REG_X         },
     { "\ttay",                   1,    REG_A,      REG_Y         },
     { "\ttsx",                   1,    REG_NONE,   REG_X         },
@@ -559,7 +565,7 @@ static int IsCondJump (Line* L)
 
 
 
-static int IsXIndAddrMode (Line* L)
+static int IsXAddrMode (Line* L)
 /* Return true if the given line does use the X register */
 {
     unsigned Len = strlen (L->Line);
@@ -569,15 +575,15 @@ static int IsXIndAddrMode (Line* L)
 
 
 
-static int NoXIndAddrMode (Line* L)
+static int NoXAddrMode (Line* L)
 /* Return true if the given line does use the X register */
 {
-    return !IsXIndAddrMode (L);
+    return !IsXAddrMode (L);
 }
 
 
 
-static int IsYIndAddrMode (Line* L)
+static int IsYAddrMode (Line* L)
 /* Return true if the given line does use the Y register */
 {
     unsigned Len = strlen (L->Line);
@@ -779,7 +785,13 @@ static unsigned EstimateDataSize (Line* L, unsigned Chunk)
 static unsigned EstimateSize (Line* L)
 /* Estimate the size of an instruction */
 {
-    static const char* Transfers [] = {
+    static const char* OneByteCmds [] = {
+       "\tdea",
+       "\tdex",
+       "\tdey",
+       "\tina",
+       "\tinx",
+       "\tiny"
        "\ttax",
        "\ttay",
        "\ttsx",
@@ -819,7 +831,7 @@ static unsigned EstimateSize (Line* L)
     if (LineMatchX (L, LongBranches) >= 0) {
        return 5;
     }
-    if (LineMatchX (L, Transfers) >= 0) {
+    if (LineMatchX (L, OneByteCmds) >= 0) {
        return 1;
     }
     return 3;
@@ -1141,9 +1153,9 @@ static unsigned RVUInt2 (Line* L,
 
        /* Evaluate the use flags, check for addressing modes */
        R = CmdDesc[I].Use;
-       if (IsXIndAddrMode (L)) {
+       if (IsXAddrMode (L)) {
            R |= REG_X;
-       } else if (IsYIndAddrMode (L)) {
+       } else if (IsYAddrMode (L)) {
            R |= REG_Y;
        }
        if (R) {
@@ -1323,7 +1335,7 @@ static void OptCompares1 (void)
                 (Cond = TosCmpFunc (L2[4])) >= 0) {
 
            /* Replace it */
-           if (IsXIndAddrMode (L2[0])) {
+           if (IsXAddrMode (L2[0])) {
                /* The load is X indirect, so we may not remove the load
                 * of the X register.
                 */
@@ -1377,7 +1389,7 @@ static void OptCompares1 (void)
            Offs = GetHexNum (L2[2]->Line+7) - 2;
 
            /* Replace it */
-           if (IsXIndAddrMode (L2[0])) {
+           if (IsXAddrMode (L2[0])) {
                /* The load is X indirect, so we may not remove the load
                 * of the X register.
                 */
@@ -1637,7 +1649,7 @@ static void OptLoads (void)
                 LineFullMatch (L2 [1], "\tjsr\tpushax")) {
 
            /* Be sure, X is not used in the load */
-           if (NoXIndAddrMode (L2 [0])) {
+           if (NoXAddrMode (L2 [0])) {
 
                /* Replace the subroutine call */
                L2 [1] = ReplaceLine (L2 [1], "\tjsr\tpusha0");
@@ -1667,7 +1679,7 @@ static void OptLoads (void)
                 LineMatch (L2 [1], "\tcmp\t#$")) {
 
            /* Be sure, X is not used in the load */
-           if (NoXIndAddrMode (L2 [0])) {
+           if (NoXAddrMode (L2 [0])) {
 
                /* Remove the unnecessary load */
                FreeLine (L);
@@ -1693,7 +1705,7 @@ static void OptLoads (void)
                         LineFullMatch (L2 [1], "\tjsr\tbnega")) {
 
            /* Be sure, X is not used in the load */
-           if (NoXIndAddrMode (L2 [0])) {
+           if (NoXAddrMode (L2 [0])) {
 
                /* Remove the unnecessary load */
                FreeLine (L);
@@ -3630,12 +3642,16 @@ static Line* OptOneBlock (Line* L)
            if (A != -1) {
                A = (A << 1) & 0xFF;
            }
+       } else if (CPU == CPU_65C02 && LineFullMatch (L, "\tdea")) {
+           DEC (A, 1);
        } else if (LineFullMatch (L, "\tdex")) {
            DEC (X, 1);
        } else if (LineFullMatch (L, "\tdey")) {
            DEC (Y, 1);
        } else if (LineMatch (L, "\teor")) {
            A = -1;
+       } else if (CPU == CPU_65C02 && LineFullMatch (L, "\tina")) {
+           INC (A, 1);
        } else if (LineFullMatch (L, "\tinx")) {
            INC (X, 1);
        } else if (LineFullMatch (L, "\tiny")) {
@@ -3949,7 +3965,7 @@ static Line* OptOneBlock (Line* L)
                /* The value loaded is not used later, remove it */
                Delete = 1;
            } else if (LineMatch (L, "\tlda\t(")) {
-               if (IsXIndAddrMode (L)) {
+               if (IsXAddrMode (L)) {
                    /* lda (zp,x) - if Y and X are both zero, replace by
                     * load indirect y and save one cycle in some cases.
                     */
@@ -3982,6 +3998,13 @@ static Line* OptOneBlock (Line* L)
                } else if (NewVal == Y) {
                    /* Requested value is already in Y */
                    L = ReplaceLine (L, "\ttya");
+               } else if (CPU == CPU_65C02 && A != -1) {
+                   /* Try ina/dea operators of 65C02 */
+                   if (NewVal == ((A - 1) & 0xFF)) {
+                       L = ReplaceLine (L, "\tdea");
+                   } else if (NewVal == ((A + 1) & 0xFF)) {
+                       L = ReplaceLine (L, "\tina");
+                   }
                }
                /* Anyway, the new value is now in A */
                A = NewVal;
@@ -4066,6 +4089,22 @@ static Line* OptOneBlock (Line* L)
            A = X = Y = -1;
        } else if (LineMatch (L, "\tsbc\t")) {
            A = -1;
+       } else if (CPU == CPU_65C02 && LineMatch (L, "\tst")) {
+           /* Try to replace by stz if possible */
+           if (A == 0 && LineMatch (L, "\tsta\t")) {
+               /* Not indirect and not Y allowed */
+               if (L->Line[5] != '(' && !IsYAddrMode (L)) {
+                   L->Line[3] = 'z';
+               }
+           } else if (X == 0 && LineMatch (L, "\tstx\t")) {
+               /* absolute,y not allowed */
+               if (!IsYAddrMode (L)) {
+                   L->Line[3] = 'z';
+               }
+           } else if (Y == 0 && LineMatch (L, "\tsty\t")) {
+               /* sty and stz share all addressing modes */
+               L->Line[3] = 'z';
+           }
        } else if (LineFullMatch (L, "\ttax")) {
            if (A != -1 && X == A) {
                /* Load has no effect */
index e30379371e9b7e116e766fa66090fb75131f455f..89c92aa156ec1a4f2007714a8be6bf879786fb6f 100644 (file)
@@ -12,7 +12,7 @@
 #include "expr.h"
 #include "global.h"
 #include "ident.h"
-#include "include.h"
+#include "incpath.h"
 #include "io.h"
 #include "macrotab.h"
 #include "mem.h"
@@ -89,7 +89,7 @@ static void comment (void)
     gch ();
     while (*lptr != '*' || nch () != '/') {
        if (*lptr == '\0') {
-           if (readline () == 0) {
+           if (NextLine () == 0) {
                PPError (ERR_EOF_IN_COMMENT, StartingLine);
                return;
            }
@@ -283,7 +283,7 @@ static int MacroCall (Macro* M)
            skipblank ();
        } else if (C == '\0') {
            /* End of line inside macro argument list - read next line */
-           if (readline () == 0) {
+           if (NextLine () == 0) {
                return 0;
            }
        } else {
@@ -864,7 +864,7 @@ void preprocess (void)
            }
 
        }
-       if (readline () == 0) {
+       if (NextLine () == 0) {
            if (i_ifdef >= 0) {
                PPError (ERR_CPP_ENDIF_EXPECTED);
            }
index 27b6a15d10f6407a9277de29bdc7670d012d00b8..fd88f31f38c9acb2126393359dce1431154a1fd6 100644 (file)
@@ -137,7 +137,7 @@ static int skipwhite (void)
 {
     while (1) {
                while (*lptr == 0) {
-           if (readline () == 0) {
+           if (NextLine () == 0) {
                return 0;
            }
            preprocess ();