]> git.sur5r.net Git - cc65/blobdiff - src/cc65/main.c
Added the io module
[cc65] / src / cc65 / main.c
index e86f6590052036663e3593343263a1dd535d83b9..3072cdb5743255935463c221366484df60486a0a 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/fname.h"
 #include "../common/version.h"
+#include "../common/xmalloc.h"
 
 #include "asmcode.h"
 #include "compile.h"
+#include "cpu.h"
 #include "error.h"
 #include "global.h"
-#include "include.h"
-#include "io.h"
+#include "incpath.h"
+#include "input.h"
 #include "macrotab.h"
-#include "mem.h"
 #include "optimize.h"
 #include "scanner.h"
 
@@ -50,57 +86,49 @@ static const char* TargetNames [] = {
 
 
 
-static void usage (int ExitCode)
-{
-    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 */
+static void Usage (void)
 {
-    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: %s [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\tHelp (this text)\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 dir\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\t\tDebug mode\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"
+                    "  --static-locals\tMake local variables static\n"
+                    "  --target sys\t\tSet the target system\n"
+                    "  --verbose\t\tIncrease verbosity\n"
+                    "  --version\t\tPrint the compiler version number\n",
+            ProgName);
 }
 
 
 
-/* Define a CBM system */
 static void cbmsys (const char* sys)
+/* Define a CBM system */
 {
     AddNumericMacro ("__CBM__", 1);
     AddNumericMacro (sys, 1);
@@ -133,8 +161,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 +170,7 @@ static void SetSys (const char* Sys)
            break;
 
        case TGT_ATARI:
-           AddNumericMacro ("__ATARI__", 1);
+           AddNumericMacro ("__ATARI__", 1);
            break;
 
        case TGT_C64:
@@ -184,21 +212,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 +225,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 +236,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,148 +255,289 @@ 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 OptAddSource (const char* Opt, const char* Arg)
+/* Add source lines as comments in generated assembler file */
+{
+    AddSource = 1;
+}
+
+
+
+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 OptDebug (const char* Opt, const char* Arg)
+/* Compiler debug mode */
+{
+    Debug = 1;
+}
+
+
+
+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 OptStaticLocals (const char* Opt, const char* Arg)
+/* Place local variables in static storage */
+{
+    StaticLocals = 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;
-    char out_name [256];
-    char* p;
+    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[] = {
+       { "--add-source",       0,      OptAddSource            },
+       { "--ansi",             0,      OptAnsi                 },
+        { "--cpu",                     1,      OptCPU                  },
+               { "--debug",            0,      OptDebug                },
+       { "--debug-info",       0,      OptDebugInfo            },
+       { "--help",             0,      OptHelp                 },
+       { "--include-dir",      1,      OptIncludeDir           },
+       { "--signed-chars",     0,      OptSignedChars          },
+               { "--static-locals",    0,      OptStaticLocals         },
+       { "--target",           1,      OptTarget               },
+       { "--verbose",          0,      OptVerbose              },
+       { "--version",          0,      OptVersion              },
+    };
+
+    int I;
 
     /* Initialize the output file name */
-    out_name [0] = '\0';
+    const char* OutputFile = 0;
+    const char* InputFile  = 0;
 
-    fin = NULL;
+    /* Initialize the cmdline module */
+    InitCmdLine (argc, argv, "cc65");
 
     /* 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];
 
-               case 'd':       /* debug mode */
-                   Debug = 1;
+               /* Check for an option */
+               if (Arg [0] == '-') {
+
+                   switch (Arg [1]) {
+
+               case '-':
+                   LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
+                   break;
+
+               case 'd':
+                   OptDebug (Arg, 0);
                    break;
 
                case 'h':
                case '?':
-                   usage (EXIT_SUCCESS);
+                   OptHelp (Arg, 0);
                    break;
 
                case 'g':
-                   DebugInfo = 1;
+                   OptDebugInfo (Arg, 0);
                    break;
 
                case 'j':
-                   SignedChars = 1;
-                   break;
+                   OptSignedChars (Arg, 0);
+                   break;
 
-               case 'o':
-                   strcpy (out_name, GetArg (&i, argv, 2));
+               case 'o':
+                   OutputFile = 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;
+                           P = Arg + 2;
+                   while (*P) {
+                       switch (*P++) {
+                           case 'l':
+                               OptStaticLocals (Arg, 0);
+                               break;
+                           default:
+                               UnknownOption (Arg);
                                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);
+                       case 'I':
+                   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;
-                               break;
-                           case 's':
-                               InlineStdFuncs = 1;
-                               break;
-                       }
-                   }
-                   break;
-
-               case 'T':
-                   IncSource = 1;
-                   break;
-
-               case 'V':
-                   fprintf (stderr, "cc65 V%u.%u.%u\n",
-                            VER_MAJOR, VER_MINOR, VER_PATCH);
-                   break;
-
-               case 'W':
-                   NoWarn = 1;
-                   break;
-
-               default:
-                   fprintf (stderr, "Invalid option %s\n", argp);
-                   usage (EXIT_FAILURE);
-           }
-       } else {
-           if (fin) {
-               fprintf (stderr, "additional file specs ignored\n");
-           } else {
-               fin = xstrdup (argp);
-               inp = fopen (fin, "r");
-               if (inp == 0) {
-                   Fatal (FAT_CANNOT_OPEN_INPUT, strerror (errno));
-               }
+                   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;
+                               break;
+                       }
+                   }
+                   break;
+
+               case 'T':
+                           OptAddSource (Arg, 0);
+                           break;
+
+                       case 'V':
+                           OptVersion (Arg, 0);
+                           break;
+
+                       case 'W':
+                           NoWarn = 1;
+                           break;
+
+                       default:
+                           UnknownOption (Arg);
+                           break;
+                   }
+               } else {
+                   if (InputFile) {
+                       fprintf (stderr, "additional file specs ignored\n");
+                   } else {
+                       InputFile = Arg;
            }
        }
+
+       /* Next argument */
+       ++I;
     }
-    if (!fin) {
+
+    /* Did we have a file spec on the command line? */
+    if (InputFile == 0) {
        fprintf (stderr, "%s: No input files\n", argv [0]);
        exit (EXIT_FAILURE);
     }
 
-    /* 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.
-     */
-    if (out_name [0] == '\0') {
-       /* No output name given, create default */
-       strcpy (out_name, fin);
-       if ((p = strrchr (out_name, '.'))) {
-           *p = '\0';
-       }
-       strcat (out_name, ".s");
+    /* Open the input file */
+    OpenMainFile (InputFile);
+
+    /* Create the output file name if it was not explicitly given */
+    if (OutputFile == 0) {
+       OutputFile = MakeFilename (InputFile, ".s");
     }
 
     /* Go! */
@@ -394,7 +554,7 @@ int main (int argc, char **argv)
        }
 
        /* Open the file */
-       F = fopen (out_name, "w");
+       F = fopen (OutputFile, "w");
        if (F == 0) {
            Fatal (FAT_CANNOT_OPEN_OUTPUT, strerror (errno));
        }
@@ -404,7 +564,7 @@ int main (int argc, char **argv)
 
        /* Close the file, check for errors */
        if (fclose (F) != 0) {
-           remove (out_name);
+           remove (OutputFile);
            Fatal (FAT_CANNOT_WRITE_OUTPUT);
        }
     }
@@ -414,3 +574,4 @@ int main (int argc, char **argv)
 }
 
 
+