mirror of https://git.wuffs.org/MWCC
242 lines
7.9 KiB
C
242 lines
7.9 KiB
C
#include "cmdline.h"
|
|
|
|
extern char STSbuf[256];
|
|
extern PCmdLine pCmdLine;
|
|
|
|
void AppendArgumentList(int *argc, char ***argv, const char *str) {
|
|
*argv = xrealloc("command-line arguments", *argv, sizeof(char *) * (*argc + 2));
|
|
(*argv)[(*argc)++] = xstrdup(str);
|
|
}
|
|
|
|
static int CopyArgumentList(int argc, char **argv, int *Argc, char ***Argv) {
|
|
int x;
|
|
int y;
|
|
|
|
y = Argc ? *Argc : 0;
|
|
*Argv = xrealloc("command-line arguments", *Argv, sizeof(char *) * (y + argc + 1));
|
|
|
|
if (argv) {
|
|
for (x = 0; x < argc; x++) {
|
|
(*Argv)[y++] = xstrdup(argv[x]);
|
|
}
|
|
}
|
|
(*Argv)[y] = NULL;
|
|
if (Argc)
|
|
*Argc = y;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int FreeArgumentList(char **argv) {
|
|
char **scan;
|
|
for (scan = argv; *scan; scan++)
|
|
xfree(*scan);
|
|
xfree(argv);
|
|
return 1;
|
|
}
|
|
|
|
static int SetupLinkerCommandLine(SInt32 dropinflags, File *file, CWCommandLineArgs *args) {
|
|
CWCommandLineArgs *baseargs;
|
|
int x;
|
|
SInt32 idx;
|
|
OSSpec spec;
|
|
|
|
for (x = 0; x < numPlugins; x++) {
|
|
if (pluginInfo[x].plugintype == CWDROPINLINKERTYPE && ((dropinflags & (isPostLinker | isPreLinker)) == (pluginInfo[x].dropinflags & (isPostLinker | isPreLinker))))
|
|
break;
|
|
}
|
|
|
|
OS_ASSERT(89, x < numPlugins);
|
|
|
|
args->argc = 1;
|
|
args->argv = xmalloc("command-line arguments", 2 * sizeof(char *));
|
|
Main_PassSpecialArgs(&args->argc, &args->argv);
|
|
|
|
baseargs = &plugin_args[x];
|
|
CopyArgumentList(baseargs->argc - 1, baseargs->argv + 1, &args->argc, &args->argv);
|
|
|
|
x = 0;
|
|
if (baseargs->envp) {
|
|
while (baseargs->envp[x])
|
|
x++;
|
|
}
|
|
args->envp = NULL;
|
|
CopyArgumentList(x, baseargs->envp, NULL, &args->envp);
|
|
|
|
if (!file && !(dropinflags & isPostLinker)) {
|
|
for (idx = 0; idx < Files_Count(&gTarg->files); idx++) {
|
|
file = Files_GetFile(&gTarg->files, idx);
|
|
if (file->sourceUsage & CmdLineStageMask_Cg) {
|
|
AppendArgumentList(&args->argc, &args->argv, file->srcfilename);
|
|
}
|
|
if (file->objectUsage & CmdLineStageMask_Cg) {
|
|
if (GetOutputFile(file, CmdLineStageMask_Cg) != 0 && StoreObjectFile(file))
|
|
AppendArgumentList(&args->argc, &args->argv, OS_SpecToString(&file->outfss, STSbuf, sizeof(STSbuf)));
|
|
else
|
|
return 0;
|
|
}
|
|
}
|
|
} else if (file) {
|
|
args->argv = xrealloc("command-line arguments", args->argv, sizeof(char *) * (args->argc + 1));
|
|
if (file->sourceUsage & CmdLineStageMask_Cg) {
|
|
AppendArgumentList(&args->argc, &args->argv, file->srcfilename);
|
|
}
|
|
if (file->objectUsage & CmdLineStageMask_Cg) {
|
|
if (GetOutputFile(file, CmdLineStageMask_Cg) != 0 && StoreObjectFile(file)) {
|
|
AppendArgumentList(&args->argc, &args->argv, OS_SpecToString(&file->outfss, STSbuf, sizeof(STSbuf)));
|
|
}
|
|
}
|
|
if ((pCmdLine.toDisk & CmdLineStageMask_Ds) && (file->objectUsage & CmdLineStageMask_Pp) && file->outfilename[0] && GetOutputFile(file, CmdLineStageMask_Ds)) {
|
|
AppendArgumentList(&args->argc, &args->argv, "-o");
|
|
AppendArgumentList(&args->argc, &args->argv, OS_SpecToString(&file->outfss, STSbuf, sizeof(STSbuf)));
|
|
}
|
|
} else if (dropinflags & isPostLinker) {
|
|
OS_FSSpec_To_OSSpec(&gTarg->targetinfo->outfile, &spec);
|
|
AppendArgumentList(&args->argc, &args->argv, OS_SpecToString(&spec, STSbuf, sizeof(STSbuf)));
|
|
}
|
|
|
|
args->argv[args->argc] = NULL;
|
|
return 1;
|
|
}
|
|
|
|
int SetupTemporaries(void) {
|
|
SInt32 idx;
|
|
File *file;
|
|
|
|
for (idx = 0; idx < Files_Count(&gTarg->files); idx++) {
|
|
file = Files_GetFile(&gTarg->files, idx);
|
|
if ((file->objectUsage & CmdLineStageMask_Cg) && !(optsCmdLine.toDisk & CmdLineStageMask_Cg) && !(file->writeToDisk & CmdLineStageMask_Cg)) {
|
|
if (!optsCompiler.keepObjects)
|
|
file->tempOnDisk |= CmdLineStageMask_Cg;
|
|
else
|
|
file->writeToDisk |= CmdLineStageMask_Cg;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int DeleteTemporaries(void) {
|
|
SInt32 idx;
|
|
File *file;
|
|
|
|
for (idx = 0; idx < Files_Count(&gTarg->files); idx++) {
|
|
file = Files_GetFile(&gTarg->files, idx);
|
|
if ((file->objectUsage & CmdLineStageMask_Cg) && (file->tempOnDisk & CmdLineStageMask_Cg) && (file->wroteToDisk & CmdLineStageMask_Cg)) {
|
|
GetOutputFile(file, CmdLineStageMask_Cg);
|
|
if (optsCmdLine.verbose > 1)
|
|
CLReport(CLStr19, OS_SpecToString(&file->outfss, STSbuf, sizeof(STSbuf)));
|
|
OS_Delete(&file->outfss);
|
|
file->tempOnDisk &= ~CmdLineStageMask_Cg;
|
|
file->wroteToDisk &= ~CmdLineStageMask_Cg;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ExecuteLinker(Plugin *plugin, SInt32 dropinflags, File *file, char *stdoutfile, char *stderrfile) {
|
|
char cname[64];
|
|
const char *linkername;
|
|
OSSpec linkerspec;
|
|
CWCommandLineArgs args;
|
|
int exitcode;
|
|
int execerr;
|
|
const char *linkertype;
|
|
int ret;
|
|
char *ptr;
|
|
char *ptr2;
|
|
int x;
|
|
|
|
// TODO rename this flag to isExecutableTool
|
|
OS_ASSERT(269, dropinflags & dropInExecutableTool);
|
|
|
|
args.argc = 0;
|
|
args.argv = args.envp = NULL;
|
|
|
|
if (dropinflags & isPreLinker)
|
|
linkertype = "pre-linker";
|
|
else if (dropinflags & isPostLinker)
|
|
linkertype = "post-linker";
|
|
else
|
|
linkertype = "linker";
|
|
|
|
linkername = Plugin_GetDropInName(plugin);
|
|
if (!(dropinflags & (isPreLinker | isPostLinker)) && optsCompiler.linkerName[0])
|
|
linkername = optsCompiler.linkerName;
|
|
|
|
if (OS_FindProgram(linkername, &linkerspec)) {
|
|
strcpy(cname, clState.programName);
|
|
|
|
for (ptr = cname; *ptr; ptr++)
|
|
*ptr = tolower(*ptr);
|
|
|
|
if ((ptr = strstr(cname, "cc")) || (ptr = strstr(cname, "pas")) || (ptr = strstr(cname, "asm"))) {
|
|
if (ptr[0] != 'c') {
|
|
memmove(ptr + 2, ptr + 3, strlen(ptr) - 3);
|
|
ptr[strlen(ptr) - 1] = 0;
|
|
}
|
|
ptr[0] = 'l';
|
|
ptr[1] = 'd';
|
|
} else {
|
|
if ((ptr = strstr(cname, "mwc"))) {
|
|
// this ptr2 seems redundant, but it's needed to generate the same code
|
|
ptr2 = ptr + 2;
|
|
memmove(ptr2 + 3, ptr2, strlen(ptr2));
|
|
memcpy(ptr + 2, "Link", 4);
|
|
}
|
|
}
|
|
|
|
if (!OS_FindProgram(cname, &linkerspec)) {
|
|
ptr = cname;
|
|
if (optsCompiler.linkerName[0]) {
|
|
CLReportWarning(CLStr66, linkertype, optsCompiler.linkerName);
|
|
CLReport(CLStr65, ptr, clState.programName);
|
|
} else if (optsCmdLine.verbose) {
|
|
CLReport(CLStr65, ptr, clState.programName);
|
|
}
|
|
} else {
|
|
CLReportError(CLStr66, linkertype, linkername);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
ret = 1;
|
|
SetupLinkerCommandLine(dropinflags, file, &args);
|
|
args.argv[0] = xstrdup(OS_SpecToString(&linkerspec, STSbuf, sizeof(STSbuf)));
|
|
args.argv[args.argc] = 0;
|
|
|
|
if (optsCmdLine.verbose || optsCmdLine.dryRun) {
|
|
CLPrint("\nCommand line:\n");
|
|
for (x = 0; x < args.argc && args.argv[x]; x++) {
|
|
if (strchr(args.argv[x], ' '))
|
|
CLPrint("\"%s\" ", args.argv[x]);
|
|
else
|
|
CLPrint("%s ", args.argv[x]);
|
|
}
|
|
CLPrint("\n\n");
|
|
}
|
|
|
|
fflush(stdout);
|
|
fflush(stderr);
|
|
|
|
if (optsCmdLine.verbose)
|
|
CLReport(CLStr67, linkertype, OS_SpecToString(&linkerspec, STSbuf, sizeof(STSbuf)));
|
|
|
|
if (!optsCmdLine.dryRun) {
|
|
execerr = OS_Execute(&linkerspec, args.argv, args.envp, stdoutfile, stderrfile, &exitcode);
|
|
if (execerr) {
|
|
CLReportError(CLStr68, linkertype, args.argv[0], OS_GetErrText(execerr));
|
|
ret = 0;
|
|
} else if (exitcode) {
|
|
CLReportError(CLStr69, linkertype, args.argv[0], exitcode);
|
|
ret = 0;
|
|
}
|
|
}
|
|
|
|
FreeArgumentList(args.argv);
|
|
FreeArgumentList(args.envp);
|
|
|
|
return ret;
|
|
}
|