1 // Microsoft.CSharp.Compiler
4 // Jackson Harper (Jackson@LatitudeGeo.com)
6 // (C) 2002 Jackson Harper, All rights reserved.
12 using System.Collections;
13 using System.Diagnostics;
14 using System.Text.RegularExpressions;
16 namespace Microsoft.CSharp {
18 public class Compiler {
24 [MonoTODO("Have not implemented bugreports")]
25 public static CompilerError[] Compile(string[] sourceTexts,
26 string[] sourceTextNames, string target, string[] imports,
29 VerifyArgs (sourceTexts, sourceTextNames, target);
31 string[] temp_cs_files;
32 CompilerError[] errors;
34 temp_cs_files = CreateCsFiles (sourceTexts, sourceTextNames);
37 errors = CompileFiles (temp_cs_files, target, imports, options);
41 foreach (string temp_file in temp_cs_files) {
42 FileInfo file = new FileInfo (temp_file);
54 private static CompilerError[] CompileFiles (string[] cs_files,
55 string target, string[] imports, IDictionary options)
57 ArrayList error_list = new ArrayList ();
58 Process mcs = new Process ();
60 string[] mcs_output_lines;
62 mcs.StartInfo.FileName = "mcs";
63 mcs.StartInfo.Arguments = BuildArgs (cs_files,
64 target, imports, options);
65 mcs.StartInfo.CreateNoWindow = true;
66 mcs.StartInfo.UseShellExecute = false;
67 mcs.StartInfo.RedirectStandardOutput = true;
71 mcs_output = mcs.StandardOutput.ReadToEnd();
77 mcs_output_lines = mcs_output.Split (
78 System.Environment.NewLine.ToCharArray ());
79 foreach (string error_line in mcs_output_lines) {
80 CompilerError error = CreateErrorFromString (error_line);
82 error_list.Add (error);
85 return (CompilerError[])error_list.ToArray (typeof(CompilerError));
89 /// Converts an error string into a CompilerError object
90 /// Return null if the line was not an error string
92 private static CompilerError CreateErrorFromString(string error_string)
94 CompilerError error = new CompilerError();
95 Regex reg = new Regex (@"^((?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s){0,}(?<level>\w+)\sCS(?<number>\d*):\s(?<message>.*)",
96 RegexOptions.Compiled | RegexOptions.ExplicitCapture);
98 Match match = reg.Match (error_string);
103 if (String.Empty != match.Result ("${file}"))
104 error.SourceFile = match.Result ("${file}");
105 if (String.Empty != match.Result ("${line}"))
106 error.SourceLine = Int32.Parse (match.Result ("${line}"));
107 if (String.Empty != match.Result ("${column}"))
108 error.SourceColumn = Int32.Parse (match.Result ("${column}"));
109 error.ErrorLevel = (ErrorLevel)Enum.Parse (typeof(ErrorLevel),
110 match.Result ("${level}"), true);
111 error.ErrorNumber = Int32.Parse (match.Result ("${number}"));
112 error.ErrorMessage = match.Result ("${message}");
117 private static string[] CreateCsFiles (string[] source_text, string[] source_name)
119 ArrayList temp_file_list = new ArrayList ();
121 for (int i=0; i<source_text.Length; i++) {
122 string temp_path = Path.GetTempFileName ();
123 StreamWriter writer = null;
125 writer = new StreamWriter (temp_path);
126 writer.WriteLine (String.Format ("#line 1 \"{0}\"",
128 writer.Write (source_text[i]);
134 temp_file_list.Add (temp_path);
137 return (string[])temp_file_list.ToArray (typeof(string));
140 private static string BuildArgs(string[] source_files,
141 string target, string[] imports, IDictionary options)
143 StringBuilder args = new StringBuilder ();
145 args.AppendFormat ("/out:{0} ", target);
147 if (null != imports) {
148 foreach (string import in imports)
149 args.AppendFormat ("/r:{0} ", import);
152 if (null != options) {
153 foreach (object option in options.Keys) {
154 object value = options[option];
155 args.AppendFormat ("{0} ", OptionString (option,value));
159 foreach (string source in source_files)
160 args.AppendFormat ("{0} ", source);
162 return args.ToString ();
165 private static string OptionString(object option, object value)
168 return String.Format ("/{0}:{1}", option, value);
170 return String.Format("/{0}", option);
173 private static void VerifyArgs (string[] sourceTexts,
174 string[] sourceTextNames, string target)
176 if (null == sourceTexts)
177 throw new ArgumentNullException ("sourceTexts");
178 if (null == sourceTextNames)
179 throw new ArgumentNullException ("sourceTextNames");
181 throw new ArgumentNullException ("target");
183 if (sourceTexts.Length <= 0 || sourceTextNames.Length <= 0)
184 throw new IndexOutOfRangeException ();