X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcl65%2Fmain.c;h=c2f09323bf66dff3a073dbef5236893163e98ba2;hb=8084702a58b3c5b669b735a98db7c9c14e383529;hp=d6119240a44e536e8a038596948fa298fa122d71;hpb=79a2185c42d82f98dd66c5a996bbb887a4f8648e;p=cc65 diff --git a/src/cl65/main.c b/src/cl65/main.c index d6119240a..c2f09323b 100644 --- a/src/cl65/main.c +++ b/src/cl65/main.c @@ -1,47 +1,61 @@ /*****************************************************************************/ -/* */ -/* main.c */ -/* */ -/* 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 */ -/* */ -/* */ -/* This software is provided 'as-is', without any expressed or implied */ +/* */ +/* main.c */ +/* */ +/* Main module for the cl65 compile-and-link utility */ +/* */ +/* */ +/* */ +/* (C) 1999-2013, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ -/* arising from the use of this software. */ -/* */ +/* arising from the use of this software. */ +/* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ -/* freely, subject to the following restrictions: */ -/* */ +/* freely, subject to the following restrictions: */ +/* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ -/* appreciated but is not required. */ +/* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ -/* be misrepresented as being the original software. */ -/* 3. This notice may not be removed or altered from any source */ -/* distribution. */ -/* */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ /*****************************************************************************/ /* Check out if we have a spawn() function on the system, or if we must use - * our own. - */ -#if defined(__WATCOMC__) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__DJGPP__) -# define HAVE_SPAWN 1 +** our own. +*/ +#if defined(_WIN32) +# define HAVE_SPAWN 1 #else -# define NEED_SPAWN 1 +# define NEED_SPAWN 1 #endif +/* GCC strictly follows http://c-faq.com/ansi/constmismatch.html and issues an +** 'incompatible pointer type' warning - that can't be suppressed via #pragma. +** The spawnvp() prototype of MinGW (http://www.mingw.org/) differs from the +** one of MinGW-w64 (http://mingw-w64.sourceforge.net/) regarding constness. +** So there's no alternative to actually distinguish these environments :-( +*/ +#define SPAWN_ARGV_CONST_CAST +#if defined(__MINGW32__) +# include <_mingw.h> +# if !defined(__MINGW64_VERSION_MAJOR) +# undef SPAWN_ARGV_CONST_CAST +# define SPAWN_ARGV_CONST_CAST (const char* const *) +# endif +#endif #include @@ -49,14 +63,17 @@ #include #include #include -#ifdef HAVE_SPAWN +#if defined(HAVE_SPAWN) # include #endif /* common */ #include "attrib.h" #include "cmdline.h" +#include "filetype.h" #include "fname.h" +#include "mmodel.h" +#include "searchpath.h" #include "strbuf.h" #include "target.h" #include "version.h" @@ -69,7 +86,7 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ @@ -77,15 +94,15 @@ /* Struct that describes a command */ typedef struct CmdDesc CmdDesc; struct CmdDesc { - char* Name; /* The command name */ + char* Name; /* The command name */ - unsigned ArgCount; /* Count of arguments */ - unsigned ArgMax; /* Maximum count of arguments */ - char** Args; /* The arguments */ + unsigned ArgCount; /* Count of arguments */ + unsigned ArgMax; /* Maximum count of arguments */ + char** Args; /* The arguments */ - unsigned FileCount; /* Count of files to translate */ - unsigned FileMax; /* Maximum count of files */ - char** Files; /* The files */ + unsigned FileCount; /* Count of files to translate */ + unsigned FileMax; /* Maximum count of files */ + char** Files; /* The files */ }; /* Command descriptors for the different programs */ @@ -95,23 +112,9 @@ static CmdDesc CO65 = { 0, 0, 0, 0, 0, 0, 0 }; static CmdDesc LD65 = { 0, 0, 0, 0, 0, 0, 0 }; static CmdDesc GRC = { 0, 0, 0, 0, 0, 0, 0 }; -/* File types */ -enum { - FILETYPE_UNKNOWN, - FILETYPE_C, - FILETYPE_ASM, - FILETYPE_OBJ, - FILETYPE_LIB, - FILETYPE_GR, /* GEOS resource file */ - FILETYPE_O65 /* O65 object file */ -}; - -/* Default file type, used if type unknown */ -static unsigned DefaultFileType = FILETYPE_UNKNOWN; - /* 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; @@ -120,19 +123,23 @@ static const char* OutputName = 0; static const char* LinkerConfig = 0; /* The name of the first input file. This will be used to construct the - * executable file name if no explicit name is given. - */ +** executable file name if no explicit name is given. +*/ 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; -static char* TargetLib = 0; +/* Name of the target specific runtime library */ +static char* TargetLib = 0; +static int NoStdLib = 0; @@ -143,106 +150,167 @@ static char* TargetLib = 0; #if defined(NEED_SPAWN) -# if defined(SPAWN_UNIX) -# include "spawn-unix.inc" -# elif defined(SPAWN_AMIGA) +# if defined(_AMIGA) # include "spawn-amiga.inc" # else -# error "Don't know which spawn module to include!" +# include "spawn-unix.inc" # endif #endif /*****************************************************************************/ -/* Determine a file type */ +/* Credential functions */ /*****************************************************************************/ -static unsigned GetFileType (const char* File) -/* Determine the type of the given file */ -{ - /* Table mapping extensions to file types */ - static const struct { - const char* Ext; - unsigned Type; - } FileTypes [] = { - { ".c", FILETYPE_C }, - { ".s", FILETYPE_ASM }, - { ".asm", FILETYPE_ASM }, - { ".a65", FILETYPE_ASM }, - { ".o", FILETYPE_OBJ }, - { ".obj", FILETYPE_OBJ }, - { ".a", FILETYPE_LIB }, - { ".lib", FILETYPE_LIB }, - { ".grc", FILETYPE_GR }, - { ".o65", FILETYPE_O65 }, - { ".emd", FILETYPE_O65 }, - { ".joy", FILETYPE_O65 }, - { ".tgi", FILETYPE_O65 }, - }; +static void DisableAssembling (void) +{ + DoAssemble = 0; +} - unsigned I; - /* Determine the file type by the extension */ - const char* Ext = FindExt (File); - /* Do we have an extension? */ - if (Ext == 0) { - return DefaultFileType; - } +static void DisableLinking (void) +{ + DoLink = 0; +} - /* Check for known extensions */ - for (I = 0; I < sizeof (FileTypes) / sizeof (FileTypes [0]); ++I) { - if (strcmp (FileTypes [I].Ext, Ext) == 0) { - /* Found */ - return FileTypes [I].Type; - } - } - /* Not found, return the default */ - return DefaultFileType; + +static void DisableAssemblingAndLinking (void) +{ + DisableAssembling (); + DisableLinking (); } /*****************************************************************************/ -/* Command structure handling */ +/* Command structure handling */ /*****************************************************************************/ +static char* CmdAllocArg (const char* Arg, unsigned Len) +/* Alloc (potentially quoted) argument */ +{ + char* Alloc; + +/* The Microsoft docs say on spawnvp(): +** Spaces embedded in strings may cause unexpected behavior; for example, +** passing _spawn the string "hi there" will result in the new process getting +** two arguments, "hi" and "there". If the intent was to have the new process +** open a file named "hi there", the process would fail. You can avoid this by +** quoting the string: "\"hi there\"". +*/ +#if defined(_WIN32) + /* Quote argument if it contains space(s) */ + if (memchr (Arg, ' ', Len)) { + Alloc = xmalloc (Len + 3); + Alloc[0] = '"'; + memcpy (Alloc + 1, Arg, Len); + Alloc[Len + 1] = '"'; + Alloc[Len + 2] = '\0'; + } else +#endif + { + Alloc = xmalloc (Len + 1); + memcpy (Alloc, Arg, Len); + Alloc[Len] = '\0'; + } + return Alloc; +} + + + +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++] = CmdAllocArg (Arg, strlen (Arg)); } else { - Cmd->Args [Cmd->ArgCount++] = 0; + Cmd->Args[Cmd->ArgCount++] = 0; } } +static void CmdAddArg2 (CmdDesc* Cmd, const char* Arg1, const char* Arg2) +/* Add a new argument pair to the command */ +{ + CmdAddArg (Cmd, Arg1); + CmdAddArg (Cmd, Arg2); +} + + + +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++] = CmdAllocArg (Arg, Len); + + /* 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 */ { while (Cmd->ArgCount > LastValid) { - Cmd->ArgCount--; - xfree (Cmd->Args [Cmd->ArgCount]); - Cmd->Args [Cmd->ArgCount] = 0; + Cmd->ArgCount--; + xfree (Cmd->Args [Cmd->ArgCount]); + Cmd->Args [Cmd->ArgCount] = 0; } } @@ -253,48 +321,56 @@ static void CmdAddFile (CmdDesc* Cmd, const char* File) { /* Expand the file vector if needed */ if (Cmd->FileCount == Cmd->FileMax) { - unsigned NewMax = Cmd->FileMax + 10; - char** NewFiles = xmalloc (NewMax * sizeof (char*)); - memcpy (NewFiles, Cmd->Files, Cmd->FileMax * sizeof (char*)); - xfree (Cmd->Files); - Cmd->Files = NewFiles; - Cmd->FileMax = NewMax; + unsigned NewMax = Cmd->FileMax + 10; + char** NewFiles = xmalloc (NewMax * sizeof (char*)); + memcpy (NewFiles, Cmd->Files, Cmd->FileMax * sizeof (char*)); + xfree (Cmd->Files); + Cmd->Files = NewFiles; + Cmd->FileMax = NewMax; } /* If the file name is not NULL (which is legal and is used to terminate - * the file list), check if the file name does already exist in the file - * list and print a warning if so. Regardless of the search result, add - * the file. - */ + ** the file list), check if the file name does already exist in the file + ** list and print a warning if so. Regardless of the search result, add + ** the file. + */ if (File) { - unsigned I; - for (I = 0; I < Cmd->FileCount; ++I) { - if (strcmp (Cmd->Files[I], File) == 0) { - /* Duplicate file */ - Warning ("Duplicate file in argument list: `%s'", File); - /* No need to search further */ - break; - } - } - - /* Add the file */ - Cmd->Files [Cmd->FileCount++] = xstrdup (File); + unsigned I; + for (I = 0; I < Cmd->FileCount; ++I) { + if (strcmp (Cmd->Files[I], File) == 0) { + /* Duplicate file */ + Warning ("Duplicate file in argument list: `%s'", File); + /* No need to search further */ + break; + } + } + + /* Add the file */ + Cmd->Files [Cmd->FileCount++] = xstrdup (File); } else { - /* Add a NULL pointer */ - Cmd->Files [Cmd->FileCount++] = 0; + /* Add a NULL pointer */ + Cmd->Files [Cmd->FileCount++] = 0; } } -static void CmdInit (CmdDesc* Cmd, const char* Path) -/* Initialize the command using the given path to the executable */ +static void CmdInit (CmdDesc* Cmd, const char* Path, const char* Name) +/* Initialize the command using the given path and name of the executable */ { + char* FullName; + + FullName = (char*) xmalloc (strlen (Path) + strlen (Name) + 1); + strcpy (FullName, Path); + strcat (FullName, Name); + /* Remember the command */ - Cmd->Name = xstrdup (Path); + Cmd->Name = xstrdup (FullName); /* Use the command name as first argument */ - CmdAddArg (Cmd, Path); + CmdAddArg (Cmd, FullName); + + xfree (FullName); } @@ -302,8 +378,7 @@ static void CmdInit (CmdDesc* Cmd, const char* Path) static void CmdSetOutput (CmdDesc* Cmd, const char* File) /* Set the output file in a command desc */ { - CmdAddArg (Cmd, "-o"); - CmdAddArg (Cmd, File); + CmdAddArg2 (Cmd, "-o", File); } @@ -311,8 +386,7 @@ static void CmdSetOutput (CmdDesc* Cmd, const char* File) static void CmdSetTarget (CmdDesc* Cmd, target_t Target) /* Set the output file in a command desc */ { - CmdAddArg (Cmd, "-t"); - CmdAddArg (Cmd, TargetNames[Target]); + CmdAddArg2 (Cmd, "-t", GetTargetName (Target)); } @@ -322,14 +396,14 @@ static void CmdPrint (CmdDesc* Cmd, FILE* F) { unsigned I; for (I = 0; I < Cmd->ArgCount && Cmd->Args[I] != 0; ++I) { - fprintf (F, "%s ", Cmd->Args[I]); + fprintf (F, "%s ", Cmd->Args[I]); } } /*****************************************************************************/ -/* Target handling */ +/* Target handling */ /*****************************************************************************/ @@ -337,30 +411,20 @@ static void CmdPrint (CmdDesc* Cmd, FILE* F) static void SetTargetFiles (void) /* Set the target system files */ { - /* Determine the names of the default startup and library file */ - if (Target != TGT_NONE) { - - /* Get a pointer to the system name and its length */ - const char* TargetName = TargetNames [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"); - - } + /* Get a pointer to the system name and its length */ + const char* TargetName = GetTargetName (Target); + unsigned TargetNameLen = strlen (TargetName); + + /* Set the library file */ + TargetLib = xmalloc (TargetNameLen + 4 + 1); + memcpy (TargetLib, TargetName, TargetNameLen); + strcpy (TargetLib + TargetNameLen, ".lib"); } /*****************************************************************************/ -/* Subprocesses */ +/* Subprocesses */ /*****************************************************************************/ @@ -372,21 +436,21 @@ static void ExecProgram (CmdDesc* Cmd) /* If in debug mode, output the command line we will execute */ if (Debug) { - printf ("Executing: "); - CmdPrint (Cmd, stdout); - printf ("\n"); + printf ("Executing: "); + CmdPrint (Cmd, stdout); + printf ("\n"); } /* Call the program */ - Status = spawnvp (P_WAIT, Cmd->Name, Cmd->Args); + Status = spawnvp (P_WAIT, Cmd->Name, SPAWN_ARGV_CONST_CAST Cmd->Args); /* Check the result code */ if (Status < 0) { - /* Error executing the program */ - Error ("Cannot execute `%s': %s", Cmd->Name, strerror (errno)); + /* Error executing the program */ + Error ("Cannot execute `%s': %s", Cmd->Name, strerror (errno)); } else if (Status != 0) { - /* Called program had an error */ - exit (Status); + /* Called program had an error */ + exit (Status); } } @@ -397,56 +461,51 @@ static void Link (void) { 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"); - } - CmdAddArg (&LD65, "-C"); - CmdAddArg (&LD65, 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. - */ + ** 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 (OutputName) { - CmdSetOutput (&LD65, OutputName); + CmdSetOutput (&LD65, OutputName); } else if (FirstInput && FindExt (FirstInput)) { /* Only if ext present! */ const char* Extension = Module? MODULE_EXT : ""; - char* Output = MakeFilename (FirstInput, Extension); - CmdSetOutput (&LD65, Output); - xfree (Output); + char* Output = MakeFilename (FirstInput, Extension); + CmdSetOutput (&LD65, Output); + xfree (Output); } - /* If we have a startup file and if we are not linking a module, add its - * name as a parameter - */ - if (TargetCRT0 && !Module) { - CmdAddArg (&LD65, TargetCRT0); + /* 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 { + CmdSetTarget (&LD65, Target); } /* Add all object files as parameters */ for (I = 0; I < LD65.FileCount; ++I) { - CmdAddArg (&LD65, LD65.Files [I]); + CmdAddArg (&LD65, LD65.Files [I]); } - /* Add the system runtime library */ - if (TargetLib) { - CmdAddArg (&LD65, TargetLib); + /* Add the standard runtime library if it is not disabled */ + if (!NoStdLib) + { + /* Determine which target library is needed */ + SetTargetFiles (); + + if (TargetLib) { + CmdAddArg (&LD65, TargetLib); + } } /* Terminate the argument list with a NULL pointer */ @@ -458,28 +517,29 @@ static void Link (void) -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 */ @@ -497,27 +557,90 @@ static void Assemble (const char* File) +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 */ @@ -533,15 +656,11 @@ static void Compile (const char* File) CmdDelArgs (&CC65, ArgCount); /* 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); + ** remove it + */ + if (DoAssemble) { + /* Assemble the intermediate file and remove it */ + AssembleIntermediate (File); } } @@ -550,15 +669,13 @@ static void Compile (const char* 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". - */ - AsmName = MakeFilename (File, ".s"); + /* Resource files need an geos-apple or geos-cbm target but this + ** is checked within grc65. + */ + CmdSetTarget (&GRC, Target); /* Add the file as argument for the resource compiler */ CmdAddArg (&GRC, File); @@ -573,18 +690,12 @@ static void CompileRes (const char* File) CmdDelArgs (&GRC, ArgCount); /* 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)); - } + ** remove it + */ + if (DoAssemble) { + /* Assemble the intermediate file and remove it */ + AssembleIntermediate (File); } - - /* Free the assembler file name which was allocated from the heap */ - xfree (AsmName); } @@ -592,21 +703,14 @@ static void CompileRes (const char* File) 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 - * 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 we won't assemble, this is the final step. In this case, set the + ** output name. + */ + if (!DoAssemble && OutputName) { + CmdSetOutput (&CO65, OutputName); } /* Add the file as argument for the object file converter */ @@ -622,24 +726,18 @@ static void ConvertO65 (const char* File) CmdDelArgs (&CO65, ArgCount); /* 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)); - } + ** remove it + */ + if (DoAssemble) { + /* Assemble the intermediate file and remove it */ + AssembleIntermediate (File); } - - /* Free the assembler file name which was allocated from the heap */ - xfree (AsmName); } /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -647,83 +745,128 @@ static void ConvertO65 (const char* File) 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-name seg\tSet the name of the BSS segment\n" - " --check-stack\t\tGenerate stack overflow checks\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-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" - " --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", - 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" + " -E\t\t\t\tStop after the preprocessing stage\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" + " --all-cdecl\t\t\tMake functions default to __cdecl__\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" + " --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" + " --no-std-lib\t\t\tDon't link standard runtime library\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" + " --print-target-path\t\tPrint the target file 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 OptAddSource (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Strict source code as comments to the generated asm code */ { CmdAddArg (&CC65, "-T"); } +static void OptAllCDecl (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Make functions default to __cdecl__ */ +{ + CmdAddArg (&CC65, "--all-cdecl"); +} + + + +static void OptAsmArgs (const char* Opt attribute ((unused)), const char* Arg) +/* Pass arguments to the assembler */ +{ + CmdAddArgList (&CA65, Arg); +} + + -static void OptAnsi (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) -/* Strict ANSI mode (compiler) */ +static void OptAsmDefine (const char* Opt attribute ((unused)), const char* Arg) +/* Define an assembler symbol (assembler) */ { - CmdAddArg (&CC65, "-A"); + CmdAddArg2 (&CA65, "-D", Arg); } @@ -731,8 +874,23 @@ static void OptAnsi (const char* Opt attribute ((unused)), static void OptAsmIncludeDir (const char* Opt attribute ((unused)), const char* Arg) /* Include directory (assembler) */ { - CmdAddArg (&CA65, "-I"); - CmdAddArg (&CA65, Arg); + CmdAddArg2 (&CA65, "-I", 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 */ +{ + CmdAddArg2 (&CO65, "--bss-label", Arg); } @@ -740,14 +898,30 @@ static void OptAsmIncludeDir (const char* Opt attribute ((unused)), const char* static void OptBssName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --bss-name option */ { - CmdAddArg (&CC65, "--bss-name"); - CmdAddArg (&CC65, Arg); + CmdAddArg2 (&CC65, "--bss-name", Arg); + CmdAddArg2 (&CO65, "--bss-name", Arg); +} + + + +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))) + const char* Arg attribute ((unused))) /* Handle the --check-stack option */ { CmdAddArg (&CC65, "--check-stack"); @@ -755,11 +929,19 @@ static void OptCheckStack (const char* Opt attribute ((unused)), +static void OptCodeLabel (const char* Opt attribute ((unused)), const char* Arg) +/* Handle the --code-label option */ +{ + CmdAddArg2 (&CO65, "--code-label", Arg); +} + + + static void OptCodeName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --code-name option */ { - CmdAddArg (&CC65, "--code-name"); - CmdAddArg (&CC65, Arg); + CmdAddArg2 (&CC65, "--code-name", Arg); + CmdAddArg2 (&CO65, "--code-name", Arg); } @@ -767,8 +949,18 @@ static void OptCodeName (const char* Opt attribute ((unused)), const char* Arg) static void OptCodeSize (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --codesize option */ { - CmdAddArg (&CC65, "--codesize"); - CmdAddArg (&CC65, Arg); + CmdAddArg2 (&CC65, "--codesize", Arg); +} + + + +static void OptConfig (const char* Opt attribute ((unused)), const char* Arg) +/* Config file (linker) */ +{ + if (LinkerConfig) { + Error ("Cannot specify -C/--config twice"); + } + LinkerConfig = Arg; } @@ -777,19 +969,40 @@ static void OptCPU (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --cpu option */ { /* Add the cpu type to the assembler and compiler */ - CmdAddArg (&CA65, "--cpu"); - CmdAddArg (&CA65, Arg); - CmdAddArg (&CC65, "--cpu"); - CmdAddArg (&CC65, Arg); + CmdAddArg2 (&CA65, "--cpu", Arg); + CmdAddArg2 (&CC65, "--cpu", Arg); } -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 OptDataLabel (const char* Opt attribute ((unused)), const char* Arg) +/* Handle the --data-label option */ +{ + CmdAddArg2 (&CO65, "--data-label", Arg); } @@ -797,28 +1010,30 @@ static void OptCreateDep (const char* Opt attribute ((unused)), static void OptDataName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --data-name option */ { - CmdAddArg (&CC65, "--data-name"); - CmdAddArg (&CC65, Arg); + CmdAddArg2 (&CC65, "--data-name", Arg); + CmdAddArg2 (&CO65, "--data-name", Arg); } static void OptDebug (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Debug mode (compiler and cl65 utility) */ { CmdAddArg (&CC65, "-d"); + CmdAddArg (&CO65, "-d"); Debug = 1; } static void OptDebugInfo (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Debug Info - add to compiler and assembler */ { CmdAddArg (&CC65, "-g"); CmdAddArg (&CA65, "-g"); + CmdAddArg (&CO65, "-g"); } @@ -826,14 +1041,21 @@ static void OptDebugInfo (const char* Opt attribute ((unused)), static void OptFeature (const char* Opt attribute ((unused)), const char* Arg) /* Emulation features for the assembler */ { - CmdAddArg (&CA65, "--feature"); - CmdAddArg (&CA65, Arg); + CmdAddArg2 (&CA65, "--feature", Arg); +} + + + +static void OptForceImport (const char* Opt attribute ((unused)), const char* Arg) +/* Emulation features for the assembler */ +{ + CmdAddArg2 (&LD65, "-u", Arg); } static void OptHelp (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Print help - cl65 */ { Usage (); @@ -845,17 +1067,64 @@ static void OptHelp (const char* Opt attribute ((unused)), static void OptIncludeDir (const char* Opt attribute ((unused)), const char* Arg) /* Include directory (compiler) */ { - CmdAddArg (&CC65, "-I"); - CmdAddArg (&CC65, Arg); + CmdAddArg2 (&CC65, "-I", Arg); } -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); } @@ -864,8 +1133,23 @@ static void OptMapFile (const char* Opt attribute ((unused)), const char* Arg) /* Create a map file */ { /* Create a map file (linker) */ - CmdAddArg (&LD65, "-m"); - CmdAddArg (&LD65, Arg); + CmdAddArg2 (&LD65, "-m", Arg); +} + + + +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); + } } @@ -883,8 +1167,67 @@ static void OptModuleId (const char* Opt attribute ((unused)), const char* Arg) /* Specify a module if for the linker */ { /* Pass it straight to the linker */ - CmdAddArg (&LD65, "--module-id"); - CmdAddArg (&LD65, Arg); + CmdAddArg2 (&LD65, "--module-id", Arg); +} + + + +static void OptNoStdLib (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Disable standard runtime library */ +{ + NoStdLib = 1; +} + + + +static void OptO65Model (const char* Opt attribute ((unused)), const char* Arg) +/* Handle the --o65-model option */ +{ + CmdAddArg2 (&CO65, "-m", Arg); +} + + + +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 OptPrintTargetPath (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Print the target file path */ +{ + char* TargetPath; + + SearchPaths* TargetPaths = NewSearchPath (); + AddSubSearchPathFromEnv (TargetPaths, "CC65_HOME", "target"); +#if defined(CL65_TGT) && !defined(_WIN32) + AddSearchPath (TargetPaths, STRINGIZE (CL65_TGT)); +#endif + AddSubSearchPathFromWinBin (TargetPaths, "target"); + + TargetPath = GetSearchPath (TargetPaths, 0); + while (*TargetPath) { + if (*TargetPath == ' ') { + /* Escape spaces */ + putchar ('\\'); + } + putchar (*TargetPath++); + } + putchar ('\n'); + exit (EXIT_SUCCESS); } @@ -892,8 +1235,7 @@ static void OptModuleId (const char* Opt attribute ((unused)), const char* Arg) static void OptRegisterSpace (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --register-space option */ { - CmdAddArg (&CC65, "--register-space"); - CmdAddArg (&CC65, Arg); + CmdAddArg2 (&CC65, "--register-space", Arg); } @@ -910,14 +1252,13 @@ static void OptRegisterVars (const char* Opt attribute ((unused)), static void OptRodataName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --rodata-name option */ { - CmdAddArg (&CC65, "--rodata-name"); - CmdAddArg (&CC65, Arg); + CmdAddArg2 (&CC65, "--rodata-name", Arg); } static void OptSignedChars (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Make default characters signed */ { CmdAddArg (&CC65, "-j"); @@ -925,17 +1266,24 @@ static void OptSignedChars (const char* Opt attribute ((unused)), +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 */ { - CmdAddArg (&LD65, "-S"); - CmdAddArg (&LD65, Arg); + CmdAddArg2 (&LD65, "-S", Arg); } static void OptStaticLocals (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Place local variables in static storage */ { CmdAddArg (&CC65, "-Cl"); @@ -957,23 +1305,39 @@ static void OptTarget (const char* Opt attribute ((unused)), const char* Arg) static void OptVerbose (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Verbose mode (compiler, assembler, linker) */ { CmdAddArg (&CC65, "-v"); CmdAddArg (&CA65, "-v"); + CmdAddArg (&CO65, "-v"); CmdAddArg (&LD65, "-v"); } static void OptVersion (const char* Opt attribute ((unused)), - const char* Arg attribute ((unused))) + const char* Arg attribute ((unused))) /* Print version number */ { - fprintf (stderr, - "cl65 V%u.%u.%u - (C) Copyright 1998-2003 Ullrich von Bassewitz\n", - VER_MAJOR, VER_MINOR, VER_PATCH); + fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); + exit(EXIT_SUCCESS); +} + + + +static void OptZeropageLabel (const char* Opt attribute ((unused)), const char* Arg) +/* Handle the --zeropage-label option */ +{ + CmdAddArg2 (&CO65, "--zeropage-label", Arg); +} + + + +static void OptZeropageName (const char* Opt attribute ((unused)), const char* Arg) +/* Handle the --zeropage-name option */ +{ + CmdAddArg2 (&CO65, "--zeropage-name", Arg); } @@ -983,47 +1347,89 @@ int main (int argc, char* argv []) { /* Program long options */ static const LongOpt OptTab[] = { - { "--add-source", 0, OptAddSource }, - { "--ansi", 0, OptAnsi }, - { "--asm-include-dir", 1, OptAsmIncludeDir }, - { "--bss-name", 1, OptBssName }, - { "--check-stack", 0, OptCheckStack }, - { "--code-name", 1, OptCodeName }, - { "--codesize", 1, OptCodeSize }, - { "--cpu", 1, OptCPU }, - { "--create-dep", 0, OptCreateDep }, - { "--data-name", 1, OptDataName }, - { "--debug", 0, OptDebug }, - { "--debug-info", 0, OptDebugInfo }, - { "--feature", 1, OptFeature }, - { "--help", 0, OptHelp }, - { "--include-dir", 1, OptIncludeDir }, - { "--listing", 0, OptListing }, - { "--mapfile", 1, OptMapFile }, - { "--module", 0, OptModule }, - { "--module-id", 1, OptModuleId }, - { "--register-space", 1, OptRegisterSpace }, - { "--register-vars", 0, OptRegisterVars }, - { "--rodata-name", 1, OptRodataName }, - { "--signed-chars", 0, OptSignedChars }, - { "--start-addr", 1, OptStartAddr }, - { "--static-locals", 0, OptStaticLocals }, - { "--target", 1, OptTarget }, - { "--verbose", 0, OptVerbose }, - { "--version", 0, OptVersion }, + { "--add-source", 0, OptAddSource }, + { "--all-cdecl", 0, OptAllCDecl }, + { "--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", 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 }, + { "--help", 0, OptHelp }, + { "--include-dir", 1, OptIncludeDir }, + { "--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 }, + { "--no-std-lib", 0, OptNoStdLib }, + { "--o65-model", 1, OptO65Model }, + { "--obj", 1, OptObj }, + { "--obj-path", 1, OptObjPath }, + { "--print-target-path", 0, OptPrintTargetPath}, + { "--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 }, + { "--verbose", 0, OptVerbose }, + { "--version", 0, OptVersion }, + { "--zeropage-label", 1, OptZeropageLabel }, + { "--zeropage-name", 1, OptZeropageName }, }; + char* CmdPath; unsigned I; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "cl65"); /* Initialize the command descriptors */ - CmdInit (&CC65, "cc65"); - CmdInit (&CA65, "ca65"); - CmdInit (&CO65, "co65"); - CmdInit (&LD65, "ld65"); - CmdInit (&GRC, "grc"); + if (argc == 0) { + CmdPath = xstrdup (""); + } else { + char* Ptr; + CmdPath = xstrdup (argv[0]); + Ptr = strrchr (CmdPath, '/'); + if (Ptr == 0) { + Ptr = strrchr (CmdPath, '\\'); + } + if (Ptr == 0) { + *CmdPath = '\0'; + } else { + *(Ptr + 1) = '\0'; + } + } + CmdInit (&CC65, CmdPath, "cc65"); + CmdInit (&CA65, CmdPath, "ca65"); + CmdInit (&CO65, CmdPath, "co65"); + CmdInit (&LD65, CmdPath, "ld65"); + CmdInit (&GRC, CmdPath, "grc65"); + xfree (CmdPath); /* Our default target is the C64 instead of "none" */ Target = TGT_C64; @@ -1032,208 +1438,219 @@ int main (int argc, char* argv []) I = 1; while (I < ArgCount) { - /* Get the argument */ - const char* Arg = ArgVec[I]; - - /* Check for an option */ - if (Arg [0] == '-') { - - switch (Arg [1]) { - - case '-': - 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); - } - break; - - case 'D': - /* Define a preprocessor symbol (compiler) */ - CmdAddArg (&CC65, "-D"); - CmdAddArg (&CC65, GetArg (&I, 2)); - break; - - case 'I': - /* Include directory (compiler) */ - OptIncludeDir (Arg, GetArg (&I, 2)); - break; - - case 'L': - if (Arg[2] == 'n') { - /* VICE label file (linker) */ - CmdAddArg (&LD65, "-Ln"); - CmdAddArg (&LD65, GetArg (&I, 3)); - } else { - UnknownOption (Arg); - } - break; - - case 'O': - /* Optimize code (compiler, also covers -Oi and others) */ - CmdAddArg (&CC65, Arg); - break; - - case 'S': - /* Dont assemble and link the created files */ - DontLink = DontAssemble = 1; - break; - - case 'T': - /* Include source as comment (compiler) */ - OptAddSource (Arg, 0); - break; - - case 'V': - /* Print version number */ - OptVersion (Arg, 0); - break; - - case 'W': - /* Suppress warnings - compiler and assembler */ - CmdAddArg (&CC65, "-W"); - CmdAddArg (&CA65, "-W"); - CmdAddArg (&CA65, "0"); - break; - - case 'c': - /* Don't link the resulting files */ - DontLink = 1; - break; - - case 'd': - /* Debug mode (compiler) */ - OptDebug (Arg, 0); - break; - - case 'g': - /* Debugging - add to compiler and assembler */ - OptDebugInfo (Arg, 0); - break; - - case 'h': - case '?': - /* Print help - cl65 */ - OptHelp (Arg, 0); - break; - - case 'j': - /* Default characters are signed */ - OptSignedChars (Arg, 0); - break; - - case 'l': - /* Create an assembler listing */ - OptListing (Arg, 0); - break; - - case 'm': - /* Create a map file (linker) */ - OptMapFile (Arg, GetArg (&I, 2)); - break; - - case 'o': - /* Name the output file */ - OutputName = GetArg (&I, 2); - break; - - case 'r': - /* Enable register variables */ - OptRegisterVars (Arg, 0); - break; - - case 't': - /* Set target system - compiler, assembler and linker */ - OptTarget (Arg, GetArg (&I, 2)); - break; - - case 'v': - if (Arg [2] == 'm') { - /* Verbose map file (linker) */ - CmdAddArg (&LD65, "-vm"); - } else { - /* Verbose mode (compiler, assembler, linker) */ - OptVerbose (Arg, 0); - } - break; - - default: - UnknownOption (Arg); - } - } else { - - /* Remember the first file name */ - if (FirstInput == 0) { - FirstInput = Arg; - } - - /* Determine the file type by the extension */ - switch (GetFileType (Arg)) { - - case FILETYPE_C: - /* Compile the file */ - Compile (Arg); - break; - - case FILETYPE_ASM: - /* Assemble the file */ - if (!DontAssemble) { - Assemble (Arg); - } - break; - - case FILETYPE_OBJ: - case FILETYPE_LIB: - /* Add to the linker files */ - CmdAddFile (&LD65, Arg); - break; - - case FILETYPE_GR: - /* Add to the resource compiler files */ - CompileRes (Arg); - break; + /* Get the argument */ + const char* Arg = ArgVec[I]; + + /* Check for an option */ + if (Arg [0] == '-') { + + switch (Arg [1]) { + + case '-': + LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); + break; + + case 'C': + if (Arg[2] == 'l' && Arg[3] == '\0') { + /* Make local variables static */ + OptStaticLocals (Arg, 0); + } else { + /* Specify linker config file */ + OptConfig (Arg, GetArg (&I, 2)); + } + break; + + case 'D': + /* Define a preprocessor symbol (compiler) */ + CmdAddArg2 (&CC65, "-D", GetArg (&I, 2)); + break; + + case 'I': + /* Include directory (compiler) */ + OptIncludeDir (Arg, GetArg (&I, 2)); + break; + + case 'L': + if (Arg[2] == 'n' && Arg[3] == '\0') { + /* VICE label file (linker) */ + CmdAddArg2 (&LD65, "-Ln", GetArg (&I, 3)); + } else { + /* Library search path (linker) */ + OptLibPath (Arg, GetArg (&I, 2)); + } + break; + + case 'O': + /* Optimize code (compiler, also covers -Oi and others) */ + CmdAddArg (&CC65, Arg); + break; + + case 'S': + /* Dont assemble and link the created files */ + DisableAssemblingAndLinking (); + break; + + case 'T': + /* Include source as comment (compiler) */ + OptAddSource (Arg, 0); + break; + + case 'V': + /* Print version number */ + OptVersion (Arg, 0); + break; + + case 'E': + /* Forward -E to compiler */ + CmdAddArg (&CC65, Arg); + DisableAssemblingAndLinking (); + 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 */ + /* Remember -Wc sub arguments in cc65 arg struct */ + 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 */ + DisableLinking (); + break; + + case 'd': + /* Debug mode (compiler) */ + OptDebug (Arg, 0); + break; + + case 'g': + /* Debugging - add to compiler and assembler */ + OptDebugInfo (Arg, 0); + break; + + case 'h': + case '?': + /* Print help - cl65 */ + OptHelp (Arg, 0); + break; + + case 'j': + /* Default characters are signed */ + OptSignedChars (Arg, 0); + break; + + case 'l': + /* Create an assembler listing */ + OptListing (Arg, GetArg (&I, 2)); + break; + + case 'm': + /* Create a map file (linker) */ + OptMapFile (Arg, GetArg (&I, 2)); + break; + + case 'o': + /* Name the output file */ + OutputName = GetArg (&I, 2); + break; + + case 'r': + /* Enable register variables */ + OptRegisterVars (Arg, 0); + break; + + case 't': + /* Set target system - compiler, assembler and linker */ + 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) */ + CmdAddArg (&LD65, "-vm"); + } else { + /* Verbose mode (compiler, assembler, linker) */ + OptVerbose (Arg, 0); + } + break; + + default: + UnknownOption (Arg); + } + } else { + + /* Remember the first file name */ + if (FirstInput == 0) { + FirstInput = Arg; + } + + /* Determine the file type by the extension */ + switch (GetFileType (Arg)) { + + case FILETYPE_C: + /* Compile the file */ + Compile (Arg); + break; + + case FILETYPE_ASM: + /* Assemble the file */ + if (DoAssemble) { + Assemble (Arg); + } + break; + + case FILETYPE_OBJ: + case FILETYPE_LIB: + /* Add to the linker files */ + CmdAddFile (&LD65, Arg); + break; + + case FILETYPE_GR: + /* Add to the resource compiler files */ + CompileRes (Arg); + break; case FILETYPE_O65: /* Add the the object file converter files */ ConvertO65 (Arg); break; - default: - Error ("Don't know what to do with `%s'", Arg); + default: + Error ("Don't know what to do with `%s'", Arg); - } + } - } + } - /* Next argument */ - ++I; + /* Next argument */ + ++I; } /* Check if we had any input files */ if (FirstInput == 0) { - Warning ("No input files"); + Warning ("No input files"); } /* Link the given files if requested and if we have any */ - if (DontLink == 0 && LD65.FileCount > 0) { - Link (); + if (DoLink && LD65.FileCount > 0) { + Link (); } /* Return an apropriate exit code */ return EXIT_SUCCESS; } - - - -