X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fca65%2Fmain.c;h=b029e2f0cc64b67255ec5102819d2143cf6c9f64;hb=1d458e9f33d442052a2921f0678efb4875d2e8ab;hp=21d6a613eb91c77680819f487ab786c0e09608a4;hpb=fbe694bca326aefe2677d478f7179ade6ee7e40c;p=cc65 diff --git a/src/ca65/main.c b/src/ca65/main.c index 21d6a613e..b029e2f0c 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -36,17 +36,27 @@ #include #include #include -#include #include -#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 (); }