// 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; }