/* */
/* main.c */
/* */
-/* Main module for the cl65 compile and link utility */
+/* Main module for the cl65 compile-and-link utility */
/* */
/* */
/* */
-/* (C) 1999-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1999-2012, 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 "filetype.h"
#include "fname.h"
+#include "mmodel.h"
#include "strbuf.h"
#include "target.h"
#include "version.h"
static CmdDesc GRC = { 0, 0, 0, 0, 0, 0, 0 };
/* Variables controlling the steps we're doing */
-static int DontLink = 0;
-static int DontAssemble = 0;
+static int DoLink = 1;
+static int DoAssemble = 1;
/* The name of the output file, NULL if none given */
static const char* OutputName = 0;
*/
static const char* FirstInput = 0;
+/* The names of the files for dependency generation */
+static const char* DepName = 0;
+static const char* FullDepName = 0;
+
/* Remember if we should link a module */
static int Module = 0;
/* Extension used for a module */
#define MODULE_EXT ".o65"
-/* Name of the crt0 object file and the runtime library */
-static char* TargetCRT0 = 0;
+/* Name of the target specific runtime library */
static char* TargetLib = 0;
+static void CmdExpand (CmdDesc* Cmd)
+/* Expand the argument vector */
+{
+ unsigned NewMax = Cmd->ArgMax + 10;
+ char** NewArgs = xmalloc (NewMax * sizeof (char*));
+ memcpy (NewArgs, Cmd->Args, Cmd->ArgMax * sizeof (char*));
+ xfree (Cmd->Args);
+ Cmd->Args = NewArgs;
+ Cmd->ArgMax = NewMax;
+}
+
+
+
static void CmdAddArg (CmdDesc* Cmd, const char* Arg)
/* Add a new argument to the command */
{
/* Expand the argument vector if needed */
- if (Cmd->ArgCount == Cmd->ArgMax) {
- unsigned NewMax = Cmd->ArgMax + 10;
- char** NewArgs = xmalloc (NewMax * sizeof (char*));
- memcpy (NewArgs, Cmd->Args, Cmd->ArgMax * sizeof (char*));
- xfree (Cmd->Args);
- Cmd->Args = NewArgs;
- Cmd->ArgMax = NewMax;
+ if (Cmd->ArgCount >= Cmd->ArgMax) {
+ CmdExpand (Cmd);
}
/* Add a copy of the new argument, allow a NULL pointer */
if (Arg) {
- Cmd->Args [Cmd->ArgCount++] = xstrdup (Arg);
+ Cmd->Args[Cmd->ArgCount++] = xstrdup (Arg);
} else {
- Cmd->Args [Cmd->ArgCount++] = 0;
+ Cmd->Args[Cmd->ArgCount++] = 0;
}
}
+static void CmdAddArgList (CmdDesc* Cmd, const char* ArgList)
+/* Add a list of arguments separated by commas */
+{
+ const char* Arg = ArgList;
+ const char* P = Arg;
+
+ while (1) {
+ if (*P == '\0' || *P == ',') {
+
+ /* End of argument, add it */
+ unsigned Len = P - Arg;
+
+ /* Expand the argument vector if needed */
+ if (Cmd->ArgCount >= Cmd->ArgMax) {
+ CmdExpand (Cmd);
+ }
+
+ /* Add the new argument */
+ Cmd->Args[Cmd->ArgCount] = memcpy (xmalloc (Len + 1), Arg, Len);
+ Cmd->Args[Cmd->ArgCount][Len] = '\0';
+ ++Cmd->ArgCount;
+
+ /* If the argument was terminated by a comma, skip it, otherwise
+ * we're done.
+ */
+ if (*P == ',') {
+ /* Start over at next char */
+ Arg = ++P;
+ } else {
+ break;
+ }
+ } else {
+ /* Skip other chars */
+ ++P;
+ }
+ }
+
+}
+
+
+
static void CmdDelArgs (CmdDesc* Cmd, unsigned LastValid)
/* Remove all arguments with an index greater than LastValid */
{
static void CmdSetTarget (CmdDesc* Cmd, target_t Target)
/* Set the output file in a command desc */
{
- CmdAddArg2 (Cmd, "-t", TargetNames[Target]);
+ CmdAddArg2 (Cmd, "-t", GetTargetName (Target));
}
static void SetTargetFiles (void)
/* Set the target system files */
{
- /* Determine the names of the default startup and library file */
+ /* Determine the names of the target specific library file */
if (Target != TGT_NONE) {
/* Get a pointer to the system name and its length */
- const char* TargetName = TargetNames [Target];
+ const char* TargetName = GetTargetName (Target);
unsigned TargetNameLen = strlen (TargetName);
- /* Set the startup file */
- TargetCRT0 = xmalloc (TargetNameLen + 2 + 1);
- strcpy (TargetCRT0, TargetName);
- strcat (TargetCRT0, ".o");
-
/* Set the library file */
TargetLib = xmalloc (TargetNameLen + 4 + 1);
- strcpy (TargetLib, TargetName);
- strcat (TargetLib, ".lib");
+ memcpy (TargetLib, TargetName, TargetNameLen);
+ strcpy (TargetLib + TargetNameLen, ".lib");
}
}
{
unsigned I;
- /* If we have a linker config file given, add it to the command line.
- * Otherwise pass the target to the linker if we have one.
- */
- if (LinkerConfig) {
- if (Module) {
- Error ("Cannot use -C and --module together");
- }
- CmdAddArg2 (&LD65, "-C", LinkerConfig);
- } else if (Module) {
- CmdSetTarget (&LD65, TGT_MODULE);
- } else if (Target != TGT_NONE) {
- CmdSetTarget (&LD65, Target);
- }
-
- /* Determine which target libraries are needed */
- SetTargetFiles ();
-
/* Since linking is always the final step, if we have an output file name
* given, set it here. If we don't have an explicit output name given,
* try to build one from the name of the first input file.
}
- /* If we have a startup file and if we are not linking a module, add its
- * name as a parameter
+ /* If we have a linker config file given, add it to the command line.
+ * Otherwise pass the target to the linker if we have one.
*/
- if (TargetCRT0 && !Module) {
- CmdAddArg (&LD65, TargetCRT0);
+ if (LinkerConfig) {
+ if (Module) {
+ Error ("Cannot use -C and --module together");
+ }
+ CmdAddArg2 (&LD65, "-C", LinkerConfig);
+ } else if (Module) {
+ CmdSetTarget (&LD65, TGT_MODULE);
+ } else {
+ CmdSetTarget (&LD65, Target);
}
+ /* Determine which target libraries are needed */
+ SetTargetFiles ();
+
/* Add all object files as parameters */
for (I = 0; I < LD65.FileCount; ++I) {
CmdAddArg (&LD65, LD65.Files [I]);
-static void Assemble (const char* File)
-/* Assemble the given file */
+static void AssembleFile (const char* File, unsigned ArgCount)
+/* Common routine to assemble a file. Will be called by Assemble() and
+ * AssembleIntermediate(). Adds options common for both routines and
+ * assembles the file. Will remove excess arguments after assembly.
+ */
{
- /* Remember the current assembler argument count */
- unsigned ArgCount = CA65.ArgCount;
-
/* Set the target system */
CmdSetTarget (&CA65, Target);
- /* If we won't link, this is the final step. In this case, set the
- * output name.
- */
- if (DontLink && OutputName) {
- CmdSetOutput (&CA65, OutputName);
+ /* Check if this is the last processing step */
+ if (DoLink) {
+ /* We're linking later. Add the output file of the assembly
+ * the the file list of the linker. The name of the output
+ * file is that of the input file with ".s" replaced by ".o".
+ */
+ char* ObjName = MakeFilename (File, ".o");
+ CmdAddFile (&LD65, ObjName);
+ xfree (ObjName);
} else {
- /* The object file name will be the name of the source file
- * with .s replaced by ".o". Add this file to the list of
- * linker files.
- */
- char* ObjName = MakeFilename (File, ".o");
- CmdAddFile (&LD65, ObjName);
- xfree (ObjName);
+ /* This is the final step. If an output name is given, set it */
+ if (OutputName) {
+ CmdSetOutput (&CA65, OutputName);
+ }
}
/* Add the file as argument for the assembler */
+static void AssembleIntermediate (const char* SourceFile)
+/* Assemble an intermediate file which was generated by a previous processing
+ * step with SourceFile as input. The -dep options won't be added and
+ * the intermediate assembler file is removed after assembly.
+ */
+{
+ /* Generate the name of the assembler output file from the source file
+ * name. It's the same name with the extension replaced by ".s"
+ */
+ char* AsmName = MakeFilename (SourceFile, ".s");
+
+ /* Assemble the intermediate assembler file */
+ AssembleFile (AsmName, CA65.ArgCount);
+
+ /* Remove the input file */
+ if (remove (AsmName) < 0) {
+ Warning ("Cannot remove temporary file `%s': %s",
+ AsmName, strerror (errno));
+ }
+
+ /* Free the assembler file name which was allocated from the heap */
+ xfree (AsmName);
+}
+
+
+
+static void Assemble (const char* File)
+/* Assemble the given file */
+{
+ /* Remember the current assembler argument count */
+ unsigned ArgCount = CA65.ArgCount;
+
+ /* We aren't assembling an intermediate file, but one requested by the
+ * user. So add a few options here if they were given on the command
+ * line.
+ */
+ if (DepName && *DepName) {
+ CmdAddArg2 (&CA65, "--create-dep", DepName);
+ }
+ if (FullDepName && *FullDepName) {
+ CmdAddArg2 (&CA65, "--create-full-dep", FullDepName);
+ }
+
+ /* Use the common routine */
+ AssembleFile (File, ArgCount);
+}
+
+
+
static void Compile (const char* File)
/* Compile the given file */
{
- char* AsmName = 0;
-
/* Remember the current compiler argument count */
unsigned ArgCount = CC65.ArgCount;
/* Set the target system */
CmdSetTarget (&CC65, Target);
- /* If we won't link, this is the final step. In this case, set the
- * output name.
- */
- if (DontAssemble && OutputName) {
- CmdSetOutput (&CC65, OutputName);
+ /* Check if this is the final step */
+ if (DoAssemble) {
+ /* We will assemble this file later. If a dependency file is to be
+ * generated, set the dependency target to be the final object file,
+ * not the intermediate assembler file. But beware: There may be an
+ * output name specified for the assembler.
+ */
+ if (DepName || FullDepName) {
+ /* Was an output name for the assembler specified? */
+ if (!DoLink && OutputName) {
+ /* Use this name as the dependency target */
+ CmdAddArg2 (&CC65, "--dep-target", OutputName);
+ } else {
+ /* Use the object file name as the dependency target */
+ char* ObjName = MakeFilename (File, ".o");
+ CmdAddArg2 (&CC65, "--dep-target", ObjName);
+ xfree (ObjName);
+ }
+ }
} else {
- /* The assembler file name will be the name of the source file
- * with .c replaced by ".s".
- */
- AsmName = MakeFilename (File, ".s");
+ /* If we won't assemble, this is the final step. In this case, set
+ * the output name if it was given.
+ */
+ if (OutputName) {
+ CmdSetOutput (&CC65, OutputName);
+ }
}
/* Add the file as argument for the compiler */
/* If this is not the final step, assemble the generated file, then
* remove it
*/
- if (!DontAssemble) {
- Assemble (AsmName);
- if (remove (AsmName) < 0) {
- Warning ("Cannot remove temporary file `%s': %s",
- AsmName, strerror (errno));
- }
- xfree (AsmName);
+ if (DoAssemble) {
+ /* Assemble the intermediate file and remove it */
+ AssembleIntermediate (File);
}
}
static void CompileRes (const char* File)
/* Compile the given geos resource file */
{
- char* AsmName = 0;
-
/* Remember the current assembler argument count */
unsigned ArgCount = GRC.ArgCount;
- /* The assembler file name will be the name of the source file
- * with .grc replaced by ".s".
+ /* Resource files need an geos-apple or geos-cbm target but this
+ * is checked within grc65.
*/
- AsmName = MakeFilename (File, ".s");
+ CmdSetTarget (&GRC, Target);
/* Add the file as argument for the resource compiler */
CmdAddArg (&GRC, File);
/* If this is not the final step, assemble the generated file, then
* remove it
*/
- if (!DontAssemble) {
- Assemble (AsmName);
- if (remove (AsmName) < 0) {
- Warning ("Cannot remove temporary file `%s': %s",
- AsmName, strerror (errno));
- }
+ if (DoAssemble) {
+ /* Assemble the intermediate file and remove it */
+ AssembleIntermediate (File);
}
-
- /* Free the assembler file name which was allocated from the heap */
- xfree (AsmName);
}
static void ConvertO65 (const char* File)
/* Convert an o65 object file into an assembler file */
{
- char* AsmName = 0;
-
/* Remember the current converter argument count */
unsigned ArgCount = CO65.ArgCount;
- /* If we won't link, this is the final step. In this case, set the
+ /* If we won't assemble, this is the final step. In this case, set the
* output name.
*/
- if (DontAssemble && OutputName) {
- CmdSetOutput (&CO65, OutputName);
- } else {
- /* The assembler file name will be the name of the source file
- * with .c replaced by ".s".
- */
- AsmName = MakeFilename (File, ".s");
+ if (!DoAssemble && OutputName) {
+ CmdSetOutput (&CO65, OutputName);
}
/* Add the file as argument for the object file converter */
/* If this is not the final step, assemble the generated file, then
* remove it
*/
- if (!DontAssemble) {
- Assemble (AsmName);
- if (remove (AsmName) < 0) {
- Warning ("Cannot remove temporary file `%s': %s",
- AsmName, strerror (errno));
- }
+ if (DoAssemble) {
+ /* Assemble the intermediate file and remove it */
+ AssembleIntermediate (File);
}
-
- /* Free the assembler file name which was allocated from the heap */
- xfree (AsmName);
}
static void Usage (void)
/* Print usage information and exit */
{
- fprintf (stderr,
- "Usage: %s [options] file [...]\n"
- "Short options:\n"
- " -c\t\t\tCompile and assemble but don't link\n"
- " -d\t\t\tDebug mode\n"
- " -g\t\t\tAdd debug info\n"
- " -h\t\t\tHelp (this text)\n"
- " -l\t\t\tCreate an assembler listing\n"
- " -m name\t\tCreate a map file\n"
- " -o name\t\tName the output file\n"
- " -r\t\t\tEnable register variables\n"
- " -t sys\t\tSet the target system\n"
- " -v\t\t\tVerbose mode\n"
- " -vm\t\t\tVerbose map file\n"
- " -A\t\t\tStrict ANSI mode\n"
- " -C name\t\tUse linker config file\n"
- " -Cl\t\t\tMake local variables static\n"
- " -D sym[=defn]\t\tDefine a preprocessor symbol\n"
- " -I dir\t\tSet a compiler include directory path\n"
- " -Ln name\t\tCreate a VICE label file\n"
- " -O\t\t\tOptimize code\n"
- " -Oi\t\t\tOptimize code, inline functions\n"
- " -Or\t\t\tOptimize code, honour the register keyword\n"
- " -Os\t\t\tOptimize code, inline known C funtions\n"
- " -S\t\t\tCompile but don't assemble and link\n"
- " -T\t\t\tInclude source as comment\n"
- " -V\t\t\tPrint the version number\n"
- " -W\t\t\tSuppress warnings\n"
- "\n"
- "Long options:\n"
- " --add-source\t\tInclude source as comment\n"
- " --ansi\t\tStrict ANSI mode\n"
- " --asm-include-dir dir\tSet an assembler include directory\n"
- " --bss-label name\tDefine and export a BSS segment label\n"
- " --bss-name seg\tSet the name of the BSS segment\n"
- " --check-stack\t\tGenerate stack overflow checks\n"
- " --code-label name\tDefine and export a CODE segment label\n"
- " --code-name seg\tSet the name of the CODE segment\n"
- " --codesize x\t\tAccept larger code by factor x\n"
- " --cpu type\t\tSet cpu type\n"
- " --create-dep\t\tCreate a make dependency file\n"
- " --data-label name\tDefine and export a DATA segment label\n"
- " --data-name seg\tSet the name of the DATA segment\n"
- " --debug\t\tDebug mode\n"
- " --debug-info\t\tAdd debug info\n"
- " --feature name\tSet an emulation feature\n"
- " --help\t\tHelp (this text)\n"
- " --include-dir dir\tSet a compiler include directory path\n"
- " --listing\t\tCreate an assembler listing\n"
- " --mapfile name\tCreate a map file\n"
- " --module\t\tLink as a module\n"
- " --module-id id\tSpecify a module id for the linker\n"
- " --o65-model model\tOverride the o65 model\n"
- " --register-space b\tSet space available for register variables\n"
- " --register-vars\tEnable register variables\n"
- " --rodata-name seg\tSet the name of the RODATA segment\n"
- " --signed-chars\tDefault characters are signed\n"
- " --start-addr addr\tSet the default start address\n"
- " --static-locals\tMake local variables static\n"
- " --target sys\t\tSet the target system\n"
- " --version\t\tPrint the version number\n"
- " --verbose\t\tVerbose mode\n"
- " --zeropage-label name\tDefine and export a ZEROPAGE segment label\n"
- " --zeropage-name seg\tSet the name of the ZEROPAGE segment\n",
- ProgName);
+ printf ("Usage: %s [options] file [...]\n"
+ "Short options:\n"
+ " -c\t\t\t\tCompile and assemble, but don't link\n"
+ " -d\t\t\t\tDebug mode\n"
+ " -g\t\t\t\tAdd debug info\n"
+ " -h\t\t\t\tHelp (this text)\n"
+ " -l name\t\t\tCreate an assembler listing file\n"
+ " -m name\t\t\tCreate a map file\n"
+ " -mm model\t\t\tSet the memory model\n"
+ " -o name\t\t\tName the output file\n"
+ " -r\t\t\t\tEnable register variables\n"
+ " -t sys\t\t\tSet the target system\n"
+ " -u sym\t\t\tForce an import of symbol `sym'\n"
+ " -v\t\t\t\tVerbose mode\n"
+ " -vm\t\t\t\tVerbose map file\n"
+ " -C name\t\t\tUse linker config file\n"
+ " -Cl\t\t\t\tMake local variables static\n"
+ " -D sym[=defn]\t\t\tDefine a preprocessor symbol\n"
+ " -I dir\t\t\tSet a compiler include directory path\n"
+ " -L path\t\t\tSpecify a library search path\n"
+ " -Ln name\t\t\tCreate a VICE label file\n"
+ " -O\t\t\t\tOptimize code\n"
+ " -Oi\t\t\t\tOptimize code, inline runtime functions\n"
+ " -Or\t\t\t\tOptimize code, honour the register keyword\n"
+ " -Os\t\t\t\tOptimize code, inline known C functions\n"
+ " -S\t\t\t\tCompile, but don't assemble and link\n"
+ " -T\t\t\t\tInclude source as comment\n"
+ " -V\t\t\t\tPrint the version number\n"
+ " -W name[,...]\t\t\tSuppress compiler warnings\n"
+ " -Wa options\t\t\tPass options to the assembler\n"
+ " -Wc options\t\t\tPass options to the compiler\n"
+ " -Wl options\t\t\tPass options to the linker\n"
+ "\n"
+ "Long options:\n"
+ " --add-source\t\t\tInclude source as comment\n"
+ " --asm-args options\t\tPass options to the assembler\n"
+ " --asm-define sym[=v]\t\tDefine an assembler symbol\n"
+ " --asm-include-dir dir\t\tSet an assembler include directory\n"
+ " --bin-include-dir dir\t\tSet an assembler binary include directory\n"
+ " --bss-label name\t\tDefine and export a BSS segment label\n"
+ " --bss-name seg\t\tSet the name of the BSS segment\n"
+ " --cc-args options\t\tPass options to the compiler\n"
+ " --cfg-path path\t\tSpecify a config file search path\n"
+ " --check-stack\t\t\tGenerate stack overflow checks\n"
+ " --code-label name\t\tDefine and export a CODE segment label\n"
+ " --code-name seg\t\tSet the name of the CODE segment\n"
+ " --codesize x\t\t\tAccept larger code by factor x\n"
+ " --config name\t\t\tUse linker config file\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"
+ " --data-label name\t\tDefine and export a DATA segment label\n"
+ " --data-name seg\t\tSet the name of the DATA segment\n"
+ " --debug\t\t\tDebug mode\n"
+ " --debug-info\t\t\tAdd debug info\n"
+ " --feature name\t\tSet an emulation feature\n"
+ " --force-import sym\t\tForce an import of symbol `sym'\n"
+ " --forget-inc-paths\t\tForget include search paths (compiler)\n"
+ " --help\t\t\tHelp (this text)\n"
+ " --include-dir dir\t\tSet a compiler include directory path\n"
+ " --ld-args options\t\tPass options to the linker\n"
+ " --lib file\t\t\tLink this library\n"
+ " --lib-path path\t\tSpecify a library search path\n"
+ " --list-targets\t\tList all available targets\n"
+ " --listing name\t\tCreate an assembler listing file\n"
+ " --list-bytes n\t\tNumber of bytes per assembler listing line\n"
+ " --mapfile name\t\tCreate a map file\n"
+ " --memory-model model\t\tSet the memory model\n"
+ " --module\t\t\tLink as a module\n"
+ " --module-id id\t\tSpecify a module ID for the linker\n"
+ " --o65-model model\t\tOverride the o65 model\n"
+ " --obj file\t\t\tLink this object file\n"
+ " --obj-path path\t\tSpecify an object file search path\n"
+ " --register-space b\t\tSet space available for register variables\n"
+ " --register-vars\t\tEnable register variables\n"
+ " --rodata-name seg\t\tSet the name of the RODATA segment\n"
+ " --signed-chars\t\tDefault characters are signed\n"
+ " --standard std\t\tLanguage standard (c89, c99, cc65)\n"
+ " --start-addr addr\t\tSet the default start address\n"
+ " --static-locals\t\tMake local variables static\n"
+ " --target sys\t\t\tSet the target system\n"
+ " --version\t\t\tPrint the version number\n"
+ " --verbose\t\t\tVerbose mode\n"
+ " --zeropage-label name\t\tDefine and export a ZEROPAGE segment label\n"
+ " --zeropage-name seg\t\tSet the name of the ZEROPAGE segment\n",
+ ProgName);
}
-static void OptAnsi (const char* Opt attribute ((unused)),
- const char* Arg attribute ((unused)))
-/* Strict ANSI mode (compiler) */
+static void OptAsmArgs (const char* Opt attribute ((unused)), const char* Arg)
+/* Pass arguments to the assembler */
+{
+ CmdAddArgList (&CA65, Arg);
+}
+
+
+
+static void OptAsmDefine (const char* Opt attribute ((unused)), const char* Arg)
+/* Define an assembler symbol (assembler) */
{
- CmdAddArg (&CC65, "-A");
+ CmdAddArg2 (&CA65, "-D", Arg);
}
+static void OptBinIncludeDir (const char* Opt attribute ((unused)), const char* Arg)
+/* Binary include directory (assembler) */
+{
+ CmdAddArg2 (&CA65, "--bin-include-dir", Arg);
+}
+
+
+
static void OptBssLabel (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --bss-label option */
{
+static void OptCCArgs (const char* Opt attribute ((unused)), const char* Arg)
+/* Pass arguments to the compiler */
+{
+ CmdAddArgList (&CC65, Arg);
+}
+
+
+
+static void OptCfgPath (const char* Opt attribute ((unused)), const char* Arg)
+/* Config file search path (linker) */
+{
+ CmdAddArg2 (&LD65, "--cfg-path", Arg);
+}
+
+
+
static void OptCheckStack (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Handle the --check-stack option */
+static void OptConfig (const char* Opt attribute ((unused)), const char* Arg)
+/* Config file (linker) */
+{
+ if (LinkerConfig) {
+ Error ("Cannot specify -C/--config twice");
+ }
+ LinkerConfig = Arg;
+}
+
+
+
static void OptCPU (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --cpu option */
{
-static void OptCreateDep (const char* Opt attribute ((unused)),
- const char* Arg attribute ((unused)))
+static void OptCreateDep (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --create-dep option */
{
- CmdAddArg (&CC65, "--create-dep");
+ /* Add the file name to the compiler */
+ CmdAddArg2 (&CC65, "--create-dep", Arg);
+
+ /* Remember the file name for the assembler */
+ DepName = Arg;
+}
+
+
+
+static void OptCreateFullDep (const char* Opt attribute ((unused)), const char* Arg)
+/* Handle the --create-full-dep option */
+{
+ /* Add the file name to the compiler */
+ CmdAddArg2 (&CC65, "--create-full-dep", Arg);
+
+ /* Remember the file name for the assembler */
+ FullDepName = Arg;
}
+static void OptForceImport (const char* Opt attribute ((unused)), const char* Arg)
+/* Emulation features for the assembler */
+{
+ CmdAddArg2 (&LD65, "-u", Arg);
+}
+
+
+
+static void OptForgetIncPaths (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* Forget all currently defined include paths */
+{
+ CmdAddArg (&CC65, "--forget-inc-paths");
+}
+
+
+
static void OptHelp (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Print help - cl65 */
-static void OptListing (const char* Opt attribute ((unused)),
- const char* Arg attribute ((unused)))
+static void OptLdArgs (const char* Opt attribute ((unused)), const char* Arg)
+/* Pass arguments to the linker */
+{
+ CmdAddArgList (&LD65, Arg);
+}
+
+
+
+static void OptLib (const char* Opt attribute ((unused)), const char* Arg)
+/* Library file follows (linker) */
+{
+ CmdAddArg2 (&LD65, "--lib", Arg);
+}
+
+
+
+static void OptLibPath (const char* Opt attribute ((unused)), const char* Arg)
+/* Library search path (linker) */
+{
+ CmdAddArg2 (&LD65, "--lib-path", Arg);
+}
+
+
+
+static void OptListBytes (const char* Opt attribute ((unused)), const char* Arg)
+/* Set the maximum number of bytes per asm listing line */
+{
+ CmdAddArg2 (&CA65, "--list-bytes", Arg);
+}
+
+
+
+static void OptListing (const char* Opt attribute ((unused)), const char* Arg)
/* Create an assembler listing */
{
- CmdAddArg (&CA65, "-l");
+ CmdAddArg2 (&CA65, "-l", Arg);
+}
+
+
+
+static void OptListTargets (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* List all targets */
+{
+ target_t T;
+
+ /* List the targets */
+ for (T = TGT_NONE; T < TGT_COUNT; ++T) {
+ printf ("%s\n", GetTargetName (T));
+ }
+
+ /* Terminate */
+ exit (EXIT_SUCCESS);
}
+static void OptMemoryModel (const char* Opt attribute ((unused)), const char* Arg)
+/* Set the memory model */
+{
+ mmodel_t MemoryModel = FindMemoryModel (Arg);
+ if (MemoryModel == MMODEL_UNKNOWN) {
+ Error ("Unknown memory model: %s", Arg);
+ } else if (MemoryModel == MMODEL_HUGE) {
+ Error ("Unsupported memory model: %s", Arg);
+ } else {
+ CmdAddArg2 (&CA65, "-mm", Arg);
+ CmdAddArg2 (&CC65, "-mm", Arg);
+ }
+}
+
+
+
static void OptModule (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Link as a module */
+static void OptObj (const char* Opt attribute ((unused)), const char* Arg)
+/* Object file follows (linker) */
+{
+ CmdAddArg2 (&LD65, "--obj", Arg);
+}
+
+
+
+static void OptObjPath (const char* Opt attribute ((unused)), const char* Arg)
+/* Object file search path (linker) */
+{
+ CmdAddArg2 (&LD65, "--obj-path", Arg);
+}
+
+
+
static void OptRegisterSpace (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --register-space option */
{
+static void OptStandard (const char* Opt attribute ((unused)), const char* Arg)
+/* Set the language standard */
+{
+ CmdAddArg2 (&CC65, "--standard", Arg);
+}
+
+
+
static void OptStartAddr (const char* Opt attribute ((unused)), const char* Arg)
/* Set the default start address */
{
/* Print version number */
{
fprintf (stderr,
- "cl65 V%u.%u.%u - (C) Copyright 1998-2003 Ullrich von Bassewitz\n",
- VER_MAJOR, VER_MINOR, VER_PATCH);
+ "cl65 V%s - (C) Copyright 1998-2011 Ullrich von Bassewitz\n",
+ GetVersionAsString ());
}
/* Program long options */
static const LongOpt OptTab[] = {
{ "--add-source", 0, OptAddSource },
- { "--ansi", 0, OptAnsi },
+ { "--asm-args", 1, OptAsmArgs },
+ { "--asm-define", 1, OptAsmDefine },
{ "--asm-include-dir", 1, OptAsmIncludeDir },
+ { "--bin-include-dir", 1, OptBinIncludeDir },
{ "--bss-label", 1, OptBssLabel },
{ "--bss-name", 1, OptBssName },
+ { "--cc-args", 1, OptCCArgs },
+ { "--cfg-path", 1, OptCfgPath },
{ "--check-stack", 0, OptCheckStack },
{ "--code-label", 1, OptCodeLabel },
{ "--code-name", 1, OptCodeName },
{ "--codesize", 1, OptCodeSize },
+ { "--config", 1, OptConfig },
{ "--cpu", 1, OptCPU },
- { "--create-dep", 0, OptCreateDep },
+ { "--create-dep", 1, OptCreateDep },
+ { "--create-full-dep", 1, OptCreateFullDep },
{ "--data-label", 1, OptDataLabel },
{ "--data-name", 1, OptDataName },
{ "--debug", 0, OptDebug },
{ "--debug-info", 0, OptDebugInfo },
{ "--feature", 1, OptFeature },
+ { "--force-import", 1, OptForceImport },
+ { "--forget-inc-paths", 0, OptForgetIncPaths },
{ "--help", 0, OptHelp },
{ "--include-dir", 1, OptIncludeDir },
- { "--listing", 0, OptListing },
+ { "--ld-args", 1, OptLdArgs },
+ { "--lib", 1, OptLib },
+ { "--lib-path", 1, OptLibPath },
+ { "--list-targets", 0, OptListTargets },
+ { "--listing", 1, OptListing },
+ { "--list-bytes", 1, OptListBytes },
{ "--mapfile", 1, OptMapFile },
+ { "--memory-model", 1, OptMemoryModel },
{ "--module", 0, OptModule },
{ "--module-id", 1, OptModuleId },
{ "--o65-model", 1, OptO65Model },
+ { "--obj", 1, OptObj },
+ { "--obj-path", 1, OptObjPath },
{ "--register-space", 1, OptRegisterSpace },
{ "--register-vars", 0, OptRegisterVars },
{ "--rodata-name", 1, OptRodataName },
{ "--signed-chars", 0, OptSignedChars },
+ { "--standard", 1, OptStandard },
{ "--start-addr", 1, OptStartAddr },
{ "--static-locals", 0, OptStaticLocals },
{ "--target", 1, OptTarget },
CmdInit (&CA65, "ca65");
CmdInit (&CO65, "co65");
CmdInit (&LD65, "ld65");
- CmdInit (&GRC, "grc");
+ CmdInit (&GRC, "grc65");
/* Our default target is the C64 instead of "none" */
Target = TGT_C64;
LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
break;
- case 'A':
- /* Strict ANSI mode (compiler) */
- OptAnsi (Arg, 0);
- break;
-
case 'C':
if (Arg[2] == 'l' && Arg[3] == '\0') {
/* Make local variables static */
OptStaticLocals (Arg, 0);
} else {
/* Specify linker config file */
- LinkerConfig = GetArg (&I, 2);
+ OptConfig (Arg, GetArg (&I, 2));
}
break;
break;
case 'L':
- if (Arg[2] == 'n') {
+ if (Arg[2] == 'n' && Arg[3] == '\0') {
/* VICE label file (linker) */
CmdAddArg2 (&LD65, "-Ln", GetArg (&I, 3));
} else {
- UnknownOption (Arg);
+ /* Library search path (linker) */
+ OptLibPath (Arg, GetArg (&I, 2));
}
break;
case 'S':
/* Dont assemble and link the created files */
- DontLink = DontAssemble = 1;
+ DoAssemble = 0;
+ DoLink = 0;
break;
case 'T':
OptVersion (Arg, 0);
break;
- case 'W':
- /* Suppress warnings - compiler and assembler */
- CmdAddArg (&CC65, "-W");
- CmdAddArg2 (&CA65, "-W", "0");
- break;
+ case 'W':
+ if (Arg[2] == 'a' && Arg[3] == '\0') {
+ /* -Wa: Pass options to assembler */
+ OptAsmArgs (Arg, GetArg (&I, 3));
+ } else if (Arg[2] == 'c' && Arg[3] == '\0') {
+ /* -Wc: Pass options to compiler */
+ OptCCArgs (Arg, GetArg (&I, 3));
+ } else if (Arg[2] == 'l' && Arg[3] == '\0') {
+ /* -Wl: Pass options to linker */
+ OptLdArgs (Arg, GetArg (&I, 3));
+ } else {
+ /* Anything else: Suppress warnings (compiler) */
+ CmdAddArg2 (&CC65, "-W", GetArg (&I, 2));
+ }
+ break;
case 'c':
/* Don't link the resulting files */
- DontLink = 1;
+ DoLink = 0;
break;
case 'd':
case 'l':
/* Create an assembler listing */
- OptListing (Arg, 0);
+ OptListing (Arg, GetArg (&I, 2));
break;
case 'm':
OptTarget (Arg, GetArg (&I, 2));
break;
+ case 'u':
+ /* Force an import (linker) */
+ OptForceImport (Arg, GetArg (&I, 2));
+ break;
+
case 'v':
if (Arg [2] == 'm') {
/* Verbose map file (linker) */
case FILETYPE_ASM:
/* Assemble the file */
- if (!DontAssemble) {
+ if (DoAssemble) {
Assemble (Arg);
}
break;
}
/* Link the given files if requested and if we have any */
- if (DontLink == 0 && LD65.FileCount > 0) {
+ if (DoLink && LD65.FileCount > 0) {
Link ();
}