/** * Given the original argv stuff, the length of our target executable, and the * filepath, build a suitable command line for CreateProcess. */ STATIC LPTSTR BuildCmdLine(int argc, TCHAR* argv[], SIZE_T szExecutable, LPTSTR lpExecutable) { int i = 1; LPTSTR lpCmdLine = NULL; SIZE_T szCmdLine = szExecutable; TCHAR** lpNewArgs = (TCHAR**)calloc(argc, sizeof(TCHAR*)); assert(lpNewArgs != NULL); // Quote the executable path if need be. XINFO(_T("Building command line..")); if(HasSpace(lpExecutable, szExecutable)) { lpNewArgs[0] = Quote(lpExecutable, &szCmdLine, FALSE); } else { lpNewArgs[0] = DupArg(lpExecutable, &szCmdLine, FALSE); } // Iterate through all args, quoting as necessary. for(; i < argc; i++) { SIZE_T szArg = (SIZE_T)_tcslen((const TCHAR*)argv[i]); if(HasSpace(argv[i], szArg)) { lpNewArgs[i] = Quote(argv[i], &szArg, TRUE); } else { lpNewArgs[i] = DupArg(argv[i], &szArg, TRUE); } // +1 for space + len(arg) szCmdLine += szArg; } // Allocate our cmdline buffer and begin adding the various parts. lpCmdLine = (LPTSTR)calloc(szCmdLine + 1, sizeof(TCHAR)); assert(lpCmdLine != NULL); _tcscpy(lpCmdLine, lpNewArgs[0]); XINFO(_T(" [0] => \"%s\""), lpNewArgs[0]); // Cleanup allocated arg. xfree(lpNewArgs[0]); lpNewArgs[0] = NULL; for(i = 1; i < argc; i++) { XINFO(_T(" [%d] => \"%s\""), i, argv[i]); _tcscat(lpCmdLine, lpNewArgs[i]); xfree(lpNewArgs[i]); lpNewArgs[i] = NULL; } XINFO(_T("Finished building..")); XINFO(_T("CmdLine: %s"), lpCmdLine); xfree(lpNewArgs); return lpCmdLine; }
char *ParseCompFlags(int nargs, char **args, int *BITS, ATL_arg_t **files, ATL_arg_t **CMP, ATL_arg_t **ASM, ATL_arg_t **LNK, int *CPPONLY) { int i, nfiles=0, DOASM=1, DOLNK=1; ATL_arg_t *cmpb, *cp, *asmb, *ap, *lnkb, *lp, *filb, *fp, *an; char *outn=NULL; *CPPONLY = 0; /* * Go through compiler flags and separate them into flags affecting * compilation, assembling, and linking */ cmpb = cp = NewArg(MYGCC); asmb = ap = NewArg(MYASM); lnkb = lp = NewArg(MYLNK); filb = NULL; for (i=1; i < nargs; i++) { ATL_arg_t *at; at = NewArg(args[i]); if (at->arg[0] == '-') /* flag */ { switch (at->arg[1]) { case 'o' : /* -o : found name of output file */ /* * If this is just -o, then actual name is given in the next arg */ if (at->len == 2) { assert(++i < nargs); outn = args[i]; } /* * is of form -o<name> */ else outn = args[i]+2; break; case 'L' : /* -L/l args go only to linker */ case 'l' : if (at->len == 2) { assert(++i < nargs); lp->next = at; lp = at->next = NewArg(args[i]); } else { lp->next = at; lp = at; } break; case 'x' : /* I only use -x asg-with-cpp, so pass to comp only */ *CPPONLY = 1; cp->next = at; assert(++i < nargs); assert(!strcmp(args[i], "assembler-with-cpp")); cp = at->next = NewArg(args[i]); break; case 'c' : DOLNK = 0; break; case 'S' : DOASM = DOLNK = 0; break; case 'E': case 'X': case 'T': case 'u': fprintf(stderr, "FLAG '-%c' NOT HANDLED, DYING\n", at->arg[1]); assert(0); /* not implemented at moment */ case 'W': /* possible linker/assembler pass-thru */ if (at->len > 3) { if (at->arg[2] == 'a' && at->arg[3] == ',') /* asm pass-thru */ { ap->next = at; ap = at; } else if (at->arg[2] == 'l' && at->arg[3] == ',') /* lnk pass */ { lp->next = at; lp = at; } } /* else fall-thru to default */ default: /* everything else assumed to be a compiler-only flag */ /* * In default, compare against all known linker options */ if ( (at->len == 13 && !strcmp(at->arg, "-nostartfiles")) || (at->len == 14 && !strcmp(at->arg, "-nodefaultlibs")) || (at->len == 9 && !strcmp(at->arg, "-nostdlib")) || (at->len == 4 && !strcmp(at->arg, "-pie")) || (at->len == 9 && !strcmp(at->arg, "-rdynamic")) || (at->len == 2 && at->arg[1] == 's') || (at->len == 7 && !strcmp(at->arg, "-static")) || (at->len == 14 && !strcmp(at->arg, "-static-libgcc")) || (at->len == 9 && !strcmp(at->arg, "-symbolic")) ) { lp->next = at; lp = at; } else if (at->len == 8 && !strcmp(at->arg, "-Xlinker")) { assert(++i < nargs); lp->next = at; lp = at->next = NewArg(args[i]); } else if (at->len == 11 && !strcmp(at->arg, "-Xassembler")) { assert(++i < nargs); ap->next = at; ap = at->next = NewArg(args[i]); } /* * -m64/32 args get passed to comp, asm & linker */ else if (at->len == 4 && (!strcmp(at->arg, "-m64") || !strcmp(at->arg, "-mx32") || !strcmp(at->arg, "-m32"))) { if (at->arg[2] == '6') *BITS = 64; else *BITS = 32; lp->next = DupArg(at); lp = lp->next; ap->next = DupArg(at); ap = ap->next; cp->next = at; cp = at; } else if (at->len == 9 && !strcmp(at->arg, "--version")) { char *sp; int i; i = strlen(MYGCC); sp = malloc(i + 12); strcpy(sp, MYGCC); strcpy(sp+i, " --version"); system(sp); free(sp); #ifdef DEBUG fclose(fplog); #endif exit(0); /* ugly uncleaned-up exit; live with it */ } else { cp->next = at; cp = at; } } } else /* anything not beginning with - must be a filename */ { char ch; int F90=0; int len = at->len; assert(len > 2); ch = at->arg[len-1]; nfiles++; if (at->arg[len-2] == '.') /* .f or .F */ assert(ch == 'f' || ch == 'F' || ch == 'o' || ch == 'a'); else /* .f90 */ { F90 = 1; ch = at->arg[len-3]; assert(len > 4) assert(at->arg[len-4] == '.' && (ch == 'f' || ch == 'F') || (at->arg[len-2] == '9')); } /* * If it isn't already an object file, add it to list of files to be * renamed during compilation */ if (ch != 'o' && ch != 'a') { if (!filb) filb = fp = at; else { fp->next = at; fp = at; } /* * Put empty node in linker options to indicate where to put in the * generated file names */ lp->next = NewArg(NULL); lp = lp->next; } /* * If it is a object/archive file, just add it to link line and forget it */ else { lp->next = NewArg(at->arg); lp = lp->next; } /* * If the file is already an object file, add it to linker */ } } if (outn) /* must use particular output name */ { ATL_arg_t *tp; tp = (DOLNK) ? lp : ap; tp->next = NewArg("-o"); tp->next->next = NewArg(outn); tp = tp->next->next; } if (outn && !DOLNK) assert(nfiles == 1); else assert(nfiles > 0); /* * If there are no files in filb, that means nothing need be compiled, so * the only thing we are doing is linking */ if (!filb) { assert(DOLNK); if (cmpb) KillAllArgs(cmpb); if (asmb) KillAllArgs(asmb); *CMP = NULL; *ASM = NULL; } else { *CMP = cmpb; if (DOASM) *ASM = asmb; else { *ASM = NULL; KillAllArgs(asmb); } } if (DOLNK) *LNK = lnkb; else { *LNK = NULL; KillAllArgs(lnkb); } *files = filb; return(outn); }