]> git.sur5r.net Git - cc65/blobdiff - src/ca65/main.c
Small fixes for Watcom-C
[cc65] / src / ca65 / main.c
index 21d6a613eb91c77680819f487ab786c0e09608a4..b029e2f0cc64b67255ec5102819d2143cf6c9f64 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 #include <time.h>
 
-#include "../common/cmdline.h"
-#include "../common/version.h"
+/* common */
+#include "chartype.h"
+#include "cmdline.h"
+#include "print.h"
+#include "target.h"
+#include "tgttrans.h"
+#include "version.h"
 
+/* ca65 */
+#include "abend.h"
 #include "error.h"
 #include "expr.h"
+#include "feature.h"
+#include "filetab.h"
 #include "global.h"
 #include "incpath.h"
 #include "instr.h"
+#include "istack.h"
+#include "lineinfo.h"
 #include "listing.h"
 #include "macro.h"
 #include "nexttok.h"
@@ -73,10 +83,12 @@ static void Usage (void)
             "Usage: %s [options] file\n"
             "Short options:\n"
                     "  -g\t\t\tAdd debug info to object file\n"
+                    "  -h\t\t\tHelp (this text)\n"
                     "  -i\t\t\tIgnore case of symbols\n"
                     "  -l\t\t\tCreate a listing if assembly was ok\n"
                     "  -o name\t\tName the output file\n"
                     "  -s\t\t\tEnable smart mode\n"
+                    "  -t sys\t\tSet the target system\n"
                     "  -v\t\t\tIncrease verbosity\n"
                     "  -D name[=value]\tDefine a symbol\n"
                     "  -I dir\t\tSet an include directory search path\n"
@@ -88,12 +100,14 @@ static void Usage (void)
                     "  --auto-import\t\tMark unresolved symbols as import\n"
                     "  --cpu type\t\tSet cpu type\n"
                     "  --debug-info\t\tAdd debug info to object file\n"
+            "  --feature name\tSet an emulation feature\n"
             "  --help\t\tHelp (this text)\n"
             "  --ignore-case\t\tIgnore case of symbols\n"
                     "  --include-dir dir\tSet an include directory search path\n"
                     "  --listing\t\tCreate a listing if assembly was ok\n"
                     "  --pagelength n\tSet the page length for the listing\n"
                     "  --smart\t\tEnable smart mode\n"
+                    "  --target sys\t\tSet the target system\n"
                     "  --verbose\t\tIncrease verbosity\n"
                     "  --version\t\tPrint the assembler version\n",
             ProgName);
@@ -125,14 +139,14 @@ static void DefineSymbol (const char* Def)
     char SymName [MAX_STR_LEN+1];
 
     /* The symbol must start with a character or underline */
-    if (Def [0] != '_' && !isalpha (Def [0])) {
+    if (Def [0] != '_' && !IsAlpha (Def [0])) {
        InvDef (Def);
     }
     P = Def;
 
     /* Copy the symbol, checking the rest */
     I = 0;
-    while (isalnum (*P) || *P == '_') {
+    while (IsAlNum (*P) || *P == '_') {
        if (I <= MAX_STR_LEN) {
            SymName [I++] = *P;
        }
@@ -163,8 +177,7 @@ static void DefineSymbol (const char* Def)
 
     /* Check if have already a symbol with this name */
     if (SymIsDef (SymName)) {
-       fprintf (stderr, "`%s' is already defined\n", SymName);
-       exit (EXIT_FAILURE);
+       AbEnd ("`%s' is already defined", SymName);
     }
 
     /* Define the symbol */
@@ -198,8 +211,7 @@ static void OptCPU (const char* Opt, const char* Arg)
        SetCPU (CPU_SUNPLUS);
 #endif
     } else {
-       fprintf (stderr, "Invalid CPU: `%s'\n", Arg);
-       exit (EXIT_FAILURE);
+       AbEnd ("Invalid CPU: `%s'", Arg);
     }
 }
 
@@ -213,6 +225,17 @@ static void OptDebugInfo (const char* Opt, const char* Arg)
 
 
 
+static void OptFeature (const char* Opt, const char* Arg)
+/* Set an emulation feature */
+{
+    /* Set the feature, check for errors */
+    if (SetFeature (Arg) == FEAT_UNKNOWN) {
+       AbEnd ("Illegal emulation feature: `%s'", Arg);
+    }
+}
+
+
+
 static void OptHelp (const char* Opt, const char* Arg)
 /* Print usage information and exit */
 {
@@ -258,8 +281,7 @@ static void OptPageLength (const char* Opt, const char* Arg)
     }
     Len = atoi (Arg);
     if (Len != -1 && (Len < MIN_PAGE_LEN || Len > MAX_PAGE_LEN)) {
-       fprintf (stderr, "Invalid page length: %d\n", Len);
-       exit (EXIT_FAILURE);
+       AbEnd ("Invalid page length: %d", Len);
     }
     PageLength = Len;
 }
@@ -274,10 +296,26 @@ static void OptSmart (const char* Opt, const char* Arg)
 
 
 
