// Input.java /** * Input gates, a component of a logic circuit simulator. * This version is distributed as a solution to Machine Problem 5, Fall 2015. * @author Douglas W. Jones * @version MP5 */ import java.util.Arrays; import java.util.List; import java.util.LinkedList; import java.util.Scanner; class Input extends Gate { /** Input gates consume input from the outside world and present * it to the logic circuit. */ private Input() {} // prevent outsiders from using the initializer // the following empty list prevents any inputs from being connected private static List inputs = new LinkedList (); // the scanner from which input changes will be read private static Scanner sc = null; // does the first input event need to be scheduled? private static boolean needToSchedule = true; public static Gate scan( Scanner sc ) { /** This is the public initializer for input gates, * it reads the gate description using the given scanner * and it returns the handle for the newly initialized gate. */ // just once, setup to read inputs later if (Input.sc == null) { Input.sc = sc; // remember the scanner to use } // now do the scan as for any other gate Input g = new Input(); g.scan( sc, inputs ); if (g.name == null) g = null; return g; } public void checkInputs() { /** Override default CheckInputs method. Input gates have * no inputs from the logic circuit itself, so we use this * to finish the initialization, scheduling the first * input change event. */ // just once, no matter how many input gates. if (needToSchedule) { needToSchedule = false; if (sc.hasNextFloat()) { // there is a next input event Simulator.schedule( sc.nextFloat(), (float time) -> scanInput( time ) ); } } } public String toString() { /** Convert an input gate back to its textual description. */ return "gate input " + name + ' ' + delay; } public void inputChange( float t, int i, boolean v ) { /** Input gates have no inputs, so should never be called. */ } private static void scanInput( float t ) { /** Event service routine, scheduled each time an input change * should occur. Scan the name of the input gate and the * new input value, make those changes and then skip to the * next line of input and scan the time of the next input * change (if any). */ if (!sc.hasNext()) { Errors.warn( "" + t + " " + "?" + "-- input or stop not specified" ); } else { String name = sc.next(); Input i = null; // the named input boolean inputValue = false; // new value of the input if ("stop".equals(name)) { // not very graceful, but it does stop. System.exit( 0 ); } // make sure the name identifies an input gate Gate g = LogicCircuit.findGate( name ); if ((g == null) || !(g instanceof Input)) { Errors.warn( "" + t + " " + name + "?" + "-- not an input" ); i = null; } else { i = (Input) g; } // deal with the value of the input if (!sc.hasNextBoolean()) { Errors.warn( "" + t + " " + name + "?" + "-- input value not specified" ); } else { inputValue = sc.nextBoolean(); } if ((i != null) && (i.outputValue != inputValue)) { // something actually changes! i.outputValue = inputValue; i.outputChange( t, inputValue ); } // deal with end of input line final boolean iv = inputValue; // kluge SyntaxCheck.lineEnd( sc, () -> "" + t + " " + name + iv ); // see if there is a next input event to schedule if (sc.hasNextFloat()) { Simulator.schedule( sc.nextFloat(), (float time) -> scanInput( time ) ); } } } }