internal void FlattenArgs( IEnumerable <string> rawArguments, IList <Diagnostic> diagnostics, List <string> processedArgs, List <string> scriptArgsOpt, string baseDirectory, List <string> responsePaths = null) { bool parsingScriptArgs = false; bool sourceFileSeen = false; bool optionsEnded = false; var args = new Stack <string>(rawArguments.Reverse()); while (args.Count > 0) { // EDMAURER trim off whitespace. Otherwise behavioral differences arise // when the strings which represent args are constructed by cmd or users. // cmd won't produce args with whitespace at the end. string arg = args.Pop().TrimEnd(); if (parsingScriptArgs) { scriptArgsOpt.Add(arg); continue; } if (scriptArgsOpt != null) { // The order of the following two checks matters. // // Command line: Script: Script args: // csi -- script.csx a b c script.csx ["a", "b", "c"] // csi script.csx -- a b c script.csx ["--", "a", "b", "c"] // csi -- @script.csx a b c @script.csx ["a", "b", "c"] // if (sourceFileSeen) { // csi/vbi: at most one script can be specified on command line, anything else is a script arg: parsingScriptArgs = true; scriptArgsOpt.Add(arg); continue; } if (!optionsEnded && arg == "--") { // csi/vbi: no argument past "--" should be treated as an option/response file optionsEnded = true; processedArgs.Add(arg); continue; } } if (!optionsEnded && arg.StartsWith("@", StringComparison.Ordinal)) { // response file: string path = RemoveQuotesAndSlashes(arg.Substring(1)).TrimEnd(null); string resolvedPath = FileUtilities.ResolveRelativePath(path, baseDirectory); if (resolvedPath != null) { foreach (string newArg in ParseResponseFile(resolvedPath, diagnostics).Reverse()) { // Ignores /noconfig option specified in a response file if (!string.Equals(newArg, "/noconfig", StringComparison.OrdinalIgnoreCase) && !string.Equals(newArg, "-noconfig", StringComparison.OrdinalIgnoreCase)) { args.Push(newArg); } else { diagnostics.Add(Diagnostic.Create(_messageProvider, _messageProvider.WRN_NoConfigNotOnCommandLine)); } } if (responsePaths != null) { responsePaths.Add(FileUtilities.NormalizeAbsolutePath(PathUtilities.GetDirectoryName(resolvedPath))); } } else { diagnostics.Add(Diagnostic.Create(_messageProvider, _messageProvider.FTL_InvalidInputFileName, path)); } } else { processedArgs.Add(arg); sourceFileSeen |= optionsEnded || !IsOption(arg); } } }
private IEnumerable <string> ExpandFileNamePattern( string path, string baseDirectory, SearchOption searchOption, IList <Diagnostic> errors) { string directory = PathUtilities.GetDirectoryName(path); string pattern = PathUtilities.GetFileName(path); var resolvedDirectoryPath = (directory.Length == 0) ? baseDirectory : FileUtilities.ResolveRelativePath(directory, baseDirectory); IEnumerator <string> enumerator = null; try { bool yielded = false; // NOTE: Directory.EnumerateFiles(...) surprisingly treats pattern "." the // same way as "*"; as we don't expect anything to be found by this // pattern, let's just not search in this case pattern = pattern.Trim(s_searchPatternTrimChars); bool singleDotPattern = string.Equals(pattern, ".", StringComparison.Ordinal); if (!singleDotPattern) { while (true) { string resolvedPath = null; try { if (enumerator == null) { enumerator = EnumerateFiles(resolvedDirectoryPath, pattern, searchOption).GetEnumerator(); } if (!enumerator.MoveNext()) { break; } resolvedPath = enumerator.Current; } catch { resolvedPath = null; } if (resolvedPath != null) { // just in case EnumerateFiles returned a relative path resolvedPath = FileUtilities.ResolveRelativePath(resolvedPath, baseDirectory); } if (resolvedPath == null) { errors.Add(Diagnostic.Create(MessageProvider, (int)MessageProvider.FTL_InvalidInputFileName, path)); break; } yielded = true; yield return(resolvedPath); } } // the pattern didn't match any files: if (!yielded) { if (searchOption == SearchOption.AllDirectories) { // handling /recurse GenerateErrorForNoFilesFoundInRecurse(path, errors); } else { // handling wildcard in file spec errors.Add(Diagnostic.Create(MessageProvider, (int)MessageProvider.ERR_FileNotFound, path)); } } } finally { if (enumerator != null) { enumerator.Dispose(); } } }
internal void FlattenArgs( IEnumerable <string> rawArguments, IList <Diagnostic> diagnostics, List <string> processedArgs, List <string> scriptArgs, string baseDirectory, List <string> responsePaths = null) { bool parsingScriptArgs = false; Stack <string> args = new Stack <string>(rawArguments.Reverse()); while (args.Count > 0) { //EDMAURER trim off whitespace. Otherwise behavioral differences arise //when the strings which represent args are constructed by cmd or users. //cmd won't produce args with whitespace at the end. string arg = args.Pop().TrimEnd(); if (parsingScriptArgs) { scriptArgs.Add(arg); continue; } if (arg.StartsWith("@", StringComparison.Ordinal)) { // response file: string path = RemoveQuotesAndSlashes(arg.Substring(1)).TrimEnd(null); string resolvedPath = FileUtilities.ResolveRelativePath(path, baseDirectory); if (resolvedPath != null) { foreach (string newArg in ParseResponseFile(resolvedPath, diagnostics).Reverse()) { // Ignores /noconfig option specified in a response file if (!string.Equals(newArg, "/noconfig", StringComparison.OrdinalIgnoreCase) && !string.Equals(newArg, "-noconfig", StringComparison.OrdinalIgnoreCase)) { args.Push(newArg); } else { diagnostics.Add(Diagnostic.Create(_messageProvider, _messageProvider.WRN_NoConfigNotOnCommandLine)); } } if (responsePaths != null) { responsePaths.Add(FileUtilities.NormalizeAbsolutePath(PathUtilities.GetDirectoryName(resolvedPath))); } } else { diagnostics.Add(Diagnostic.Create(_messageProvider, _messageProvider.FTL_InputFileNameTooLong, path)); } } else if (arg == "--" && scriptArgs != null) { parsingScriptArgs = true; } else { processedArgs.Add(arg); } } }