diff --git a/src/cl65/main.c b/src/cl65/main.c index 31d805181..42126e6d7 100644 --- a/src/cl65/main.c +++ b/src/cl65/main.c @@ -378,6 +378,14 @@ static void CmdSetOutput (CmdDesc* Cmd, const char* File) +static void CmdSetAsmOutput (CmdDesc* Cmd, const char* File) +/* Set the output asm file in a command desc for grc65 */ +{ + CmdAddArg2 (Cmd, "-s", File); +} + + + static void CmdSetTarget (CmdDesc* Cmd, target_t Target) /* Set the output file in a command desc */ { @@ -526,12 +534,15 @@ static void Link (void) -static void AssembleFile (const char* File, unsigned ArgCount) +static void AssembleFile (const char* File, const char* TmpFile, 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. */ { + /* ObjName may be used for temporary or real filename */ + char *ObjName; + /* Set the target system */ CmdSetTarget (&CA65, Target); @@ -541,7 +552,12 @@ static void AssembleFile (const char* File, unsigned ArgCount) ** to 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"); + if (TmpFile) { + ObjName = MakeFilename (TmpFile, ".o"); + } else { + ObjName = MakeTmpFilename (".o"); + } + CmdSetOutput (&CA65, ObjName); CmdAddFile (&LD65, ObjName); /* This is just a temporary file, schedule it for removal */ CmdAddFile (&RM, ObjName); @@ -550,11 +566,15 @@ static void AssembleFile (const char* File, unsigned ArgCount) /* This is the final step. If an output name is given, set it */ if (OutputName) { CmdSetOutput (&CA65, OutputName); + } else { + ObjName = MakeFilename (File, ".o"); + CmdSetOutput (&CA65, ObjName); + xfree (ObjName); } } /* Add the file as argument for the assembler */ - CmdAddArg (&CA65, File); + CmdAddArg (&CA65, TmpFile ? TmpFile : File); /* Add a NULL pointer to terminate the argument list */ CmdAddArg (&CA65, 0); @@ -568,7 +588,7 @@ static void AssembleFile (const char* File, unsigned ArgCount) -static void AssembleIntermediate (const char* SourceFile) +static void AssembleIntermediate (const char* SourceFile, const char* TmpFile) /* 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. @@ -578,18 +598,20 @@ static void AssembleIntermediate (const char* SourceFile) ** name. It's the same name with the extension replaced by ".s" */ char* AsmName = MakeFilename (SourceFile, ".s"); + char* AsmTmpName = TmpFile ? MakeFilename(TmpFile, ".s") : NULL; /* Assemble the intermediate assembler file */ - AssembleFile (AsmName, CA65.ArgCount); + AssembleFile (AsmName, AsmTmpName, CA65.ArgCount); /* Remove the input file */ - if (remove (AsmName) < 0) { + if (remove (AsmTmpName ? AsmTmpName : AsmName) < 0) { Warning ("Cannot remove temporary file '%s': %s", - AsmName, strerror (errno)); + AsmTmpName ? AsmTmpName : AsmName, strerror (errno)); } /* Free the assembler file name which was allocated from the heap */ xfree (AsmName); + xfree (AsmTmpName); } @@ -612,7 +634,7 @@ static void Assemble (const char* File) } /* Use the common routine */ - AssembleFile (File, ArgCount); + AssembleFile (File, NULL, ArgCount); } @@ -620,6 +642,9 @@ static void Assemble (const char* File) static void Compile (const char* File) /* Compile the given file */ { + /* A temporary file name passed to the assembler */ + char *TmpFile = NULL; + /* Remember the current compiler argument count */ unsigned ArgCount = CC65.ArgCount; @@ -657,6 +682,12 @@ static void Compile (const char* File) /* Add the file as argument for the compiler */ CmdAddArg (&CC65, File); + if (DoAssemble) { + /* set a temporary output file name */ + TmpFile = MakeTmpFilename(".s"); + CmdSetOutput (&CC65, TmpFile); + } + /* Add a NULL pointer to terminate the argument list */ CmdAddArg (&CC65, 0); @@ -671,7 +702,10 @@ static void Compile (const char* File) */ if (DoAssemble) { /* Assemble the intermediate file and remove it */ - AssembleIntermediate (File); + AssembleIntermediate (File, TmpFile); + if (TmpFile) { + xfree(TmpFile); + } } } @@ -680,6 +714,9 @@ static void Compile (const char* File) static void CompileRes (const char* File) /* Compile the given geos resource file */ { + /* tmp Asm file name, if needed */ + char* AsmName = NULL; + /* Remember the current assembler argument count */ unsigned ArgCount = GRC.ArgCount; @@ -688,6 +725,14 @@ static void CompileRes (const char* File) */ CmdSetTarget (&GRC, Target); + /* Changes to output file name must come + ** BEFORE adding the file + */ + if (DoAssemble && DoLink) { + AsmName = MakeTmpFilename(".s"); + CmdSetAsmOutput(&GRC, AsmName); + } + /* Add the file as argument for the resource compiler */ CmdAddArg (&GRC, File); @@ -705,7 +750,10 @@ static void CompileRes (const char* File) */ if (DoAssemble) { /* Assemble the intermediate file and remove it */ - AssembleIntermediate (File); + AssembleIntermediate (File, AsmName); + if (AsmName) { + xfree(AsmName); + } } } @@ -741,7 +789,7 @@ static void ConvertO65 (const char* File) */ if (DoAssemble) { /* Assemble the intermediate file and remove it */ - AssembleIntermediate (File); + AssembleIntermediate (File, NULL); } } diff --git a/src/common/fname.c b/src/common/fname.c index 4e4f7c7fa..e67470b33 100644 --- a/src/common/fname.c +++ b/src/common/fname.c @@ -33,6 +33,7 @@ +#include #include #include "xmalloc.h" @@ -115,3 +116,38 @@ char* MakeFilename (const char* Origin, const char* Ext) } return Out; } + + + +char* MakeTmpFilename (const char* Ext) +/* Make a new temporary file name from Ext. tmpnam(3) is called +** and Ext is appended to generate the filename. +** The result is placed in a malloc'ed buffer and returned. +*/ +{ + char* Out; + char Buffer[L_tmpnam * 2]; /* a lazy way to ensure we have space for Ext */ + + /* + ** gcc emits the following warning here: + ** + ** warning: the use of `tmpnam' is dangerous, better use `mkstemp' + ** + ** however, mkstemp actually opens a file, which we do not want. + ** tmpfile() is unsuitable for the same reason. + ** + ** we could write our own version, but then we would have to struggle + ** with supporting multiple build environments. + ** + ** tmpnam(3) is safe here, because ca65 / cc65 / ld65 will simply clobber + ** an existing file, or exit if with an error if they are unable to. + ** + ** gcc will also complain, if you don't use the return value from tmpnam(3) + */ + strcat(tmpnam(Buffer), Ext); + + Out = xmalloc (strlen (Buffer) + 1); + strcpy (Out, Buffer); + + return Out; +} diff --git a/src/common/fname.h b/src/common/fname.h index 1b94d270c..852c4ae56 100644 --- a/src/common/fname.h +++ b/src/common/fname.h @@ -59,6 +59,12 @@ char* MakeFilename (const char* Origin, const char* Ext); ** The function may be used to create "foo.o" from "foo.s". */ +char* MakeTmpFilename (const char* Ext); +/* Make a new temporary file name from Ext. tmpnam(3) is called +** and Ext is appended to generate the filename. +** The result is placed in a malloc'ed buffer and returned. +*/ + /* End of fname.h */