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;
106 mcs_output
= mcs
.StandardOutput
.ReadToEnd();
112 mcs_output_lines
= mcs_output
.Split (
113 System
.Environment
.NewLine
.ToCharArray ());
114 foreach (string error_line
in mcs_output_lines
) {
115 CompilerError error
= CreateErrorFromString (error_line
);
117 error_list
.Add (error
);
120 if (bug_report
!= null) {
121 bug_report
.WriteLine ("### Compiler Output");
122 bug_report
.Write (mcs_output
);
125 return (CompilerError
[])error_list
.ToArray (typeof(CompilerError
));
129 /// Converts an error string into a CompilerError object
130 /// Return null if the line was not an error string
132 private static CompilerError
CreateErrorFromString(string error_string
)
134 CompilerError error
= new CompilerError();
135 Regex reg
= new Regex (@"^((?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)\s){0,}(?<level>\w+)\sCS(?<number>\d*):\s(?<message>.*)",
136 RegexOptions
.Compiled
| RegexOptions
.ExplicitCapture
);
138 Match match
= reg
.Match (error_string
);
143 if (String
.Empty
!= match
.Result ("${file}"))
144 error
.SourceFile
= match
.Result ("${file}");
145 if (String
.Empty
!= match
.Result ("${line}"))
146 error
.SourceLine
= Int32
.Parse (match
.Result ("${line}"));
147 if (String
.Empty
!= match
.Result ("${column}"))
148 error
.SourceColumn
= Int32
.Parse (match
.Result ("${column}"));
149 error
.ErrorLevel
= (ErrorLevel
)Enum
.Parse (typeof(ErrorLevel
),
150 match
.Result ("${level}"), true);
151 error
.ErrorNumber
= Int32
.Parse (match
.Result ("${number}"));
152 error
.ErrorMessage
= match
.Result ("${message}");
157 private static string[] CreateCsFiles (string[] source_text
, string[] source_name
)
159 ArrayList temp_file_list
= new ArrayList ();
161 for (int i
=0; i
<source_text
.Length
; i
++) {
162 string temp_path
= Path
.GetTempFileName ();
163 StreamWriter writer
= null;
165 writer
= new StreamWriter (temp_path
);
166 writer
.WriteLine (String
.Format ("#line 1 \"{0}\"",
168 writer
.Write (source_text
[i
]);
174 temp_file_list
.Add (temp_path
);
177 return (string[])temp_file_list
.ToArray (typeof(string));
180 private static string BuildArgs(string[] source_files
,
181 string target
, string[] imports
, IDictionary options
)
183 StringBuilder args
= new StringBuilder ();
185 args
.AppendFormat ("/out:{0} ", target
);
187 if (null != imports
) {
188 foreach (string import
in imports
)
189 args
.AppendFormat ("/r:{0} ", import
);
192 if (null != options
) {
193 foreach (object option
in options
.Keys
) {
194 object value = options
[option
];
195 if (!ValidOption ((string)option
))
197 args
.AppendFormat ("{0} ", OptionString (option
,value));
201 foreach (string source
in source_files
)
202 args
.AppendFormat ("{0} ", source
);
204 return args
.ToString ();
207 private static string OptionString(object option
, object value)
210 return String
.Format ("/{0}:{1}", option
, value);
212 return String
.Format("/{0}", option
);
215 private static void VerifyArgs (string[] sourceTexts
,
216 string[] sourceTextNames
, string target
)
218 if (null == sourceTexts
)
219 throw new ArgumentNullException ("sourceTexts");
220 if (null == sourceTextNames
)
221 throw new ArgumentNullException ("sourceTextNames");
223 throw new ArgumentNullException ("target");
225 if (sourceTexts
.Length
<= 0 || sourceTextNames
.Length
<= 0)
226 throw new IndexOutOfRangeException ();
229 private static StreamWriter
CreateBugReport (string[] source_texts
,
230 string[] source_names
, string path
)
232 StreamWriter bug_report
= null;
235 bug_report
= new StreamWriter (path
);
236 bug_report
.WriteLine ("### C# Compiler Defect Report," +
237 " created {0}", DateTime
.Now
);
242 for (int i
=0; i
<source_texts
.Length
; i
++) {
243 bug_report
.WriteLine ("### Source file: '{0}'",
245 bug_report
.Write (source_texts
[i
]);
248 if (bug_report
!= null)
257 private static bool ValidOption (string option
)