+static void OptTarget (const char* Opt, const char* Arg)
+/* Set the target system */
+{
+    if (Arg == 0) {
+       NeedArg (Opt);
+    }
+
+    /* Map the target name to a target id */
+    Target = FindTarget (Arg);
+    if (Target == TGT_UNKNOWN) {
+       AbEnd ("Invalid target name: `%s'", Arg);
+    }
+}
+
+
+
 static void OptVerbose (const char* Opt, const char* Arg)
 /* Increase verbosity */
 {
-    ++Verbose;
+    ++Verbosity;
 }
 
 
@@ -292,90 +330,113 @@ static void OptVersion (const char* Opt, const char* Arg)
 
 
 
+static void DoPCAssign (void)
+/* Start absolute code */
+{
+    long PC = ConstExpression ();
+    if (PC < 0 || PC > 0xFFFFFF) {
+       Error (ERR_RANGE);
+    } else {
+       SetAbsPC (PC);
+    }
+}
+
+
+
 static void OneLine (void)
 /* Assemble one line */
 {
     char Ident [MAX_STR_LEN+1];
     int Done = 0;
 
-    /* Initialize the listing line */
-    InitListingLine ();
+    /* Initialize the new listing line if we are actually reading from file
+     * and not from internally pushed input.
+     */
+    if (!HavePushedInput ()) {
+       InitListingLine ();
+    }
 
     if (Tok == TOK_COLON) {
-       /* An unnamed label */
-       ULabDef ();
-       NextTok ();
+       /* An unnamed label */
+       ULabDef ();
+       NextTok ();
     }
 
     /* Assemble the line */
     if (Tok == TOK_IDENT) {
 
-       /* Is it a macro? */
-       if (IsMacro (SVal)) {
+       /* Is it a macro? */
+       if (IsMacro (SVal)) {
 
-           /* Yes, start a macro expansion */
-           MacExpandStart ();
-           Done = 1;
+           /* Yes, start a macro expansion */
+           MacExpandStart ();
+           Done = 1;
 
-       } else {
+       } else {
 
-           /* No, label. Remember the identifier, then skip it */
-           int HadWS = WS;     /* Did we have whitespace before the ident? */
-           strcpy (Ident, SVal);
-           NextTok ();
+           /* No, label. Remember the identifier, then skip it */
+           int HadWS = WS;     /* Did we have whitespace before the ident? */
+           strcpy (Ident, SVal);
+           NextTok ();
 
-           /* If a colon follows, this is a label definition. If there
-            * is no colon, it's an assignment.
-            */
+           /* If a colon follows, this is a label definition. If there
+            * is no colon, it's an assignment.
+            */
                    if (Tok == TOK_EQ) {
-               /* Skip the '=' */
-               NextTok ();
-               /* Define the symbol with the expression following the '=' */
-               SymDef (Ident, Expression (), 0);
-               /* Don't allow anything after a symbol definition */
-               Done = 1;
-           } else {
-               /* Define a label */
-               SymDef (Ident, CurrentPC (), IsZPSeg ());
-               /* Skip the colon. If NoColonLabels is enabled, allow labels
-                * without a colon if there is no whitespace before the
-                * identifier.
-                */
-               if (Tok != TOK_COLON) {
-                   if (HadWS || !NoColonLabels) {
-                       Error (ERR_COLON_EXPECTED);
-                   }
-                   if (Tok == TOK_NAMESPACE) {
-                       /* Smart :: handling */
-                       NextTok ();
-                   }
-               } else {
-                   /* Skip the colon */
-                   NextTok ();
-               }
-           }
-       }
+               /* Skip the '=' */
+               NextTok ();
+               /* Define the symbol with the expression following the '=' */
+               SymDef (Ident, Expression (), 0);
+               /* Don't allow anything after a symbol definition */
+               Done = 1;
+           } else {
+               /* Define a label */
+               SymDef (Ident, CurrentPC (), IsZPSeg ());
+               /* Skip the colon. If NoColonLabels is enabled, allow labels
+                * without a colon if there is no whitespace before the
+                * identifier.
+                */
+               if (Tok != TOK_COLON) {
+                   if (HadWS || !NoColonLabels) {
+                       Error (ERR_COLON_EXPECTED);
+                   }
+                   if (Tok == TOK_NAMESPACE) {
+                       /* Smart :: handling */
+                       NextTok ();
+                   }
+               } else {
+                   /* Skip the colon */
+                   NextTok ();
+               }
+           }
+       }
     }
 
     if (!Done) {
 
-       if (TokIsPseudo (Tok)) {
-           /* A control command, IVal is index into table */
-           HandlePseudo ();
-       } else if (Tok == TOK_MNEMO) {
-           /* A mnemonic - assemble one instruction */
-           HandleInstruction (IVal);
-       } else if (Tok == TOK_IDENT && IsMacro (SVal)) {
-           /* A macro expansion */
-           MacExpandStart ();
+       if (TokIsPseudo (Tok)) {
+           /* A control command, IVal is index into table */
+           HandlePseudo ();
+       } else if (Tok == TOK_MNEMO) {
+           /* A mnemonic - assemble one instruction */
+           HandleInstruction (IVal);
+       } else if (Tok == TOK_IDENT && IsMacro (SVal)) {
+           /* A macro expansion */
+           MacExpandStart ();
+       } else if (PCAssignment && (Tok == TOK_STAR || Tok == TOK_PC)) {
+           NextTok ();
+           if (Tok != TOK_EQ) {
+               Error (ERR_EQ_EXPECTED);
+               SkipUntilSep ();
+           } else {
+               /* Skip the equal sign */
+               NextTok ();
+               /* Enter absolute mode */
+               DoPCAssign ();
+           }
        }
     }
 
-    /* Calling InitListingLine again here is part of a hack that introduces
-     * enough magic to make the PC output in the listing work.
-     */
-    InitListingLine ();
-
     /* Line separator must come here */
     ConsumeSep ();
 }
