//------------------------------------------------------------ // 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); }
//------------------------------------------------------------ // CAsmLink.SetNonAssemblyFlags // // If afNoRefHash is specified and this.m_bDontDoHashes is not set, // set m_bDoHash false for all CAssembly instants in m_pImports, // If failed to get a CFile instance of a CAssembly instant, return error code. //------------------------------------------------------------ //virtual internal HRESULT SetNonAssemblyFlags(AssemblyFlags afFlags) //{ // ASSERT(m_bInited && !m_bAssemblyEmitted && !m_bPreClosed); // HRESULT hr = S_FALSE; // // if (afFlags & afNoRefHash) { // if (!m_bDontDoHashes) { // // This just changed, so tell all the previously imported assemblies // DWORD cnt = m_pImports->CountFiles(); // for (DWORD d = 0; d < cnt; d++) { // CAssembly *pFile = NULL; // if (FAILED(hr = m_pImports->GetFile(d, (CFile**)&pFile))) // return hr; // pFile->DontDoHash(); // } // } // m_bDontDoHashes = true; // } // // return hr; //} // Files and importing //------------------------------------------------------------ // CAsmLink.ImportFile (Do not use, call ImportFileEx2) //------------------------------------------------------------ // virtual internal HRESULT ImportFile( // LPCWSTR pszFilename, // LPCWSTR pszTargetName, // BOOL fSmartImport, // mdToken *pFileToken, // IMetaDataAssemblyImport **ppAssemblyScope, // DWORD *pdwCountOfScopes) //{ // return ImportFileEx2( // pszFilename, // pszTargetName, // NULL, // fSmartImport, // ofReadOnly | ofNoTypeLib, // pFileToken, // ppAssemblyScope, // pdwCountOfScopes); //} //------------------------------------------------------------ // CAsmLink.ImportFile2 (Do not use, call ImportFileEx2) //------------------------------------------------------------ // virtual internal HRESULT ImportFile2( // LPCWSTR pszFilename, // LPCWSTR pszTargetName, // IMetaDataAssemblyImport *pAssemblyScopeIn, // BOOL fSmartImport, // mdToken *pFileToken, // IMetaDataAssemblyImport **ppAssemblyScope, // DWORD *pdwCountOfScopes) //{ // return ImportFileEx2( // pszFilename, // pszTargetName, // pAssemblyScopeIn, // fSmartImport, // ofReadOnly | ofNoTypeLib, // pFileToken, // ppAssemblyScope, // pdwCountOfScopes); //} //------------------------------------------------------------ // CAsmLink.ImportFileEx (Do not use, call ImportFileEx2) //------------------------------------------------------------ // virtual internal HRESULT ImportFileEx( // LPCWSTR pszFilename, // LPCWSTR pszTargetName, // BOOL fSmartImport, // DWORD dwOpenFlags, // mdToken *pFileToken, // IMetaDataAssemblyImport **ppAssemblyScope, // DWORD *pdwCountOfScopes) //{ // return ImportFileEx2( // pszFilename, // pszTargetName, // NULL, // fSmartImport, // dwOpenFlags, // pFileToken, // ppAssemblyScope, // pdwCountOfScopes); //} //------------------------------------------------------------ // CAsmLink.ImportFileEx2 // /// <summary> /// Create a CModuleEx instance or CAssemblyEx instance for a given INFILESYM. /// </summary> /// <param name="infileSym"></param> /// <param name="targetName"></param> /// <returns></returns> //------------------------------------------------------------ internal bool ImportFileEx2(INFILESYM infileSym, string targetName) { //DebugUtil.Assert(m_bInited); if (infileSym == null || infileSym.FileInfo == null) { return(false); } string newTarget = null; bool isNewTarget = false; Exception excp = null; //-------------------------------------------------- // Check if pszFilename is valid. // Then, if pszTargetName is NULL, assign pszFilename to it. //-------------------------------------------------- FileInfo fileInfo = infileSym.FileInfo; FileInfo targetInfo = null; if (!String.IsNullOrEmpty(targetName)) { if (!IOUtil.CreateFileInfo(targetName, out targetInfo, out excp)) { return(false); } } if (targetInfo == null || String.IsNullOrEmpty(targetInfo.Name)) { newTarget = infileSym.Name; isNewTarget = false; } else { newTarget = targetName; isNewTarget = (String.Compare(infileSym.Name, newTarget, true) != 0); } // If cassembly is null, create from fileName. //-------------------------------------------------- // Module // // If the file is a module, load it as a module of this.assemblyBuilder. // And create CModule instance, add to this.importedModuleDic //-------------------------------------------------- if (infileSym.IsModule) { if (infileSym.IsModuleLoaded) { return(true); } if (this.tempAssemblyBuilder == null) { CreateTempAssemblyBuilder(); } CModuleEx cmod = this.tempAssemblyBuilder.AddModule( infileSym, null, targetName, false); if (cmod == null) { return(false); } if (!this.importedModuleDic.Add(cmod.Name, cmod)) { // If the name is already registered, CDictionary.Add returns false. // Show warning and contiue processing. } return(true); } //-------------------------------------------------- // Assembly //-------------------------------------------------- else if (infileSym.IsAssembly) { if (infileSym.IsAssemblyLoaded) { return(true); } CAssemblyEx casm = new CAssemblyEx(this.controller); if (!casm.Init(infileSym.FileInfo, this)) { return(false); } //if (this.m_bDontDoHashes == true) casm.DontDoHash(); //casm.SetInMemory(); if (casm.ImportAssembly(true)) { if (isNewTarget) { this.controller.ReportError( ALERRID.ERR_CantRenameAssembly, ERRORKIND.ERROR, infileSym.Name); } if (!this.importedAssemblyDic.Add(casm.FileFullName, casm)) { // Duplicate. Show warning. infileSym.SetMetadataFile(importedAssemblyDic[casm.FileFullName]); } else { infileSym.SetMetadataFile(casm); if (casm.IsStdLib) { this.msCorLib = casm; } } return(true); } } return(false); }
//------------------------------------------------------------ // CSConsoleArgs.wcstoul64 //------------------------------------------------------------ // to \Utilities //------------------------------------------------------------ // CSConsoleArgs.ExamineNoConfigOption // /// <summary> /// <para>(ConsoleArgs::ProcessAutoConfig in sscli)</para> /// <para>Process '/noconfig', and CSC.CFG, modifying the argument list</para> /// <para>Process Auto Config options: /// #1 search for '/noconfig' /// if not present and csc.cfg exists in EXE dir, inject after env var stuff</para> /// <para>/noconfig が指定されていなければ、 /// csc.rsp ファイルの内容をオプションリストに追加する。</para> /// </summary> //------------------------------------------------------------ private void ExamineNoConfigOption() { this.NoConfig = false; //-------------------------------------------------- // Scan the argument list for the "/noconfig" options. If present, just kill it and bail. // /noconfig または -noconfig が指定されていれば foundNoConfig に true をセットする。 //-------------------------------------------------- for (int i = 0; i < this.OptionList.Count; ++i) { string[] opt = this.OptionList[i]; // Skip everything except options if ((opt.Length < 3 || opt[1] != "/")) { continue; } if (String.Compare(opt[2], "noconfig", true) == 0) { this.NoConfig = true; // /noconfig オプションは引数リストから削除する。 // 複数回指定されている可能性もあるので break しない。 this.OptionList[i] = null; } } // /noconfig が指定されている場合は終了する。 if (this.NoConfig) { return; } //-------------------------------------------------- // 指定されていない場合は csc.rsp をレスポンスファイルとしてオプションに追加する。 // まずこのアセンブリと同じディレクトリに csc.rsp があるか調べる。 //-------------------------------------------------- string rspFullName = null; System.IO.FileInfo finfo = null; Exception excp = null; try { rspFullName = Path.Combine( Path.GetDirectoryName(Assembly.GetAssembly(typeof(Util)).Location), @"csc.rsp"); } catch (ArgumentException ex) { this.Controller.ReportError(ERRORKIND.ERROR, ex); return; } catch (PathTooLongException ex) { this.Controller.ReportError(ERRORKIND.ERROR, ex); return; } if (!IOUtil.CreateFileInfo(rspFullName, out finfo, out excp) || finfo == null) { if (excp != null) { this.Controller.ReportError(ERRORKIND.ERROR, excp); } else { this.Controller.ReportInternalCompilerError("ExamineNoConfigOption"); } return; } if (!finfo.Exists) { // In this project, mscorlib.dll and system.dll are always imported. // So, it is not an error that csc.rsp is not found. this.Controller.WriteLine("no csc.rsp"); return; } // If cannot open csc.rsp, show warning. if ((finfo.Attributes & ( System.IO.FileAttributes.Compressed | System.IO.FileAttributes.Directory | System.IO.FileAttributes.Encrypted)) != 0) { this.Controller.ReportError(ERRORKIND.WARNING, "csc.rsp could not be opened."); return; } //-------------------------------------------------- // この時点では実際に csc.rsp が存在し読み取り可能である。 // 先頭に @ をつけてオプションリストの先頭に追加する。 //-------------------------------------------------- this.OptionList.Insert(0, new string[3] { "@" + rspFullName, "@", rspFullName }); }
//============================================================ // 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); }