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 {
42 public class Compiler {
48 [MonoTODO("Have not implemented bugreports")]
49 public static CompilerError[] Compile(string[] sourceTexts,
50 string[] sourceTextNames, string target, string[] imports,
53 VerifyArgs (sourceTexts, sourceTextNames, target);
55 string[] temp_cs_files;
56 CompilerError[] errors;
57 string bugreport_path = null;
58 StreamWriter bug_report = null;
60 temp_cs_files = CreateCsFiles (sourceTexts, sourceTextNames);
63 bugreport_path = (string)options["bugreport"];
65 if (bugreport_path != null) {
66 bug_report = CreateBugReport (sourceTexts, sourceTextNames, bugreport_path);
70 errors = CompileFiles (temp_cs_files, target, imports, options, bug_report);
74 foreach (string temp_file in temp_cs_files) {
75 FileInfo file = new FileInfo (temp_file);
78 if (bug_report != null)
89 private static CompilerError[] CompileFiles (string[] cs_files,
90 string target, string[] imports, IDictionary options, StreamWriter bug_report)
92 ArrayList error_list = new ArrayList ();
93 Process mcs = new Process ();
95 string[] mcs_output_lines;
97 mcs.StartInfo.FileName = "mcs";
98 mcs.StartInfo.Arguments = BuildArgs (cs_files,
99 target, imports, options);
100 mcs.StartInfo.CreateNoWindow = true;
101 mcs.StartInfo.UseShellExecute = false;
102 mcs.StartInfo.RedirectStandardOutput = true;
103 mcs.StartInfo.RedirectStandardError = true;
107 mcs_output = mcs.StandardError.ReadToEnd ();
108 mcs.StandardOutput.ReadToEnd ();
114 mcs_output_lines = mcs_output.Split (
115 System.Environment.NewLine.ToCharArray ());
116 foreach (string error_line in mcs_output_lines) {
117 CompilerError error = CreateErrorFromString (error_line);
119 error_list.Add (error);
122 if (bug_report != null) {
123 bug_report.WriteLine ("### Compiler Output");
124 bug_report.Write (mcs_output);
127 return (CompilerError[])error_list.ToArray (typeof(CompilerError));
131 /// Converts an error string into a CompilerError object
132 /// Return null if the line was not an error string
134 private static CompilerError CreateErrorFromString(string error_string)
136 CompilerError error = new CompilerError();
137 Regex reg = new Regex (@"^((?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s){0,}(?<level>\w+)\sCS(?<number>\d*):\s(?<message>.*)",
138 RegexOptions.Compiled | RegexOptions.ExplicitCapture);
140 Match match = reg.Match (error_string);
145 if (String.Empty != match.Result ("${file}"))
146 error.SourceFile = match.Result ("${file}");
147 if (String.Empty != match.Result ("${line}"))
148 error.SourceLine = Int32.Parse (match.Result ("${line}"));
149 if (String.Empty != match.Result ("${column}"))
150 error.SourceColumn = Int32.Parse (match.Result ("${column}"));
151 error.ErrorLevel = (ErrorLevel)Enum.Parse (typeof(ErrorLevel),
152 match.Result ("${level}"), true);
153 error.ErrorNumber = Int32.Parse (match.Result ("${number}"));
154 error.ErrorMessage = match.Result ("${message}");
159 private static string[] CreateCsFiles (string[] source_text, string[] source_name)
161 ArrayList temp_file_list = new ArrayList ();
163 for (int i=0; i<source_text.Length; i++) {
164 string temp_path = Path.GetTempFileName ();
165 StreamWriter writer = null;
167 writer = new StreamWriter (temp_path);
168 writer.WriteLine (String.Format ("#line 1 \"{0}\"",
170 writer.Write (source_text[i]);
176 temp_file_list.Add (temp_path);
179 return (string[])temp_file_list.ToArray (typeof(string));
182 private static string BuildArgs(string[] source_files,
183 string target, string[] imports, IDictionary options)
185 StringBuilder args = new StringBuilder ();
187 args.AppendFormat ("/out:{0} ", target);
189 if (null != imports) {
190 foreach (string import in imports)
191 args.AppendFormat ("/r:{0} ", import);
194 if (null != options) {
195 foreach (object option in options.Keys) {
196 object value = options[option];
197 if (!ValidOption ((string)option))
199 args.AppendFormat ("{0} ", OptionString (option,value));
203 foreach (string source in source_files)
204 args.AppendFormat ("{0} ", source);
206 return args.ToString ();
209 private static string OptionString(object option, object value)
212 return String.Format ("/{0}:{1}", option, value);
214 return String.Format("/{0}", option);
217 private static void VerifyArgs (string[] sourceTexts,
218 string[] sourceTextNames, string target)
220 if (null == sourceTexts)
221 throw new ArgumentNullException ("sourceTexts");
222 if (null == sourceTextNames)
223 throw new ArgumentNullException ("sourceTextNames");
225 throw new ArgumentNullException ("target");
227 if (sourceTexts.Length <= 0 || sourceTextNames.Length <= 0)
228 throw new IndexOutOfRangeException ();
231 private static StreamWriter CreateBugReport (string[] source_texts,
232 string[] source_names, string path)
234 StreamWriter bug_report = null;
237 bug_report = new StreamWriter (path);
238 bug_report.WriteLine ("### C# Compiler Defect Report," +
239 " created {0}", DateTime.Now);
244 for (int i=0; i<source_texts.Length; i++) {
245 bug_report.WriteLine ("### Source file: '{0}'",
247 bug_report.Write (source_texts[i]);
250 if (bug_report != null)
259 private static bool ValidOption (string option)