codecompiler.cs
来自「没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没」· CS 代码 · 共 543 行
CS
543 行
/* * CodeCompiler.cs - Implementation of the * System.CodeDom.Compiler.CodeCompiler class. * * Copyright (C) 2002 Southern Storm Software, Pty Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */namespace System.CodeDom.Compiler{#if CONFIG_CODEDOMusing System.IO;using System.Collections;using System.Reflection;using System.Diagnostics;using System.Globalization;using System.Text;public abstract class CodeCompiler : CodeGenerator, ICodeCompiler{ // Constructor. protected CodeCompiler() : base() {} // Join an array of strings with a separator. protected static String JoinStringArray(String[] sa, String separator) { if(sa == null || sa.Length == 0) { return String.Empty; } return ProcessStartInfo.ArgVToArguments(sa, 0, separator); } // Get the name of the compiler. protected abstract String CompilerName { get; } // Get the file extension to use for source files. protected abstract String FileExtension { get; } // Convert compiler parameters into compiler arguments. protected abstract String CmdArgsFromParameters (CompilerParameters options); // Compile a CodeDom compile unit. protected virtual CompilerResults FromDom (CompilerParameters options, CodeCompileUnit e) { CodeCompileUnit[] list = new CodeCompileUnit [1]; list[0] = e; return FromDomBatch(options, list); } // Compile an array of CodeDom compile units. protected virtual CompilerResults FromDomBatch (CompilerParameters options, CodeCompileUnit[] ea) { // Write all of the CodeDom units to temporary files. String[] tempFiles = new String [ea.Length]; int src; Stream stream; StreamWriter writer; for(src = 0; src < ea.Length; ++src) { tempFiles[src] = options.TempFiles.AddExtension (src + FileExtension); stream = new FileStream(tempFiles[src], FileMode.Create, FileAccess.Write, FileShare.Read); try { writer = new StreamWriter(stream, Encoding.UTF8); ((ICodeGenerator)this).GenerateCodeFromCompileUnit (ea[src], writer, Options); writer.Flush(); writer.Close(); } finally { stream.Close(); } } // Compile the temporary files. return FromFileBatch(options, tempFiles); } // Compile a file. protected virtual CompilerResults FromFile (CompilerParameters options, String fileName) { // Verify that the file can be read, throwing an // exception to the caller if it cannot. (new FileStream(fileName, FileMode.Open, FileAccess.Read)) .Close(); // Pass the filename to "FromFileBatch". String[] list = new String [1]; list[0] = fileName; return FromFileBatch(options, list); } // Compile an array of files. protected virtual CompilerResults FromFileBatch (CompilerParameters options, String[] fileNames) { // Add an output filename to the options if necessary. if(options.OutputAssembly == null || options.OutputAssembly.Length == 0) { if(options.GenerateExecutable) { options.OutputAssembly = options.TempFiles.AddExtension ("exe", !(options.GenerateInMemory)); } else { options.OutputAssembly = options.TempFiles.AddExtension ("dll", !(options.GenerateInMemory)); } } // Build the full command-line to pass to the compiler. String args = CmdArgsFromParameters(options); args = args + " " + JoinStringArray(fileNames, " "); // If the argument array is too long, then write the // command-line to a temporary file and use "@file". if(args.Length > 8192) // string length > 8k { args = GetResponseFileCmdArgs(options, args); } // Create a compiler results block. CompilerResults results; results = new CompilerResults(options.TempFiles); // Build the process start info block. ProcessStartInfo startInfo; startInfo = new ProcessStartInfo(CompilerName, args); startInfo.RedirectStandardError = true; startInfo.UseShellExecute = false; // Create and run the process. Process process = Process.Start(startInfo); // Read the stderr stream until EOF. String line; while((line = process.StandardError.ReadLine()) != null) { results.Output.Add(line); ProcessCompilerOutputLine(results, line); } // Wait for the process to exit and record the return code. process.WaitForExit(); results.NativeCompilerReturnValue = process.ExitCode; process.Close(); // Load the assembly into memory if necessary. if(!(results.Errors.HasErrors) && options.GenerateInMemory) { FileStream stream; stream = new FileStream(options.OutputAssembly, FileMode.Open, FileAccess.Read, FileShare.Read); try { // We must use the memory-based load method, // because "OutputAssembly" may be deleted // before we are done with the assembly. byte[] buf = new byte [(int)(stream.Length)]; stream.Read(buf, 0, buf.Length); results.CompiledAssembly = Assembly.Load(buf); } finally { stream.Close(); } } else { results.PathToAssembly = options.OutputAssembly; } // Return the final results to the caller. return results; } // Compile a source string. protected virtual CompilerResults FromSource (CompilerParameters options, String source) { String[] list = new String [1]; list[0] = source; return FromSourceBatch(options, list); } // Compile an array of source strings. protected virtual CompilerResults FromSourceBatch (CompilerParameters options, String[] sources) { // Write all of the sources to temporary files. String[] tempFiles = new String [sources.Length]; int src; Stream stream; StreamWriter writer; for(src = 0; src < sources.Length; ++src) { tempFiles[src] = options.TempFiles.AddExtension (src + "." + FileExtension); stream = new FileStream(tempFiles[src], FileMode.Create, FileAccess.Write, FileShare.Read); try { writer = new StreamWriter(stream, Encoding.UTF8); writer.Write(sources[src]); writer.Flush(); writer.Close(); } finally { stream.Close(); } } // Compile the temporary files. return FromFileBatch(options, tempFiles); } // Get the response file command arguments. protected virtual String GetResponseFileCmdArgs (CompilerParameters options, String cmdArgs) { // Get a temporary file to use for the response file. String responseFile = options.TempFiles.AddExtension("cmdline"); // Write the arguments to the response file. Stream stream = new FileStream(responseFile, FileMode.Create, FileAccess.Write, FileShare.Read); try { StreamWriter writer = new StreamWriter (stream, Encoding.UTF8); writer.Write(cmdArgs); writer.Flush(); writer.Close(); } finally { stream.Close(); } // Build the new command-line containing the response file. return "@\"" + responseFile + "\""; } // Internal version of "ProcessCompilerOutputLine". // The line may have one of the following forms: // // FILENAME(LINE,COLUMN): error CODE: message // FILENAME(LINE,COLUMN): fatal error CODE: message // FILENAME(LINE,COLUMN): warning CODE: message // FILENAME:LINE: message // FILENAME:LINE:COLUMN: message // FILENAME:LINE: warning: message // FILENAME:LINE:COLUMN: warning: message // internal static CompilerError ProcessCompilerOutputLine(String line) { CompilerError error; int posn, start; // Bail out if the line is empty. if(line == null || line.Length == 0) { return null; } // Create the error block. error = new CompilerError(); // Parse out the filename. posn = 0; if(line.Length >= 3 && Char.IsLetter(line[0]) && line[1] == ':' && (line[2] == '/' || line[2] == '\\')) { // Filename starting with a Windows drive specification. posn += 3; } while(posn < line.Length && line[posn] != ':' && line[posn] != '(') { ++posn; } if(posn >= line.Length) { return null; } error.FileName = line.Substring(0, posn); // Parse out the line and column numbers. if(line[posn] == '(') { // (LINE,COLUMN) format. ++posn; start = posn; while(posn < line.Length && line[posn] != ')' && line[posn] != ',') { ++posn; } error.Line = Int32.Parse (line.Substring(start, posn - start)); if(posn < line.Length && line[posn] == ',') { ++posn; start = posn; while(posn < line.Length && line[posn] != ')' && line[posn] != ',') { ++posn; } error.Column = Int32.Parse (line.Substring(start, posn - start)); } while(posn < line.Length && line[posn] != ')') { ++posn; } if(posn < line.Length) { ++posn; } if(posn < line.Length && line[posn] == ':') { ++posn; } } else { // LINE:COLUMN format. ++posn; start = posn; while(posn < line.Length && line[posn] != ':') { ++posn; } error.Line = Int32.Parse (line.Substring(start, posn - start)); if(posn < line.Length && line[posn + 1] != ' ') { ++posn; start = posn; while(posn < line.Length && line[posn] != ':') { ++posn; } error.Column = Int32.Parse (line.Substring(start, posn - start)); } if(posn < line.Length) { ++posn; } } // Skip white space. while(posn < line.Length && line[posn] == ' ') { ++posn; } // Parse the error type. bool needCode = true; if((line.Length - posn) >= 6 && String.CompareOrdinal("error ", 0, line, posn, 6) == 0) { posn += 6; } else if((line.Length - posn) >= 12 && String.CompareOrdinal ("fatal error ", 0, line, posn, 12) == 0) { posn += 12; } else if((line.Length - posn) >= 8 && String.CompareOrdinal ("warning ", 0, line, posn, 8) == 0) { error.IsWarning = true; posn += 8; } else if((line.Length - posn) >= 8 && String.CompareOrdinal ("warning:", 0, line, posn, 8) == 0) { error.IsWarning = true; posn += 8; needCode = false; } else { needCode = false; } // Parse the error code. if(needCode) { start = posn; while(posn < line.Length && line[posn] != ':') { ++posn; } error.ErrorNumber = line.Substring(posn, posn - start); if(posn < line.Length) { ++posn; } } // Skip white space. while(posn < line.Length && line[posn] == ' ') { ++posn; } // Extract the error text. error.ErrorText = line.Substring(posn); // Return the error block to the caller. return error; } // Process an output line from the compiler. protected abstract void ProcessCompilerOutputLine (CompilerResults results, String line); // Compile an assembly from a CodeDom compile unit. CompilerResults ICodeCompiler.CompileAssemblyFromDom (CompilerParameters options, CodeCompileUnit compilationUnit) { try { return FromDom(options, compilationUnit); } finally { options.TempFiles.Delete(); } } // Compile an assembly from an array of CodeDom compile units. CompilerResults ICodeCompiler.CompileAssemblyFromDomBatch (CompilerParameters options, CodeCompileUnit[] compilationUnits) { try { return FromDomBatch(options, compilationUnits); } finally { options.TempFiles.Delete(); } } // Compile an assembly from the contents of a source file. CompilerResults ICodeCompiler.CompileAssemblyFromFile (CompilerParameters options, String fileName) { try { return FromFile(options, fileName); } finally { options.TempFiles.Delete(); } } // Compile an assembly from the contents of an array of source files. CompilerResults ICodeCompiler.CompileAssemblyFromFileBatch (CompilerParameters options, String[] fileNames) { try { return FromFileBatch(options, fileNames); } finally { options.TempFiles.Delete(); } } // Compile an assembly from the contents of a source string. CompilerResults ICodeCompiler.CompileAssemblyFromSource (CompilerParameters options, String source) { try { return FromSource(options, source); } finally { options.TempFiles.Delete(); } } // Compile an assembly from the contents of an array of source strings. CompilerResults ICodeCompiler.CompileAssemblyFromSourceBatch (CompilerParameters options, String[] sources) { try { return FromSourceBatch(options, sources); } finally { options.TempFiles.Delete(); } }}; // class CodeCompiler#endif // CONFIG_CODEDOM}; // namespace System.CodeDom.Compiler
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?