1 // Microsoft.CSharp.Compiler
4 // Jackson Harper (Jackson@LatitudeGeo.com)
6 // (C) 2002 Jackson Harper, All rights reserved.
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections;
34 using System.Diagnostics;
35 using System.Text.RegularExpressions;
37 namespace Microsoft.CSharp {
39 public class Compiler {
45 [MonoTODO("Have not implemented bugreports")]
46 public static CompilerError[] Compile(string[] sourceTexts,
47 string[] sourceTextNames, string target, string[] imports,
50 VerifyArgs (sourceTexts, sourceTextNames, target);
52 string[] temp_cs_files;
53 CompilerError[] errors;
54 string bugreport_path = null;
55 StreamWriter bug_report = null;
57 temp_cs_files = CreateCsFiles (sourceTexts, sourceTextNames);
60 bugreport_path = (string)options["bugreport"];
62 if (bugreport_path != null) {
63 bug_report = CreateBugReport (sourceTexts, sourceTextNames, bugreport_path);
67 errors = CompileFiles (temp_cs_files, target, imports, options, bug_report);
71 foreach (string temp_file in temp_cs_files) {
72 FileInfo file = new FileInfo (temp_file);
75 if (bug_report != null)
86 private static CompilerError[] CompileFiles (string[] cs_files,
87 string target, string[] imports, IDictionary options, StreamWriter bug_report)
89 ArrayList error_list = new ArrayList ();
90 Process mcs = new Process ();
92 string[] mcs_output_lines;
94 mcs.StartInfo.FileName = "mcs";
95 mcs.StartInfo.Arguments = BuildArgs (cs_files,
96 target, imports, options);
97 mcs.StartInfo.CreateNoWindow = true;
98 mcs.StartInfo.UseShellExecute = false;
99 mcs.StartInfo.RedirectStandardOutput = true;
103 mcs_output = mcs.StandardOutput.ReadToEnd();
109 mcs_output_lines = mcs_output.Split (
110 System.Environment.NewLine.ToCharArray ());
111 foreach (string error_line in mcs_output_lines) {
112 CompilerError error = CreateErrorFromString (error_line);
114 error_list.Add (error);
117 if (bug_report != null) {
118 bug_report.WriteLine ("### Compiler Output");
119 bug_report.Write (mcs_output);
122 return (CompilerError[])error_list.ToArray (typeof(CompilerError));
126 /// Converts an error string into a CompilerError object
127 /// Return null if the line was not an error string
129 private static CompilerError CreateErrorFromString(string error_string)
131 CompilerError error = new CompilerError();
132 Regex reg = new Regex (@"^((?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s){0,}(?<level>\w+)\sCS(?<number>\d*):\s(?<message>.*)",
133 RegexOptions.Compiled | RegexOptions.ExplicitCapture);
135 Match match = reg.Match (error_string);
140 if (String.Empty != match.Result ("${file}"))
141 error.SourceFile = match.Result ("${file}");
142 if (String.Empty != match.Result ("${line}"))
143 error.SourceLine = Int32.Parse (match.Result ("${line}"));
144 if (String.Empty != match.Result ("${column}"))
145 error.SourceColumn = Int32.Parse (match.Result ("${column}"));
146 error.ErrorLevel = (ErrorLevel)Enum.Parse (typeof(ErrorLevel),
147 match.Result ("${level}"), true);
148 error.ErrorNumber = Int32.Parse (match.Result ("${number}"));
149 error.ErrorMessage = match.Result ("${message}");
154 private static string[] CreateCsFiles (string[] source_text, string[] source_name)
156 ArrayList temp_file_list = new ArrayList ();
158 for (int i=0; i<source_text.Length; i++) {
159 string temp_path = Path.GetTempFileName ();
160 StreamWriter writer = null;
162 writer = new StreamWriter (temp_path);
163 writer.WriteLine (String.Format ("#line 1 \"{0}\"",
165 writer.Write (source_text[i]);
171 temp_file_list.Add (temp_path);
174 return (string[])temp_file_list.ToArray (typeof(string));
177 private static string BuildArgs(string[] source_files,
178 string target, string[] imports, IDictionary options)
180 StringBuilder args = new StringBuilder ();
182 args.AppendFormat ("/out:{0} ", target);
184 if (null != imports) {
185 foreach (string import in imports)
186 args.AppendFormat ("/r:{0} ", import);
189 if (null != options) {
190 foreach (object option in options.Keys) {
191 object value = options[option];
192 if (!ValidOption ((string)option))
194 args.AppendFormat ("{0} ", OptionString (option,value));
198 foreach (string source in source_files)
199 args.AppendFormat ("{0} ", source);
201 return args.ToString ();
204 private static string OptionString(object option, object value)
207 return String.Format ("/{0}:{1}", option, value);
209 return String.Format("/{0}", option);
212 private static void VerifyArgs (string[] sourceTexts,
213 string[] sourceTextNames, string target)
215 if (null == sourceTexts)
216 throw new ArgumentNullException ("sourceTexts");
217 if (null == sourceTextNames)
218 throw new ArgumentNullException ("sourceTextNames");
220 throw new ArgumentNullException ("target");
222 if (sourceTexts.Length <= 0 || sourceTextNames.Length <= 0)
223 throw new IndexOutOfRangeException ();
226 private static StreamWriter CreateBugReport (string[] source_texts,
227 string[] source_names, string path)
229 StreamWriter bug_report = null;
232 bug_report = new StreamWriter (path);
233 bug_report.WriteLine ("### C# Compiler Defect Report," +
234 " created {0}", DateTime.Now);
239 for (int i=0; i<source_texts.Length; i++) {
240 bug_report.WriteLine ("### Source file: '{0}'",
242 bug_report.Write (source_texts[i]);
245 if (bug_report != null)
254 private static bool ValidOption (string option)