@@ -420,6 +481,9 @@ static void CreateObjFile (void)
     /* Write debug symbols if requested */
     WriteDbgSyms ();
 
+    /* Write line infos if requested */
+    WriteLineInfo ();
+
     /* Write an updated header and close the file */
     ObjClose ();
 }
@@ -434,20 +498,22 @@ int main (int argc, char* argv [])
         { "--auto-import",             0,      OptAutoImport           },
         { "--cpu",                     1,      OptCPU                  },
        { "--debug-info",       0,      OptDebugInfo            },
-       { "--help",             0,      OptHelp                 },
+       { "--feature",          1,      OptFeature              },
+       { "--help",             0,      OptHelp                 },
        { "--ignore-case",      0,      OptIgnoreCase           },
        { "--include-dir",      1,      OptIncludeDir           },
-       { "--listing",          0,      OptListing              },
+       { "--listing",          0,      OptListing              },
        { "--pagelength",       1,      OptPageLength           },
-       { "--smart",            0,      OptSmart                },
-       { "--verbose",          0,      OptVerbose              },
-       { "--version",          0,      OptVersion              },
+       { "--smart",            0,      OptSmart                },
+       { "--target",           1,      OptTarget               },
+       { "--verbose",          0,      OptVerbose              },
+       { "--version",          0,      OptVersion              },
     };
 
     int I;
 
     /* Initialize the cmdline module */
-    InitCmdLine (argc, argv, "ca65");
+    InitCmdLine (&argc, &argv, "ca65");
 
     /* Enter the base lexical level. We must do that here, since we may
      * define symbols using -D.
@@ -456,10 +522,10 @@ int main (int argc, char* argv [])
 
     /* Check the parameters */
     I = 1;
-    while (I < argc) {
+    while (I < ArgCount) {
 
                /* Get the argument */
-               const char* Arg = argv [I];
+               const char* Arg = ArgVec [I];
 
                /* Check for an option */
                if (Arg [0] == '-') {
@@ -469,10 +535,14 @@ int main (int argc, char* argv [])
                    LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
                    break;
 
-                       case 'g':
+                       case 'g':
                            OptDebugInfo (Arg, 0);
                            break;
 
+               case 'h':
+                   OptHelp (Arg, 0);
+                   break;
+
                        case 'i':
                            OptIgnoreCase (Arg, 0);
                            break;
@@ -489,6 +559,10 @@ int main (int argc, char* argv [])
                            OptSmart (Arg, 0);
                            break;
 
+               case 't':
+                   OptTarget (Arg, GetArg (&I, 2));
+                   break;
+
                        case 'v':
                    OptVerbose (Arg, 0);
                            break;
@@ -506,7 +580,7 @@ int main (int argc, char* argv [])
                            break;
 
                        case 'V':
-                   OptVersion (Arg, 0);
+                   OptVersion (Arg, 0);
                            break;
 
                        case 'W':
@@ -522,10 +596,10 @@ int main (int argc, char* argv [])
            /* Filename. Check if we already had one */
            if (InFile) {
                fprintf (stderr, "%s: Don't know what to do with `%s'\n",
-                        ProgName, Arg);
-               exit (EXIT_FAILURE);
+                        ProgName, Arg);
+               exit (EXIT_FAILURE);
            } else {
-               InFile = Arg;
+               InFile = Arg;
            }
        }
 
@@ -539,6 +613,9 @@ int main (int argc, char* argv [])
        exit (EXIT_FAILURE);
     }
 
+    /* Intialize the target translation tables */
+    TgtTranslateInit ();
+
     /* Initialize the scanner, open the input file */
     InitScanner (InFile);
 
@@ -563,8 +640,11 @@ int main (int argc, char* argv [])
         SegCheck ();
     }
 
+    /* If we didn't have an errors, index the line infos */
+    MakeLineInfoIndex ();
+
     /* Dump the data */
-    if (Verbose >= 2) {
+    if (Verbosity >= 2) {
         SymDump (stdout);
         SegDump ();
     }