using System.Collections.Specialized;
using System.Diagnostics;
using System.Text.RegularExpressions;
-
+
#if NET_2_0
+ using System.Threading;
using System.Collections.Generic;
#endif
static string windowsMcsPath;
static string windowsMonoPath;
+#if NET_2_0
+ Mutex mcsOutMutex;
+ StringCollection mcsOutput;
+#endif
+
static CSharpCodeCompiler ()
{
if (Path.DirectorySeparatorChar == '\\') {
CompilerResults results=new CompilerResults(options.TempFiles);
Process mcs=new Process();
+#if !NET_2_0
string mcs_output;
string mcs_stdout;
- string[] mcs_output_lines;
+ string[] mcsOutput;
+#endif
+
// FIXME: these lines had better be platform independent.
if (Path.DirectorySeparatorChar == '\\') {
mcs.StartInfo.FileName = windowsMonoPath;
mcs.StartInfo.Arguments=BuildArgs(options, fileNames);
#endif
}
+
+#if NET_2_0
+ mcsOutput = new StringCollection ();
+ mcsOutMutex = new Mutex ();
+#endif
+
mcs.StartInfo.CreateNoWindow=true;
mcs.StartInfo.UseShellExecute=false;
mcs.StartInfo.RedirectStandardOutput=true;
mcs.StartInfo.RedirectStandardError=true;
#if NET_2_0
+ mcs.OutputDataReceived += new DataReceivedEventHandler (McsStdoutDataReceived);
+ mcs.ErrorDataReceived += new DataReceivedEventHandler (McsStderrDataReceived);
+
string mono_inside_mdb = null;
#endif
Environment.SetEnvironmentVariable ("MONO_INSIDE_MDB", null);
}
#endif
-
+
mcs.Start();
+
+#if NET_2_0
+ mcs.BeginOutputReadLine ();
+ mcs.BeginErrorReadLine ();
+#else
// If there are a few kB in stdout, we might lock
mcs_output=mcs.StandardError.ReadToEnd();
mcs_stdout=mcs.StandardOutput.ReadToEnd ();
+#endif
mcs.WaitForExit();
+
results.NativeCompilerReturnValue = mcs.ExitCode;
} finally {
- mcs.Close();
#if NET_2_0
+ mcs.CancelErrorRead ();
+ mcs.CancelOutputRead ();
+
if (mono_inside_mdb != null)
Environment.SetEnvironmentVariable ("MONO_INSIDE_MDB", mono_inside_mdb);
#endif
+
+ mcs.Close();
}
- mcs_output_lines=mcs_output.Split(
- System.Environment.NewLine.ToCharArray());
- bool loadIt=true;
+
+#if NET_2_0
+ StringCollection sc = mcsOutput;
+#else
+ mcsOutput = mcs_output.Split (System.Environment.NewLine.ToCharArray ());
StringCollection sc = new StringCollection ();
- foreach (string error_line in mcs_output_lines)
- {
+#endif
+
+ bool loadIt=true;
+ foreach (string error_line in mcsOutput) {
+#if !NET_2_0
+ Console.WriteLine ("Adding error line");
sc.Add (error_line);
-
- CompilerError error=CreateErrorFromString(error_line);
- if (null!=error)
- {
- results.Errors.Add(error);
- if (!error.IsWarning) loadIt=false;
+#endif
+ CompilerError error = CreateErrorFromString (error_line);
+ if (error != null) {
+ results.Errors.Add (error);
+ if (!error.IsWarning)
+ loadIt = false;
}
}
-
- // (g)mcs outputs no useful information to stdout, we can ignore it here.
+
if (sc.Count > 0) {
- sc.Insert (0, Environment.NewLine);
- sc.Insert (0, mcs.StartInfo.FileName + " " + mcs.StartInfo.Arguments);
+ sc.Insert (0, mcs.StartInfo.FileName + " " + mcs.StartInfo.Arguments + Environment.NewLine);
results.Output = sc;
}
-
+
if (loadIt) {
if (!File.Exists (options.OutputAssembly)) {
- throw new Exception ("Compiler failed to produce the assembly. Stderr='" +mcs_output + "'");
+ StringBuilder sb = new StringBuilder ();
+ foreach (string s in sc)
+ sb.Append (s + Environment.NewLine);
+
+ throw new Exception ("Compiler failed to produce the assembly. Output: '" + sb.ToString () + "'");
}
+
if (options.GenerateInMemory) {
using (FileStream fs = File.OpenRead(options.OutputAssembly)) {
byte[] buffer = new byte[fs.Length];
}
#if NET_2_0
+ void McsStdoutDataReceived (object sender, DataReceivedEventArgs args)
+ {
+ mcsOutMutex.WaitOne ();
+ mcsOutput.Add (args.Data);
+ mcsOutMutex.ReleaseMutex ();
+ }
+
+ void McsStderrDataReceived (object sender, DataReceivedEventArgs args)
+ {
+ mcsOutMutex.WaitOne ();
+ mcsOutput.Add (args.Data);
+ mcsOutMutex.ReleaseMutex ();
+ }
+
private static string BuildArgs(CompilerParameters options,string[] fileNames, Dictionary <string, string> providerOptions)
#else
private static string BuildArgs(CompilerParameters options,string[] fileNames)