462 lines
15 KiB
Plaintext
462 lines
15 KiB
Plaintext
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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<ConsoleOutput> 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<ConsoleOutput>(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<ConsoleOutput> 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;
|
|
}
|
|
|
|
}
|
|
}
|