X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fca65%2Fmain.c;h=7364891bc7208c54fac12eed9fbde5f7bd8c7678;hb=1e20489ee1d09f3b043b7f6b3e8434d3d8a0b27a;hp=6223bfe9254b0bf464b68ca84a7f39d90099b800;hpb=ba68b5f87af2e2fea641462f7c4d0308a4140e97;p=cc65 diff --git a/src/ca65/main.c b/src/ca65/main.c index 6223bfe92..7364891bc 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstraße 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2011, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -42,7 +42,10 @@ #include "addrsize.h" #include "chartype.h" #include "cmdline.h" +#include "mmodel.h" #include "print.h" +#include "scopedefs.h" +#include "strbuf.h" #include "target.h" #include "tgttrans.h" #include "version.h" @@ -60,6 +63,7 @@ #include "istack.h" #include "lineinfo.h" #include "listing.h" +#include "macpack.h" #include "macro.h" #include "nexttok.h" #include "objfile.h" @@ -67,7 +71,9 @@ #include "pseudo.h" #include "scanner.h" #include "segment.h" +#include "sizeof.h" #include "spool.h" +#include "symbol.h" #include "symtab.h" #include "ulabel.h" @@ -82,38 +88,45 @@ static void Usage (void) /* Print usage information and exit */ { - fprintf (stderr, - "Usage: %s [options] file\n" - "Short options:\n" - " -D name[=value]\tDefine a symbol\n" - " -I dir\t\tSet an include directory search path\n" - " -U\t\t\tMark unresolved symbols as import\n" - " -V\t\t\tPrint the assembler version\n" - " -W n\t\t\tSet warning level n\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" - "\n" - "Long options:\n" - " --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); + printf ("Usage: %s [options] file\n" + "Short options:\n" + " -D name[=value]\t\tDefine a symbol\n" + " -I dir\t\t\tSet an include directory search path\n" + " -U\t\t\t\tMark unresolved symbols as import\n" + " -V\t\t\t\tPrint the assembler version\n" + " -W n\t\t\t\tSet warning level n\n" + " -g\t\t\t\tAdd debug info to object file\n" + " -h\t\t\t\tHelp (this text)\n" + " -i\t\t\t\tIgnore case of symbols\n" + " -l name\t\t\tCreate a listing file if assembly was ok\n" + " -mm model\t\t\tSet the memory model\n" + " -o name\t\t\tName the output file\n" + " -s\t\t\t\tEnable smart mode\n" + " -t sys\t\t\tSet the target system\n" + " -v\t\t\t\tIncrease verbosity\n" + "\n" + "Long options:\n" + " --auto-import\t\t\tMark unresolved symbols as import\n" + " --bin-include-dir dir\t\tSet a search path for binary includes\n" + " --cpu type\t\t\tSet cpu type\n" + " --create-dep name\t\tCreate a make dependency file\n" + " --create-full-dep name\tCreate a full make dependency file\n" + " --debug-info\t\t\tAdd debug info to object file\n" + " --feature name\t\tSet an emulation feature\n" + " --forget-inc-paths\t\tForget include search paths\n" + " --help\t\t\tHelp (this text)\n" + " --ignore-case\t\t\tIgnore case of symbols\n" + " --include-dir dir\t\tSet an include directory search path\n" + " --listing name\t\tCreate a listing file if assembly was ok\n" + " --list-bytes n\t\tMaximum number of bytes per listing line\n" + " --macpack-dir dir\t\tSet a macro package directory\n" + " --memory-model model\t\tSet the memory model\n" + " --pagelength n\t\tSet the page length for the listing\n" + " --smart\t\t\tEnable smart mode\n" + " --target sys\t\t\tSet the target system\n" + " --verbose\t\t\tIncrease verbosity\n" + " --version\t\t\tPrint the assembler version\n", + ProgName); } @@ -121,14 +134,166 @@ static void Usage (void) static void SetOptions (void) /* Set the option for the translator */ { - char Buf [256]; + StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Set the translator */ - sprintf (Buf, "ca65 V%u.%u.%u", VER_MAJOR, VER_MINOR, VER_PATCH); - OptTranslator (Buf); + SB_Printf (&Buf, "ca65 V%s", GetVersionAsString ()); + OptTranslator (&Buf); /* Set date and time */ OptDateTime ((unsigned long) time(0)); + + /* Release memory for the string */ + SB_Done (&Buf); +} + + + +static void NewSymbol (const char* SymName, long Val) +/* Define a symbol with a fixed numeric value in the current scope */ +{ + ExprNode* Expr; + SymEntry* Sym; + + /* Convert the name to a string buffer */ + StrBuf SymBuf = STATIC_STRBUF_INITIALIZER; + SB_CopyStr (&SymBuf, SymName); + + /* Search for the symbol, allocate a new one if it doesn't exist */ + Sym = SymFind (CurrentScope, &SymBuf, SYM_ALLOC_NEW); + + /* Check if have already a symbol with this name */ + if (SymIsDef (Sym)) { + AbEnd ("`%s' is already defined", SymName); + } + + /* Generate an expression for the symbol */ + Expr = GenLiteralExpr (Val); + + /* Mark the symbol as defined */ + SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_NONE); + + /* Free string buffer memory */ + SB_Done (&SymBuf); +} + + + +static void CBMSystem (const char* Sys) +/* Define a CBM system */ +{ + NewSymbol ("__CBM__", 1); + NewSymbol (Sys, 1); +} + + + +static void SetSys (const char* Sys) +/* Define a target system */ +{ + switch (Target = FindTarget (Sys)) { + + case TGT_NONE: + break; + + case TGT_MODULE: + AbEnd ("Cannot use `module' as a target for the assembler"); + break; + + case TGT_ATARI: + NewSymbol ("__ATARI__", 1); + break; + + case TGT_C16: + CBMSystem ("__C16__"); + break; + + case TGT_C64: + CBMSystem ("__C64__"); + break; + + case TGT_VIC20: + CBMSystem ("__VIC20__"); + break; + + case TGT_C128: + CBMSystem ("__C128__"); + break; + + case TGT_PLUS4: + CBMSystem ("__PLUS4__"); + break; + + case TGT_CBM510: + CBMSystem ("__CBM510__"); + break; + + case TGT_CBM610: + CBMSystem ("__CBM610__"); + break; + + case TGT_PET: + CBMSystem ("__PET__"); + break; + + case TGT_BBC: + NewSymbol ("__BBC__", 1); + break; + + case TGT_APPLE2: + NewSymbol ("__APPLE2__", 1); + break; + + case TGT_APPLE2ENH: + NewSymbol ("__APPLE2ENH__", 1); + break; + + case TGT_GEOS: + /* Do not handle as a CBM system */ + NewSymbol ("__GEOS__", 1); + break; + + case TGT_LUNIX: + NewSymbol ("__LUNIX__", 1); + break; + + case TGT_ATMOS: + NewSymbol ("__ATMOS__", 1); + break; + + case TGT_NES: + NewSymbol ("__NES__", 1); + break; + + case TGT_SUPERVISION: + NewSymbol ("__SUPERVISION__", 1); + break; + + case TGT_LYNX: + NewSymbol ("__LYNX__", 1); + break; + + default: + AbEnd ("Invalid target name: `%s'", Sys); + + } + + /* Initialize the translation tables for the target system */ + TgtTranslateInit (); +} + + + +static void FileNameOption (const char* Opt, const char* Arg, StrBuf* Name) +/* Handle an option that remembers a file name for later */ +{ + /* Cannot have the option twice */ + if (SB_NotEmpty (Name)) { + AbEnd ("Cannot use option `%s' twice", Opt); + } + /* Remember the file name for later */ + SB_CopyStr (Name, Arg); + SB_Terminate (Name); } @@ -139,25 +304,21 @@ static void DefineSymbol (const char* Def) const char* P; unsigned I; long Val; - char SymName [MAX_STR_LEN+1]; - SymEntry* Sym; + StrBuf SymName = AUTO_STRBUF_INITIALIZER; /* The symbol must start with a character or underline */ - if (Def [0] != '_' && !IsAlpha (Def [0])) { + if (!IsIdStart (Def [0])) { InvDef (Def); } P = Def; /* Copy the symbol, checking the rest */ I = 0; - while (IsAlNum (*P) || *P == '_') { - if (I <= MAX_STR_LEN) { - SymName [I++] = *P; - } - ++P; + while (IsIdChar (*P)) { + SB_AppendChar (&SymName, *P++); } - SymName [I] = '\0'; + SB_Terminate (&SymName); /* Do we have a value given? */ if (*P != '=') { @@ -166,36 +327,31 @@ static void DefineSymbol (const char* Def) } Val = 0; } else { - /* We have a value */ - ++P; - if (*P == '$') { - ++P; - if (sscanf (P, "%lx", &Val) != 1) { - InvDef (Def); - } - } else { - if (sscanf (P, "%li", &Val) != 1) { - InvDef (Def); - } + /* We have a value */ + ++P; + if (*P == '$') { + ++P; + if (sscanf (P, "%lx", &Val) != 1) { + InvDef (Def); + } + } else { + if (sscanf (P, "%li", &Val) != 1) { + InvDef (Def); + } } } - /* Search for the symbol, allocate a new one if it doesn't exist */ - Sym = SymFind (CurrentScope, SymName, SYM_ALLOC_NEW); - - /* Check if have already a symbol with this name */ - if (SymIsDef (Sym)) { - AbEnd ("`%s' is already defined", SymName); - } + /* Define the new symbol */ + NewSymbol (SB_GetConstBuf (&SymName), Val); - /* Mark the symbol as defined */ - SymDef (Sym, GenLiteralExpr (Val), ADDR_SIZE_DEFAULT, SF_NONE); + /* Release string memory */ + SB_Done (&SymName); } static void OptAutoImport (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Mark unresolved symbols as imported */ { AutoImport = 1; @@ -203,6 +359,14 @@ static void OptAutoImport (const char* Opt attribute ((unused)), +static void OptBinIncludeDir (const char* Opt attribute ((unused)), const char* Arg) +/* Add an include search path for binaries */ +{ + AddSearchPath (BinSearchPath, Arg); +} + + + static void OptCPU (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --cpu option */ { @@ -216,8 +380,25 @@ static void OptCPU (const char* Opt attribute ((unused)), const char* Arg) +static void OptCreateDep (const char* Opt, const char* Arg) +/* Handle the --create-dep option */ +{ + FileNameOption (Opt, Arg, &DepName); +} + + + +static void OptCreateFullDep (const char* Opt attribute ((unused)), + const char* Arg) +/* Handle the --create-full-dep option */ +{ + FileNameOption (Opt, Arg, &FullDepName); +} + + + static void OptDebugInfo (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Add debug info to the object file */ { DbgSyms = 1; @@ -228,14 +409,26 @@ static void OptDebugInfo (const char* Opt attribute ((unused)), static void OptFeature (const char* Opt attribute ((unused)), const char* Arg) /* Set an emulation feature */ { + /* Make a string buffer from Arg */ + StrBuf Feature; + /* Set the feature, check for errors */ - if (SetFeature (Arg) == FEAT_UNKNOWN) { + if (SetFeature (SB_InitFromString (&Feature, Arg)) == FEAT_UNKNOWN) { AbEnd ("Illegal emulation feature: `%s'", Arg); } } +static void OptForgetIncPaths (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Forget all currently defined include paths */ +{ + ForgetAllIncludePaths (); +} + + + static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ @@ -258,16 +451,82 @@ static void OptIgnoreCase (const char* Opt attribute ((unused)), static void OptIncludeDir (const char* Opt attribute ((unused)), const char* Arg) /* Add an include search path */ { - AddIncludePath (Arg); + AddSearchPath (IncSearchPath, Arg); } -static void OptListing (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) +static void OptListBytes (const char* Opt, const char* Arg) +/* Set the maximum number of bytes per listing line */ +{ + unsigned Num; + char Check; + + /* Convert the argument to a number */ + if (sscanf (Arg, "%u%c", &Num, &Check) != 1) { + InvArg (Opt, Arg); + } + + /* Check the bounds */ + if (Num != 0 && (Num < MIN_LIST_BYTES || Num > MAX_LIST_BYTES)) { + AbEnd ("Argument for option `%s' is out of range", Opt); + } + + /* Use the value */ + SetListBytes (Num); +} + + + +static void OptListing (const char* Opt, const char* Arg) /* Create a listing file */ { - Listing = 1; + /* Since the meaning of -l and --listing has changed, print an error if + * the filename is empty or begins with the option char. + */ + if (Arg == 0 || *Arg == '\0' || *Arg == '-') { + Fatal ("The meaning of `%s' has changed. It does now " + "expect a file name as argument.", Opt); + } + + /* Get the file name */ + FileNameOption (Opt, Arg, &ListingName); +} + + + +static void OptMacPackDir (const char* Opt attribute ((unused)), const char* Arg) +/* Set a macro package directory */ +{ + /* Make a string buffer from Arg */ + StrBuf Dir; + + /* Use the directory */ + MacPackSetDir (SB_InitFromString (&Dir, Arg)); +} + + + +static void OptMemoryModel (const char* Opt, const char* Arg) +/* Set the memory model */ +{ + mmodel_t M; + + /* Check the current memory model */ + if (MemoryModel != MMODEL_UNKNOWN) { + AbEnd ("Cannot use option `%s' twice", Opt); + } + + /* Translate the memory model name and check it */ + M = FindMemoryModel (Arg); + if (M == MMODEL_UNKNOWN) { + AbEnd ("Unknown memory model: %s", Arg); + } else if (M == MMODEL_HUGE) { + AbEnd ("Unsupported memory model: %s", Arg); + } + + /* Set the memory model */ + SetMemoryModel (M); } @@ -296,13 +555,7 @@ static void OptSmart (const char* Opt attribute ((unused)), static void OptTarget (const char* Opt attribute ((unused)), const char* Arg) /* Set the target system */ { - /* Map the target name to a target id */ - Target = FindTarget (Arg); - if (Target == TGT_UNKNOWN) { - AbEnd ("Invalid target name: `%s'", Arg); - } else if (Target == TGT_MODULE) { - AbEnd ("Cannot use `module' as a target for the assembler"); - } + SetSys (Arg); } @@ -320,9 +573,7 @@ static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the assembler version */ { - fprintf (stderr, - "ca65 V%u.%u.%u - %s\n", - VER_MAJOR, VER_MINOR, VER_PATCH, Copyright); + fprintf (stderr, "ca65 V%s - %s\n", GetVersionAsString (), Copyright); } @@ -334,7 +585,7 @@ static void DoPCAssign (void) if (PC < 0 || PC > 0xFFFFFF) { Error ("Range error"); } else { - SetAbsPC (PC); + EnterAbsoluteMode (PC); } } @@ -343,98 +594,176 @@ static void DoPCAssign (void) static void OneLine (void) /* Assemble one line */ { - int Done = 0; + Segment* Seg = 0; + unsigned long PC = 0; + SymEntry* Sym = 0; + Macro* Mac = 0; + int Instr = -1; /* 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 (); - } - - /* Assemble the line */ - if (Tok == TOK_IDENT) { - - /* Is it a macro? */ - if (IsMacro (SVal)) { - - /* Yes, start a macro expansion */ - MacExpandStart (); - Done = 1; - - } else { - - /* No, label. Remember the identifier, then skip it */ - int HadWS = WS; /* Did we have whitespace before the ident? */ - - /* Generate the symbol table entry, then skip the name */ - SymEntry* Sym = SymFind (CurrentScope, SVal, SYM_ALLOC_NEW); - NextTok (); - - /* If a colon follows, this is a label definition. If there - * is no colon, it's an assignment. - */ - if (Tok == TOK_EQ || Tok == TOK_ASSIGN) { - /* If it's an assign token, we have a label */ - unsigned Flags = (Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE; - /* Skip the '=' */ - NextTok (); - /* Define the symbol with the expression following the '=' */ - SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags); - /* Don't allow anything after a symbol definition */ - Done = 1; - } else { - /* Define a label */ - SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL); - /* 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 ("`:' expected"); - } - if (Tok == TOK_NAMESPACE) { - /* Smart :: handling */ - NextTok (); - } - } else { - /* Skip the colon */ - NextTok (); - } - } - } + InitListingLine (); } - 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 (); - } else if (PCAssignment && (Tok == TOK_STAR || Tok == TOK_PC)) { - NextTok (); - if (Tok != TOK_EQ) { - Error ("`=' expected"); - SkipUntilSep (); - } else { - /* Skip the equal sign */ - NextTok (); - /* Enter absolute mode */ - DoPCAssign (); - } - } + /* Single colon means unnamed label */ + if (CurTok.Tok == TOK_COLON) { + ULabDef (); + NextTok (); + } + + /* If the first token on the line is an identifier, check for a macro or + * an instruction. + */ + if (CurTok.Tok == TOK_IDENT) { + if (!UbiquitousIdents) { + /* Macros and symbols cannot use instruction names */ + Instr = FindInstruction (&CurTok.SVal); + if (Instr < 0) { + Mac = FindMacro (&CurTok.SVal); + } + } else { + /* Macros and symbols may use the names of instructions */ + Mac = FindMacro (&CurTok.SVal); + } + } + + /* Handle an identifier. This may be a cheap local symbol, or a fully + * scoped identifier which may start with a namespace token (for global + * namespace) + */ + if (CurTok.Tok == TOK_LOCAL_IDENT || + CurTok.Tok == TOK_NAMESPACE || + (CurTok.Tok == TOK_IDENT && Instr < 0 && Mac == 0)) { + + /* Did we have whitespace before the ident? */ + int HadWS = CurTok.WS; + + /* Generate the symbol table entry, then skip the name */ + Sym = ParseAnySymName (SYM_ALLOC_NEW); + + /* If a colon follows, this is a label definition. If there + * is no colon, it's an assignment. + */ + if (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_ASSIGN) { + + /* Determine the symbol flags from the assignment token */ + unsigned Flags = (CurTok.Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE; + + /* Skip the '=' */ + NextTok (); + + /* Define the symbol with the expression following the '=' */ + SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags); + + /* Don't allow anything after a symbol definition */ + ConsumeSep (); + return; + + } else if (CurTok.Tok == TOK_SET) { + + ExprNode* Expr; + + /* .SET defines variables (= redefinable symbols) */ + NextTok (); + + /* Read the assignment expression, which must be constant */ + Expr = GenLiteralExpr (ConstExpression ()); + + /* Define the symbol with the constant expression following + * the '=' + */ + SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR); + + /* Don't allow anything after a symbol definition */ + ConsumeSep (); + return; + + } else { + + /* A label. Remember the current segment, so we can later + * determine the size of the data stored under the label. + */ + Seg = ActiveSeg; + PC = GetPC (); + + /* Define the label */ + SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL); + + /* Skip the colon. If NoColonLabels is enabled, allow labels + * without a colon if there is no whitespace before the + * identifier. + */ + if (CurTok.Tok != TOK_COLON) { + if (HadWS || !NoColonLabels) { + Error ("`:' expected"); + /* Try some smart error recovery */ + if (CurTok.Tok == TOK_NAMESPACE) { + NextTok (); + } + } + } else { + /* Skip the colon */ + NextTok (); + } + + /* If we come here, a new identifier may be waiting, which may + * be a macro or instruction. + */ + if (CurTok.Tok == TOK_IDENT) { + if (!UbiquitousIdents) { + /* Macros and symbols cannot use instruction names */ + Instr = FindInstruction (&CurTok.SVal); + if (Instr < 0) { + Mac = FindMacro (&CurTok.SVal); + } + } else { + /* Macros and symbols may use the names of instructions */ + Mac = FindMacro (&CurTok.SVal); + } + } + } + } + + /* We've handled a possible label, now handle the remainder of the line */ + if (CurTok.Tok >= TOK_FIRSTPSEUDO && CurTok.Tok <= TOK_LASTPSEUDO) { + /* A control command */ + HandlePseudo (); + } else if (Mac != 0) { + /* A macro expansion */ + MacExpandStart (Mac); + } else if (Instr >= 0 || + (UbiquitousIdents && ((Instr = FindInstruction (&CurTok.SVal)) >= 0))) { + /* A mnemonic - assemble one instruction */ + HandleInstruction (Instr); + } else if (PCAssignment && (CurTok.Tok == TOK_STAR || CurTok.Tok == TOK_PC)) { + NextTok (); + if (CurTok.Tok != TOK_EQ) { + Error ("`=' expected"); + SkipUntilSep (); + } else { + /* Skip the equal sign */ + NextTok (); + /* Enter absolute mode */ + DoPCAssign (); + } + } + + /* If we have defined a label, remember its size. Sym is also set by + * a symbol assignment, but in this case Done is false, so we don't + * come here. + */ + if (Sym) { + unsigned long Size; + if (Seg == ActiveSeg) { + /* Same segment */ + Size = GetPC () - PC; + } else { + /* The line has switched the segment */ + Size = 0; + } + DefSizeOfSymbol (Sym, Size); } /* Line separator must come here */ @@ -450,7 +779,7 @@ static void Assemble (void) NextTok (); /* Assemble lines until end of file */ - while (Tok != TOK_EOF) { + while (CurTok.Tok != TOK_EOF) { OneLine (); } } @@ -481,8 +810,11 @@ static void CreateObjFile (void) /* Write debug symbols if requested */ WriteDbgSyms (); + /* Write the scopes if requested */ + WriteScopes (); + /* Write line infos if requested */ - WriteLineInfo (); + WriteLineInfos (); /* Write the string pool */ WriteStrPool (); @@ -502,29 +834,50 @@ int main (int argc, char* argv []) /* Program long options */ static const LongOpt OptTab[] = { { "--auto-import", 0, OptAutoImport }, + { "--bin-include-dir", 1, OptBinIncludeDir }, { "--cpu", 1, OptCPU }, + { "--create-dep", 1, OptCreateDep }, + { "--create-full-dep", 1, OptCreateFullDep }, { "--debug-info", 0, OptDebugInfo }, { "--feature", 1, OptFeature }, + { "--forget-inc-paths", 0, OptForgetIncPaths }, { "--help", 0, OptHelp }, { "--ignore-case", 0, OptIgnoreCase }, { "--include-dir", 1, OptIncludeDir }, - { "--listing", 0, OptListing }, + { "--list-bytes", 1, OptListBytes }, + { "--listing", 1, OptListing }, + { "--macpack-dir", 1, OptMacPackDir }, + { "--memory-model", 1, OptMemoryModel }, { "--pagelength", 1, OptPageLength }, - { "--smart", 0, OptSmart }, + { "--smart", 0, OptSmart }, { "--target", 1, OptTarget }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, }; + /* Name of the global name space */ + static const StrBuf GlobalNameSpace = STATIC_STRBUF_INITIALIZER; + unsigned I; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "ca65"); + /* Initialize the include search paths */ + InitIncludePaths (); + + /* Create the predefined segments */ + SegInit (); + /* Enter the base lexical level. We must do that here, since we may * define symbols using -D. */ - SymEnterLevel ("", ST_GLOBAL, ADDR_SIZE_DEFAULT); + SymEnterLevel (&GlobalNameSpace, SCOPE_FILE, ADDR_SIZE_DEFAULT, 0); + + /* Initialize the line infos. Must be done here, since we need line infos + * for symbol definitions. + */ + InitLineInfo (); /* Check the parameters */ I = 1; @@ -534,31 +887,39 @@ int main (int argc, char* argv []) const char* Arg = ArgVec [I]; /* Check for an option */ - if (Arg [0] == '-') { - switch (Arg [1]) { + if (Arg[0] == '-') { + switch (Arg[1]) { - case '-': - LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); - break; + case '-': + LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); + break; - case 'g': - OptDebugInfo (Arg, 0); - break; + case 'g': + OptDebugInfo (Arg, 0); + break; - case 'h': - OptHelp (Arg, 0); - break; + case 'h': + OptHelp (Arg, 0); + break; case 'i': - OptIgnoreCase (Arg, 0); - break; + OptIgnoreCase (Arg, 0); + break; - case 'l': - OptListing (Arg, 0); - break; + case 'l': + OptListing (Arg, GetArg (&I, 2)); + break; + + case 'm': + if (Arg[2] == 'm') { + OptMemoryModel (Arg, GetArg (&I, 3)); + } else { + UnknownOption (Arg); + } + break; case 'o': - OutFile = GetArg (&I, 2); + OutFile = GetArg (&I, 2); break; case 's': @@ -582,7 +943,7 @@ int main (int argc, char* argv []) break; case 'U': - OptAutoImport (Arg, 0); + OptAutoImport (Arg, 0); break; case 'V': @@ -628,8 +989,13 @@ int main (int argc, char* argv []) } } - /* Intialize the target translation tables */ - TgtTranslateInit (); + /* If no memory model was given, use the default */ + if (MemoryModel == MMODEL_UNKNOWN) { + SetMemoryModel (MMODEL_NEAR); + } + + /* Set the default segment sizes according to the memory model */ + SetSegmentSizes (); /* Initialize the scanner, open the input file */ InitScanner (InFile); @@ -640,14 +1006,14 @@ int main (int argc, char* argv []) /* Assemble the input */ Assemble (); - /* If we didn't have any errors, check the segment stack */ + /* If we didn't have any errors, check the pseudo insn stacks */ if (ErrorCount == 0) { - SegStackCheck (); + CheckPseudo (); } - /* If we didn't have any errors, check the unnamed labels */ + /* If we didn't have any errors, check and cleanup the unnamed labels */ if (ErrorCount == 0) { - ULabCheck (); + ULabDone (); } /* If we didn't have any errors, check the symbol table */ @@ -655,13 +1021,20 @@ int main (int argc, char* argv []) SymCheck (); } + /* If we didn't have any errors, close the file scope lexical level */ + if (ErrorCount == 0) { + SymLeaveLevel (); + } + /* If we didn't have any errors, check and resolve the segment data */ if (ErrorCount == 0) { - SegCheck (); + SegDone (); } - /* If we didn't have an errors, index the line infos */ - MakeLineInfoIndex (); + /* If we didn't have any errors, check the assertions */ + if (ErrorCount == 0) { + CheckAssertions (); + } /* Dump the data */ if (Verbosity >= 2) { @@ -669,12 +1042,18 @@ int main (int argc, char* argv []) SegDump (); } - /* If we didn't have any errors, create the object and listing files */ + /* If we didn't have an errors, finish off the line infos */ + DoneLineInfo (); + + /* If we didn't have any errors, create the object, listing and + * dependency files + */ if (ErrorCount == 0) { - CreateObjFile (); - if (Listing) { - CreateListing (); - } + CreateObjFile (); + if (SB_GetLen (&ListingName) > 0) { + CreateListing (); + } + CreateDependencies (); } /* Close the input file */