public bool ProcessArguments(string[] args) { try { DisableTracker(); CommandLine = args; for (int i = 0; i < args.Length; i++) { var opt = getOption(args[i]); var full = getFullOption(args[i]); onlyOptions.Add(full); #region switch process each argument type switch (opt) { case "/c": HasDashC = true; break; case "/o": return(NotSupported("/o")); case "/D": if (opt == full) { // define value is next argument... i++; onlyOptions.Add(args[i]); } break; case "/I": if (opt == full) { // include path is next argument.. // microsoft really dont know how to do command line! i++; if (i > args.Length) { return(NotSupported("-I has no path!")); } full = "/I" + args[i]; onlyOptions.Add(args[i]); goto default; } break; case "/Z7": GeneratePdb = false; PdbFile = null; break; case "/Yu": PrecompiledHeaders = true; return(NotSupported("pre-compiler headers {0}", opt)); case "/FI": return(NotSupported(opt)); case "/Zi": GeneratePdb = true; break; case "/Fd": PdbFile = Path.Combine(WorkingDirectory, full.Substring(3)); // openssl gives us a posix path here.. PdbFile = PdbFile.Replace('/', '\\'); if (!PdbFile.ToLower().EndsWith(".pdb") && !PdbFile.EndsWith("\\")) { PdbFile = PdbFile + ".pdb"; } break; case "/Fo": ObjectTarget = Path.Combine(WorkingDirectory, full.Substring(3)); if (ArgumentUtils.TargetIsFolder(ObjectTarget)) { ObjectTargetIsFolder = true; } else { ObjectTarget = ArgumentUtils.TargetObject(ObjectTarget); } break; case "/Tp": case "/Tc": var srcfile = ArgumentUtils.MakeWindowsPath(full.Substring(3)); if (!Path.IsPathRooted(srcfile)) { srcfile = Path.Combine(WorkingDirectory, srcfile); } if (FileUtils.Exists(srcfile)) { srcs.Add(srcfile); // remove last added option onlyOptions.RemoveAt(onlyOptions.Count - 1); srcsOptions.Add(full); } else { return(NotSupported("cant find file for {0}", full)); } break; case "/E": return(NotSupported(opt)); case "/EP": return(NotSupported(opt)); case "/MP": var numOfCompilersStr = full.Substring(3); if (string.IsNullOrEmpty(numOfCompilersStr)) { ParallelCompilers = Environment.ProcessorCount; } else { int parallel; if (int.TryParse(numOfCompilersStr, out parallel)) { ParallelCompilers = parallel; } else { ParallelCompilers = Environment.ProcessorCount; } } break; default: #region positional or other flag options if (full == "/link") { Linking = true; return(NotSupported("/link")); } if (opt.StartsWith("@")) { // remove last added option onlyOptions.RemoveAt(onlyOptions.Count - 1); #region response file ResponseFile = ArgumentUtils.MakeWindowsPath(full.Substring(1)); if (ResponseFile.EndsWith(InternalResponseFileSuffix)) { Logging.Emit("cclash misshelper internal response file"); return(false); } if (!Path.IsPathRooted(ResponseFile)) { ResponseFile = Path.Combine(WorkingDirectory, ResponseFile); } string rsptxt = File.ReadAllText(ResponseFile); if (rsptxt.Length < 2047) // windows max command line, this is why they invented response files { Logging.Emit("response data [{0}]", rsptxt); if (args.Length == 1) { // this only works if it is the one and only arg! args = ArgumentUtils.FixupArgs(CommandLineToArgs(rsptxt).Skip(1)).ToArray(); i = -1; // replace the command line with the response file content // and restart parsing. This does go wrong if the response text is huge continue; } } else { Logging.Emit("response file too large"); } return(NotSupported("response file error")); #endregion } if (!full.StartsWith("/")) { // NOTE, if we ever cache -link calls this will also match input objects and libs var file = ArgumentUtils.MakeWindowsPath(full); if (!Path.IsPathRooted(file)) { file = Path.Combine(WorkingDirectory, file); } if (FileUtils.Exists(file)) { srcs.Add(file); // remove last added option onlyOptions.RemoveAt(onlyOptions.Count - 1); srcsOptions.Add(full); continue; } } if (full.StartsWith("/I")) { var d = ArgumentUtils.MakeWindowsPath(full.Substring(2)); if (d == ".") { d = WorkingDirectory; } if (d == "..") { d = Path.GetDirectoryName(WorkingDirectory); } if (!Path.IsPathRooted(d)) { d = Path.Combine(WorkingDirectory, d); } if (Directory.Exists(d)) { cliincs.Add(d); continue; } } #endregion break; } #endregion } if (SingleSource) { var defaultObj = ArgumentUtils.TargetObject(Path.GetFileNameWithoutExtension(SingleSourceFile)); if (ObjectTarget == null) { if (Path.IsPathRooted(defaultObj)) { ObjectTarget = defaultObj; } else { ObjectTarget = Path.Combine(WorkingDirectory, defaultObj); } } if (ObjectTargetIsFolder) { ObjectTarget = Path.Combine(ObjectTarget, defaultObj); } if (GeneratePdb) { if (Settings.ConvertObjPdbToZ7) { Logging.Emit("converting pdb request to Z7 embedded debug {0}:{1}", WorkingDirectory, Path.GetFileName(ObjectTarget)); // append /Z7 to the arg list and don't generate a pdb var newargs = new List <string>(); foreach (var a in args) { if (!(a.StartsWith("/Zi") || a.StartsWith("/Fd"))) { newargs.Add(a); } } newargs.Add("/Z7"); AttemptPdb = false; PdbFile = null; GeneratePdb = false; PdbExistsAlready = false; args = newargs.ToArray(); } } if (GeneratePdb) { return(NotSupported("PDB file requested")); } } } catch (Exception e) { Console.Error.WriteLine(e); return(NotSupported("option parser exception '{0}'", e)); } CompileArgs = args.ToArray(); return(IsSupported); }
string getFullOption(string arg) { arg = arg.Trim('"', '\''); return(ArgumentUtils.CanonicalArgument(arg)); }