#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; }