162 lines
3.7 KiB
Java
162 lines
3.7 KiB
Java
// PART OF THE MACHINE SIMULATION. DO NOT CHANGE.
|
|
|
|
package nachos.machine;
|
|
|
|
import nachos.security.*;
|
|
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* A text-based console that uses System.in and System.out.
|
|
*/
|
|
public class StandardConsole implements SerialConsole {
|
|
/**
|
|
* Allocate a new standard console.
|
|
*
|
|
* @param privilege encapsulates privileged access to the Nachos
|
|
* machine.
|
|
*/
|
|
public StandardConsole(Privilege privilege) {
|
|
System.out.print(" console");
|
|
|
|
this.privilege = privilege;
|
|
|
|
receiveInterrupt = new Runnable() {
|
|
public void run() { receiveInterrupt(); }
|
|
};
|
|
|
|
sendInterrupt = new Runnable() {
|
|
public void run() { sendInterrupt(); }
|
|
};
|
|
|
|
scheduleReceiveInterrupt();
|
|
}
|
|
|
|
public final void setInterruptHandlers(Runnable receiveInterruptHandler,
|
|
Runnable sendInterruptHandler) {
|
|
this.receiveInterruptHandler = receiveInterruptHandler;
|
|
this.sendInterruptHandler = sendInterruptHandler;
|
|
}
|
|
|
|
private void scheduleReceiveInterrupt() {
|
|
privilege.interrupt.schedule(Stats.ConsoleTime, "console read",
|
|
receiveInterrupt);
|
|
}
|
|
|
|
/**
|
|
* Attempt to read a byte from the object backing this console.
|
|
*
|
|
* @return the byte read, or -1 of no data is available.
|
|
*/
|
|
protected int in() {
|
|
try {
|
|
if (System.in.available() <= 0)
|
|
return -1;
|
|
|
|
return System.in.read();
|
|
}
|
|
catch (IOException e) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
private int translateCharacter(int c) {
|
|
// translate win32 0x0D 0x0A sequence to single newline
|
|
if (c == 0x0A && prevCarriageReturn) {
|
|
prevCarriageReturn = false;
|
|
return -1;
|
|
}
|
|
prevCarriageReturn = (c == 0x0D);
|
|
|
|
// invalid if non-ASCII
|
|
if (c >= 0x80)
|
|
return -1;
|
|
// backspace characters
|
|
else if (c == 0x04 || c == 0x08 || c == 0x19 || c == 0x1B || c == 0x7F)
|
|
return '\b';
|
|
// if normal ASCII range, nothing to do
|
|
else if (c >= 0x20)
|
|
return c;
|
|
// newline characters
|
|
else if (c == 0x0A || c == 0x0D)
|
|
return '\n';
|
|
// everything else is invalid
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
|
|
private void receiveInterrupt() {
|
|
Lib.assertTrue(incomingKey == -1);
|
|
|
|
incomingKey = translateCharacter(in());
|
|
if (incomingKey == -1) {
|
|
scheduleReceiveInterrupt();
|
|
}
|
|
else {
|
|
privilege.stats.numConsoleReads++;
|
|
|
|
if (receiveInterruptHandler != null)
|
|
receiveInterruptHandler.run();
|
|
}
|
|
}
|
|
|
|
public final int readByte() {
|
|
int key = incomingKey;
|
|
|
|
if (incomingKey != -1) {
|
|
incomingKey = -1;
|
|
scheduleReceiveInterrupt();
|
|
}
|
|
|
|
return key;
|
|
}
|
|
|
|
private void scheduleSendInterrupt() {
|
|
privilege.interrupt.schedule(Stats.ConsoleTime, "console write",
|
|
sendInterrupt);
|
|
}
|
|
|
|
/**
|
|
* Write a byte to the object backing this console.
|
|
*
|
|
* @param value the byte to write.
|
|
*/
|
|
protected void out(int value) {
|
|
System.out.write(value);
|
|
System.out.flush();
|
|
}
|
|
|
|
private void sendInterrupt() {
|
|
Lib.assertTrue(outgoingKey != -1);
|
|
|
|
out(outgoingKey);
|
|
outgoingKey = -1;
|
|
|
|
privilege.stats.numConsoleWrites++;
|
|
|
|
if (sendInterruptHandler != null)
|
|
sendInterruptHandler.run();
|
|
}
|
|
|
|
public final void writeByte(int value) {
|
|
if (outgoingKey == -1)
|
|
scheduleSendInterrupt();
|
|
|
|
outgoingKey = value&0xFF;
|
|
}
|
|
|
|
private Privilege privilege = null;
|
|
|
|
private Runnable receiveInterrupt;
|
|
private Runnable sendInterrupt;
|
|
|
|
private Runnable receiveInterruptHandler = null;
|
|
private Runnable sendInterruptHandler = null;
|
|
|
|
private int incomingKey = -1;
|
|
private int outgoingKey = -1;
|
|
|
|
private boolean prevCarriageReturn = false;
|
|
}
|