static async Task runCoqtop(string coqtopBin, string mainChannel, string controlChannel, bool ideSlave, IEnumerable <string> args, string traceFile) { var editorMain = await openChannelSocket(mainChannel); var editorControl = await openChannelSocket(controlChannel); Stream coqtopMain; Stream coqtopControl; var coqtop = new Process(); coqtop.StartInfo.UseShellExecute = false; coqtop.StartInfo.RedirectStandardError = false; coqtop.StartInfo.RedirectStandardInput = true; coqtop.StartInfo.RedirectStandardOutput = false; //if (System.Environment.OSVersion.Platform == PlatformID.Win32NT) //{// coqtop expects a dedicated read and write socket for each channel on Windows due to a bug in OCaml var coqtopMainR = new TcpListener(IPAddress.Loopback, 0); var coqtopMainW = new TcpListener(IPAddress.Loopback, 0); var coqtopControlR = new TcpListener(IPAddress.Loopback, 0); var coqtopControlW = new TcpListener(IPAddress.Loopback, 0); coqtopMainR.Start(1); coqtopMainW.Start(1); coqtopControlR.Start(1); coqtopControlW.Start(1); var coqtopMainAddr = ((IPEndPoint)coqtopMainR.LocalEndpoint).Address.ToString() + ":" + ((IPEndPoint)coqtopMainR.LocalEndpoint).Port + ":" + ((IPEndPoint)coqtopMainW.LocalEndpoint).Port; var coqtopControlAddr = ((IPEndPoint)coqtopControlR.LocalEndpoint).Address.ToString() + ":" + ((IPEndPoint)coqtopControlR.LocalEndpoint).Port + ":" + ((IPEndPoint)coqtopControlW.LocalEndpoint).Port; var arguments = String.Format("{0} -main-channel {1} -control-channel {2} ", ideSlave ? "-ideslave" : "", coqtopMainAddr, coqtopControlAddr) + String.Join(" ", args); coqtop.StartInfo.FileName = coqtopBin; coqtop.StartInfo.Arguments = arguments; coqtop.Start(); //var stderr = Console.OpenStandardError(); //coqtop.StandardError.BaseStream.CopyToAsync(stderr); //coqtop.StandardOutput.BaseStream.CopyToAsync(stderr); var connections = await Task.WhenAny(new Task <Tuple <Stream, Stream> >[] { AcceptCoqTopConnections(coqtopMainR, coqtopMainW, coqtopControlR, coqtopControlW) , Task.Run <Tuple <Stream, Stream> >(() => { System.Threading.Thread.Sleep(5000); return((Tuple <Stream, Stream>)null); }) }).Result; if (connections == null) { await Console.Error.WriteLineAsync("No response from coqtop."); System.Environment.Exit(-1); } coqtopMain = connections.Item1; coqtopControl = connections.Item2; coqtopMainR.Stop(); coqtopMainW.Stop(); coqtopControlR.Stop(); coqtopControlW.Stop(); //} else { // var coqtopMainRW = new TcpListener(IPAddress.Loopback, 0); // var coqtopControlRW = new TcpListener(IPAddress.Loopback, 0); // var coqtopMainAddr = ((IPEndPoint)coqtopMainRW.LocalEndpoint).Address.ToString() + ":" + ((IPEndPoint)coqtopMainRW.LocalEndpoint).Port; // var coqtopControlAddr = ((IPEndPoint)coqtopControlRW.LocalEndpoint).Address.ToString() + ":" + ((IPEndPoint)coqtopControlRW.LocalEndpoint).Port; // var arguments = String.Format("{0} -main-channel {1} -control-channel {2}", ideSlave ? "-ideslave" : "", coqtopMainAddr, coqtopControlAddr) // + String.Join(" ", args); // coqtopMainRW.Start(); // coqtopControlRW.Start(); // coqtop = Process.Start(coqtopBin, arguments); // var coqtopMainConnection = await coqtopMainRW.AcceptTcpClientAsync(); // var coqtopControlConnection = await coqtopControlRW.AcceptTcpClientAsync(); // coqtopMain = coqtopMainConnection.GetStream(); // coqtopControl = coqtopControlConnection.GetStream(); // coqtopMainRW.Stop(); // coqtopControlRW.Stop(); //} FileStream trace = null; if (traceFile != null) { try { File.Delete(traceFile); trace = new FileStream(traceFile, FileMode.Create); var header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n</root>"; var headerBytes = System.Text.Encoding.UTF8.GetBytes(header); trace.Write(headerBytes, 0, headerBytes.Length); trace.Position = header.IndexOf("\n</root>"); } catch (Exception) { trace = null; } } if (trace != null) { var closeXml = "\n</root>"; var closeXmlBytes = System.Text.Encoding.UTF8.GetBytes(closeXml); coqtopMain = new TraceStream(coqtopMain, System.Text.Encoding.UTF8.GetBytes("\n<!-- editor->coqtop main-channel: -->\n"), closeXmlBytes, trace); editorMain = new TraceStream(editorMain, System.Text.Encoding.UTF8.GetBytes("\n<!-- coqtop->editor main-channel: -->\n"), closeXmlBytes, trace); coqtopControl = new TraceStream(coqtopControl, System.Text.Encoding.UTF8.GetBytes("\n<!-- editor->coqtop control-channel: -->\n"), closeXmlBytes, trace); editorControl = new TraceStream(editorControl, System.Text.Encoding.UTF8.GetBytes("\n<!-- coqtop->editor control-channel: -->\n"), closeXmlBytes, trace); } var tasks = new List <Task>(); tasks.Add(coqtopMain.CopyToAsync(editorMain)); if (!ideSlave) { tasks.Add(editorMain.CopyToAsync(coqtopMain)); } else { tasks.Add(copyStreamWithInterrupt(coqtop, editorMain, coqtopMain)); } if (controlChannel != null) { tasks.Add(coqtopControl.CopyToAsync(editorControl)); tasks.Add(editorControl.CopyToAsync(coqtopControl)); } await Task.WhenAny(tasks); }
static async Task runCoqtop(string coqtopBin, string mainChannel, string controlChannel, bool ideSlave, IEnumerable<string> args, string traceFile) { var editorMain = await openChannelSocket(mainChannel); var editorControl = await openChannelSocket(controlChannel); Stream coqtopMain; Stream coqtopControl; var coqtop = new Process(); coqtop.StartInfo.UseShellExecute = false; coqtop.StartInfo.RedirectStandardError = false; coqtop.StartInfo.RedirectStandardInput = true; coqtop.StartInfo.RedirectStandardOutput = false; //if (System.Environment.OSVersion.Platform == PlatformID.Win32NT) //{// coqtop expects a dedicated read and write socket for each channel on Windows due to a bug in OCaml var coqtopMainR = new TcpListener(IPAddress.Loopback, 0); var coqtopMainW = new TcpListener(IPAddress.Loopback, 0); var coqtopControlR = new TcpListener(IPAddress.Loopback, 0); var coqtopControlW = new TcpListener(IPAddress.Loopback, 0); coqtopMainR.Start(1); coqtopMainW.Start(1); coqtopControlR.Start(1); coqtopControlW.Start(1); var coqtopMainAddr = ((IPEndPoint)coqtopMainR.LocalEndpoint).Address.ToString() + ":" + ((IPEndPoint)coqtopMainR.LocalEndpoint).Port + ":" + ((IPEndPoint)coqtopMainW.LocalEndpoint).Port; var coqtopControlAddr = ((IPEndPoint)coqtopControlR.LocalEndpoint).Address.ToString() + ":" + ((IPEndPoint)coqtopControlR.LocalEndpoint).Port + ":" + ((IPEndPoint)coqtopControlW.LocalEndpoint).Port; var arguments = String.Format("{0} -main-channel {1} -control-channel {2} ", ideSlave ? "-ideslave" : "", coqtopMainAddr, coqtopControlAddr) + String.Join(" ", args); coqtop.StartInfo.FileName = coqtopBin; coqtop.StartInfo.Arguments = arguments; coqtop.Start(); //var stderr = Console.OpenStandardError(); //coqtop.StandardError.BaseStream.CopyToAsync(stderr); //coqtop.StandardOutput.BaseStream.CopyToAsync(stderr); var connections = await Task.WhenAny(new Task<Tuple<Stream,Stream>>[] { AcceptCoqTopConnections(coqtopMainR, coqtopMainW, coqtopControlR, coqtopControlW) , Task.Run<Tuple<Stream,Stream>>(() => {System.Threading.Thread.Sleep(5000); return (Tuple<Stream,Stream>)null; }) }).Result; if (connections == null) { await Console.Error.WriteLineAsync("No response from coqtop."); System.Environment.Exit(-1); } coqtopMain = connections.Item1; coqtopControl = connections.Item2; coqtopMainR.Stop(); coqtopMainW.Stop(); coqtopControlR.Stop(); coqtopControlW.Stop(); //} else { // var coqtopMainRW = new TcpListener(IPAddress.Loopback, 0); // var coqtopControlRW = new TcpListener(IPAddress.Loopback, 0); // var coqtopMainAddr = ((IPEndPoint)coqtopMainRW.LocalEndpoint).Address.ToString() + ":" + ((IPEndPoint)coqtopMainRW.LocalEndpoint).Port; // var coqtopControlAddr = ((IPEndPoint)coqtopControlRW.LocalEndpoint).Address.ToString() + ":" + ((IPEndPoint)coqtopControlRW.LocalEndpoint).Port; // var arguments = String.Format("{0} -main-channel {1} -control-channel {2}", ideSlave ? "-ideslave" : "", coqtopMainAddr, coqtopControlAddr) // + String.Join(" ", args); // coqtopMainRW.Start(); // coqtopControlRW.Start(); // coqtop = Process.Start(coqtopBin, arguments); // var coqtopMainConnection = await coqtopMainRW.AcceptTcpClientAsync(); // var coqtopControlConnection = await coqtopControlRW.AcceptTcpClientAsync(); // coqtopMain = coqtopMainConnection.GetStream(); // coqtopControl = coqtopControlConnection.GetStream(); // coqtopMainRW.Stop(); // coqtopControlRW.Stop(); //} FileStream trace = null; if (traceFile != null) { try { File.Delete(traceFile); trace = new FileStream(traceFile, FileMode.Create); var header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n</root>"; var headerBytes = System.Text.Encoding.UTF8.GetBytes(header); trace.Write(headerBytes, 0, headerBytes.Length); trace.Position = header.IndexOf("\n</root>"); } catch (Exception) { trace = null; } } if (trace != null) { var closeXml = "\n</root>"; var closeXmlBytes = System.Text.Encoding.UTF8.GetBytes(closeXml); coqtopMain = new TraceStream(coqtopMain, System.Text.Encoding.UTF8.GetBytes("\n<!-- editor->coqtop main-channel: -->\n"), closeXmlBytes, trace); editorMain = new TraceStream(editorMain, System.Text.Encoding.UTF8.GetBytes("\n<!-- coqtop->editor main-channel: -->\n"), closeXmlBytes, trace); coqtopControl = new TraceStream(coqtopControl, System.Text.Encoding.UTF8.GetBytes("\n<!-- editor->coqtop control-channel: -->\n"), closeXmlBytes, trace); editorControl = new TraceStream(editorControl, System.Text.Encoding.UTF8.GetBytes("\n<!-- coqtop->editor control-channel: -->\n"), closeXmlBytes, trace); } var tasks = new List<Task>(); tasks.Add(coqtopMain.CopyToAsync(editorMain)); if (!ideSlave) tasks.Add(editorMain.CopyToAsync(coqtopMain)); else tasks.Add(copyStreamWithInterrupt(coqtop, editorMain, coqtopMain)); if (controlChannel != null) { tasks.Add(coqtopControl.CopyToAsync(editorControl)); tasks.Add(editorControl.CopyToAsync(coqtopControl)); } await Task.WhenAny(tasks); }