/* */
/* */
/* */
-/* (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 */
#include "cmdline.h"
#include "mmodel.h"
#include "print.h"
+#include "scopedefs.h"
+#include "strbuf.h"
#include "target.h"
#include "tgttrans.h"
#include "version.h"
#include "istack.h"
#include "lineinfo.h"
#include "listing.h"
+#include "macpack.h"
#include "macro.h"
#include "nexttok.h"
#include "objfile.h"
#include "pseudo.h"
#include "scanner.h"
#include "segment.h"
+#include "sizeof.h"
#include "spool.h"
+#include "symbol.h"
#include "symtab.h"
#include "ulabel.h"
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"
- " -mm model\t\tSet the memory model\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"
- " --memory-model model\tSet the memory model\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);
}
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);
}
const char* P;
unsigned I;
long Val;
- char SymName [MAX_STR_LEN+1];
- SymEntry* Sym;
- ExprNode* Expr;
+ 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 != '=') {
}
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);
- /* Generate an expression for the symbol */
- Expr = GenLiteralExpr (Val);
-
- /* Mark the symbol as defined */
- SymDef (Sym, Expr, 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;
+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 */
{
+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;
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 */
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 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);
}
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);
}
if (PC < 0 || PC > 0xFFFFFF) {
Error ("Range error");
} else {
- SetAbsPC (PC);
+ EnterAbsoluteMode (PC);
}
}
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 */
NextTok ();
/* Assemble lines until end of file */
- while (Tok != TOK_EOF) {
+ while (CurTok.Tok != TOK_EOF) {
OneLine ();
}
}
/* Write debug symbols if requested */
WriteDbgSyms ();
+ /* Write the scopes if requested */
+ WriteScopes ();
+
/* Write line infos if requested */
- WriteLineInfo ();
+ WriteLineInfos ();
/* Write the string pool */
WriteStrPool ();
/* 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;
break;
case 'l':
- OptListing (Arg, 0);
+ OptListing (Arg, GetArg (&I, 2));
break;
case 'm':
break;
case 'o':
- OutFile = GetArg (&I, 2);
+ OutFile = GetArg (&I, 2);
break;
case 's':
break;
case 'U':
- OptAutoImport (Arg, 0);
+ OptAutoImport (Arg, 0);
break;
case 'V':
/* If no memory model was given, use the default */
if (MemoryModel == MMODEL_UNKNOWN) {
- MemoryModel = MMODEL_NEAR;
+ SetMemoryModel (MMODEL_NEAR);
}
- /* Intialize the target translation tables */
- TgtTranslateInit ();
-
- /* Initialize the segments */
- InitSegments ();
+ /* Set the default segment sizes according to the memory model */
+ SetSegmentSizes ();
/* Initialize the scanner, open the input file */
InitScanner (InFile);
/* 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 */
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) {
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 */