//------------------------------------------------------------ // CSConsoleArgs.ExpandResponseFiles // /// <summary> /// <para>(ConsoleArgs::ProcessResponseArgs in sscli.)</para> /// <para>Process Response files on the command line /// Returns true if it allocated a new argv array that must be freed later</para> /// <para>コマンドラインでレスポンスファイルが指定されていたら、 /// その内容をオプションリストに追加する。 /// (レスポンスファイルは @ファイル名 の形式で指定されている。)</para> /// </summary> //------------------------------------------------------------ private void ExpandResponseFiles() { Dictionary <string, bool> processedResponseFiles = new Dictionary <string, bool>(new StringEqualityComparerIgnoreCase()); List <string[]> listTemp = null; string fileName = null; string fullName = null; string fileContents = null; Exception excp = null; bool foundResponseFile; int loopCount = 0; const int maxLoopCount = 32; do { if (loopCount >= maxLoopCount) { throw new Exception("Too many nested response file."); } listTemp = new List <string[]>(); foundResponseFile = false; foreach (string[] opt in this.OptionList) { // オプションが null や空の場合は破棄する。 if (opt == null || opt.Length == 0) { continue; } // 1 文字目が @ でないものはそのままリストに追加する。 if (opt[1] != "@") { listTemp.Add(opt); continue; } if (opt.Length <= 2 || String.IsNullOrEmpty(opt[2])) { this.Controller.ReportError( CSCERRID.ERR_NoFileSpec, ERRORKIND.ERROR, opt[0]); continue; } // Check for duplicates // @ と引用符を外す。 fileName = opt[2]; IOUtil.RemoveQuotes(ref fileName); if (String.IsNullOrEmpty(fileName)) { this.Controller.ReportError( CSCERRID.ERR_NoFileSpec, ERRORKIND.ERROR, opt[0]); continue; } // ファイルのフルパスを求める。 fullName = this.GetFullFileName(fileName, false); if (String.IsNullOrEmpty(fullName)) { this.Controller.ReportError( CSCERRID.ERR_NoFileSpec, ERRORKIND.ERROR, opt[0]); continue; } // 得られたファイルがすでに処理されていないか調べる。 try { if (processedResponseFiles.ContainsKey(fullName)) { continue; } } catch (ArgumentException) { DebugUtil.Assert(false); continue; } // ファイルの内容を読み込む。エラーの場合はメッセージを表示して次へ。 if (!IOUtil.ReadTextFile(fullName, null, out fileContents, out excp)) { this.Controller.ReportError(ERRORKIND.ERROR, excp.Message); continue; } // レスポンスファイル内で指定されているオプションを取得する。 TextToArgs(fileContents, listTemp); foundResponseFile = true; // 処理済みファイルのリストに追加する。 processedResponseFiles.Add(fullName, true); } this.OptionList = listTemp; ++loopCount; } while (foundResponseFile); }
//============================================================ // For string //============================================================ //------------------------------------------------------------ // Util.SplitString // /// <summary></summary> /// <param name="str"></param> /// <param name="separators"></param> /// <returns></returns> //------------------------------------------------------------ internal static List <string> SplitString( string str, string separators, bool eliminateEmptyString) { List <string> split1 = new List <string>(); if (str == null) { return(split1); } List <string> split2 = new List <string>(); int pos = 0; int start = 0; bool inQuote = false; while (pos < str.Length) { char ch = str[pos]; switch (ch) { case '\\': ++pos; if (pos < str.Length) { ++pos; } break; case '"': inQuote = !inQuote; ++pos; break; default: if (separators.IndexOf(ch) >= 0 && !inQuote) { split2.Add(str.Substring(start, pos - start)); ++pos; start = pos; } else { ++pos; } break; } } split2.Add(str.Substring(start, pos - start)); for (int i = 0; i < split2.Count; ++i) { string seg = split2[i]; seg = seg.Trim(); IOUtil.RemoveQuotes(ref seg); if (!String.IsNullOrEmpty(seg) || !eliminateEmptyString) { split1.Add(seg); } } return(split1); }