//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: ConsoleOutput.sg // // Note: Uses /dev/conout to display console output. // namespace Microsoft.Singularity.Io { using Microsoft.SingSharp; using Microsoft.Singularity; using Microsoft.Singularity.V1.Services; using Microsoft.Singularity.Channels; using Microsoft.Singularity.Directory; using System; using System.Text; using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; public sealed class ConsoleOutput : ITracked { private static TContainer consoleContainer; private struct PipeData : ITracked { public UnicodePipeContract.Imp channel; public void Dispose() { delete channel; } void ITracked.Acquire() {} void ITracked.Release() {} public void Expose() {} public void UnExpose() {} public UnicodePipeContract.Imp:READY Swap([Claims] UnicodePipeContract.Imp:READY newPipe) { expose (this) { UnicodePipeContract.Imp result = this.channel; this.channel = newPipe; return result; } } } // //private struct DeviceData : ITracked { // public ConsoleDeviceContract.Imp:Ready channel; // public void Dispose() // { // delete channel; // } // void ITracked.Acquire() {} // void ITracked.Release() {} // public void Expose() {} // public void UnExpose() {} //} // private char[]! in ExHeap side; private PipeData pipe; // //private DeviceData device; // private ConsoleOutput([Claims] UnicodePipeContract.Imp? pipe) { this.side = new[ExHeap] char [280]; this.pipe.channel = pipe; } private static UnicodePipeContract.Imp GetPipe() { UnicodePipeContract.Imp con = null; Endpoint* in ExHeap pipeep = Process.GetStartupEndpoint(1); if (pipeep != null) { con = pipeep as UnicodePipeContract.Imp; if (con == null) { Process.RetStartupEndpoint(1,pipeep); return null; } return con; } return null; } public static void Initialize() { // //ConsoleDeviceContract.Imp imp = null; // //imp = OpenConsole("/dev/video-text"); //if (imp == null) { // imp = OpenConsole("/dev/conout"); // if (imp == null) { // DebugStub.Print("Couldn't open console.\n"); // return; // } //} // UnicodePipeContract.Imp pipe = GetPipe(); ConsoleOutput co = new ConsoleOutput(pipe); consoleContainer = new TContainer(co); } public void Dispose() { this.pipe.Dispose(); // this.device.Dispose(); delete this.side; } void ITracked.Acquire() { //Tracing.Log(Tracing.Debug,"ConsoleOutput.Acquire"); } void ITracked.Release() { //Tracing.Log(Tracing.Debug,"ConsoleOutput.Release"); } void ITracked.Expose() { //Tracing.Log(Tracing.Debug,"ConsoleOutput.Expose"); } void ITracked.UnExpose() { //Tracing.Log(Tracing.Debug,"ConsoleOutput.UnExpose"); } public static void Finalize() { TContainer chandle = consoleContainer; consoleContainer = null; if (chandle == null) return; ConsoleOutput co = chandle.Acquire(); if (co != null) co.Dispose(); } // //private static ConsoleDeviceContract.Imp //OpenConsoleInternal(DirectoryServiceContract.Imp! nsImp, // [Claims] char[]! in ExHeap deviceName) //{ // ConsoleDeviceContract.Exp! exp; // ConsoleDeviceContract.Imp! imp; // ConsoleDeviceContract.NewChannel(out imp, out exp); // // nsImp.SendBind(deviceName, exp); // switch receive { // case nsImp.AckBind(): // return imp; // break; // case nsImp.NakBind(rejectImp, error): // delete rejectImp; // delete imp; // break; // case nsImp.ChannelClosed(): // throw new Exception("Channel closed during Console bind."); // delete imp; // break; // case nsImp.NakBindReparse(path, rest, linked, backExp): // assert linked == true; // assert rest == null; // delete backExp; // delete imp; // // return OpenConsoleInternal(nsImp, path); // break; // } // return null; //} // //private static ConsoleDeviceContract.Imp OpenConsole(string! devName) //{ // DirectoryServiceContract.Imp ns = DirectoryService.NewClientEndpoint(); // ConsoleDeviceContract.Imp imp = // OpenConsoleInternal(ns, Bitter.FromString2(devName)); // delete ns; // // if (imp != null) { // switch receive { // case imp.Success(): // break; // case imp.ContractNotSupported(): // throw new Exception("ConsoleOutput: ContractNotSupported"); // break; // case imp.ChannelClosed(): // throw new Exception("ConsoleOutput: ChannelClosed"); // break; // } // } // return imp; //} // //public static void Clear() //{ // if (consoleContainer == null) return; // // ConsoleOutput co = consoleContainer.Acquire(); // // expose (co) { // ConsoleDeviceContract.Imp ep = co.device.channel; // if (ep != null) { // ep.SendClear(); // switch receive { // case ep.AckClear(): // break; // case ep.NakClear(): // break; // case ep.ChannelClosed(): // delete ep; // co.device.channel = null; // break; // } // } // } // consoleContainer.Release(co); //} // //public static void CursorFlash() //{ // if (consoleContainer == null) return; // // ConsoleOutput co = consoleContainer.Acquire(); // // expose (co) { // ConsoleDeviceContract.Imp ep = co.device.channel; // if (ep != null) { // ep.SendCursorFlash(); // switch receive { // case ep.AckCursorFlash(): // break; // case ep.NakCursorFlash(): // break; // case ep.ChannelClosed(): // delete ep; // co.device.channel = null; // break; // } // } // } // consoleContainer.Release(co); //} // //public static void CursorHide() //{ // if (consoleContainer == null) return; // // ConsoleOutput co = consoleContainer.Acquire(); // // expose (co) { // ConsoleDeviceContract.Imp ep = co.device.channel; // if (ep != null) { // ep.SendCursorHide(); // switch receive { // case ep.AckCursorHide(): // break; // case ep.NakCursorHide(): // break; // case ep.ChannelClosed(): // delete ep; // co.device.channel = null; // break; // } // } // } // consoleContainer.Release(co); //} // //public static void CursorShow() //{ // if (consoleContainer == null) return; // // ConsoleOutput co = consoleContainer.Acquire(); // // expose (co) { // ConsoleDeviceContract.Imp ep = co.device.channel; // if (ep != null) { // ep.SendCursorShow(); // switch receive { // case ep.AckCursorShow(): // break; // case ep.NakCursorShow(): // break; // case ep.ChannelClosed(): // delete ep; // co.device.channel = null; // break; // } // } // } // consoleContainer.Release(co); //} // public static char[]! in ExHeap Write([Claims] char[]! in ExHeap buffer, int index, int count) { if (consoleContainer == null) return buffer; ConsoleOutput co = consoleContainer.Acquire(); try { expose (co) { if (co.pipe.channel != null) { return Write(buffer, index, count, ref co.pipe); } else { return buffer; } } } finally { consoleContainer.Release(co); } } // //private static char[]! in ExHeap Write([Claims] char[]! in ExHeap buffer, // int index, int count, // ref DeviceData device) //{ // expose (device) { // ConsoleDeviceContract.Imp channel = device.channel; // if (channel != null) { // channel.SendWrite(buffer, index, count); // switch receive { // case channel.AckWrite(localside): // return localside; // // case channel.NakWrite(localside): // return localside; // // case channel.ChannelClosed(): // delete channel; // device.channel = null; // return new[ExHeap] char[0]; // } // } // else { // return buffer; // } // } //} // private static char[]! in ExHeap Write([Claims] char[]! in ExHeap buffer, int index, int count, ref PipeData pipe) { expose (pipe) { UnicodePipeContract.Imp channel = pipe.channel; if (channel != null) { // char[]! in ExHeap buffer=Bitter.FromString2(value); channel.SendWrite(buffer, index, count); switch receive { case channel.AckWrite(i_buffer): return i_buffer; case channel.ChannelClosed(): delete channel; pipe.channel = null; return new[ExHeap] char[0]; case unsatisfiable: DebugStub.Break(); throw new Exception("Pipe unsatisfiable "); } } else { return buffer; } } } public static void Write(char[]! buffer, int index, int count) { if (consoleContainer == null) return; ConsoleOutput co = consoleContainer.Acquire(); expose (co) { char[] in ExHeap side = co.side; if (side.Length < count) { delete side; co.side = side = new[ExHeap] char [count]; } for (int i = 0; i < count; i++) { side[i] = buffer[index + i]; } if (co.pipe.channel != null) { co.side = Write(side, index, count, ref co.pipe); } // //else { // co.side = Write(side, index, count, ref co.device); //} // } consoleContainer.Release(co); } public static void Write(String! value) { if (consoleContainer == null) return; ConsoleOutput co = consoleContainer.Acquire(); expose (co) { char[] in ExHeap side = co.side; if (side.Length < value.Length) { delete side; co.side = side = new[ExHeap] char [value.Length]; } for (int i = 0; i < value.Length; i++) { side[i] = value[i]; } if (co.pipe.channel != null) { co.side = Write(side, 0, value.Length, ref co.pipe); } // //else { // co.side = Write(side, 0, value.Length, ref co.device); //} // } consoleContainer.Release(co); return; } public static UnicodePipeContract.Imp:READY Swap([Claims] UnicodePipeContract.Imp:READY newOutput) { if (consoleContainer == null) { delete newOutput; return null; } ConsoleOutput co = consoleContainer.Acquire(); UnicodePipeContract.Imp result; expose(co) { result = co.pipe.Swap(newOutput); } consoleContainer.Release(co); return result; } } }