#!/bin/sh # This is a shell archive (produced by GNU sharutils 4.15.2). # To extract the files from this archive, save it to some FILE, remove # everything before the '#!/bin/sh' line above, then type 'sh FILE'. # lock_dir=_sh30632 # Made on 2019-04-19 10:26 CDT by . # Source directory was '/mnt/nfs/clasnetappvm/fs3/dwjones/mp5'. # # Existing files will *not* be overwritten, unless '-c' is specified. # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 835 -rw------- README # 1434 -rwx------ tests # 157 -rw------- classes # 1222 -rw------- Errors.java # 4689 -rw------- Gate.java # 2370 -rw------- InputCountGate.java # 2101 -rw------- InputGate.java # 3007 -rw------- MP5.java # 1105 -rw------- OutputGate.java # 3555 -rw------- ScanSupport.java # 1748 -rw------- Simulation.java # 1131 -rw------- ThresholdGate.java # 3033 -rw------- Wire.java # 949 -rw------- XorGate.java # MD5SUM=${MD5SUM-md5sum} f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'` test -n "${f}" && md5check=true || md5check=false ${md5check} || \ echo 'Note: not verifying md5sums. Consider installing GNU coreutils.' if test "X$1" = "X-c" then keep_file='' else keep_file=true fi echo=echo save_IFS="${IFS}" IFS="${IFS}:" gettext_dir= locale_dir= set_echo=false for dir in $PATH do if test -f $dir/gettext \ && ($dir/gettext --version >/dev/null 2>&1) then case `$dir/gettext --version 2>&1 | sed 1q` in *GNU*) gettext_dir=$dir set_echo=true break ;; esac fi done if ${set_echo} then set_echo=false for dir in $PATH do if test -f $dir/shar \ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1) then locale_dir=`$dir/shar --print-text-domain-dir` set_echo=true break fi done if ${set_echo} then TEXTDOMAINDIR=$locale_dir export TEXTDOMAINDIR TEXTDOMAIN=sharutils export TEXTDOMAIN echo="$gettext_dir/gettext -s" fi fi IFS="$save_IFS" if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null then if (echo -n test; echo 1,2,3) | grep n >/dev/null then shar_n= shar_c=' ' else shar_n=-n shar_c= ; fi else shar_n= shar_c='\c' ; fi f=shar-touch.$$ st1=200112312359.59 st2=123123592001.59 st2tr=123123592001.5 # old SysV 14-char limit st3=1231235901 if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \ test ! -f ${st1} && test -f ${f}; then shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"' elif touch -am ${st2} ${f} >/dev/null 2>&1 && \ test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"' elif touch -am ${st3} ${f} >/dev/null 2>&1 && \ test ! -f ${st3} && test -f ${f}; then shar_touch='touch -am $3$4$5$6$2 "$8"' else shar_touch=: echo ${echo} 'WARNING: not restoring timestamps. Consider getting and installing GNU '\''touch'\'', distributed in GNU coreutils...' echo fi rm -f ${st1} ${st2} ${st2tr} ${st3} ${f} # if test ! -d ${lock_dir} ; then : else ${echo} "lock directory ${lock_dir} exists" exit 1 fi if mkdir ${lock_dir} then ${echo} "x - created lock directory ${lock_dir}." else ${echo} "x - failed to create lock directory ${lock_dir}." exit 1 fi # ============= README ============== if test -n "${keep_file}" && test -f 'README' then ${echo} "x - SKIPPING README (file already exists)" else ${echo} "x - extracting README (text)" sed 's/^X//' << 'SHAR_EOF' > 'README' && README version 2019-04-19 author Douglas W. Jones X Posted solution to MP5 consisting of the following files. These files make up a digital logic simulator. X README -- this file X classes -- the @ file for the javac command X Errors.java -- utility package ScanSupport.java -- utility package Simulation.java -- utility package X Wire.java -- wires that connect gates Gate.java -- gates are connected by wires InputCountGate.java -- a subclass of Gate ThresholdGate.java -- a subclass of InputCountGate XXorGate.java -- a subclass of InputCountGate InputGate.java -- a subclass of Gate OutputGate.java -- a subclass of Gate X MP5.java -- the main program X tests -- an executable test script X To build the simulator, use the shell command javac @classes To run the tests, make the file tests executable and then run the script SHAR_EOF (set 20 19 04 19 10 26 30 'README' eval "${shar_touch}") && \ chmod 0600 'README' if test $? -ne 0 then ${echo} "restore of README failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'README': 'MD5 check failed' ) << \SHAR_EOF 2e86fae00c2369724c677d30e95a01d2 README SHAR_EOF else test `LC_ALL=C wc -c < 'README'` -ne 835 && \ ${echo} "restoration warning: size of 'README' is not 835" fi fi # ============= tests ============== if test -n "${keep_file}" && test -f 'tests' then ${echo} "x - SKIPPING tests (file already exists)" else ${echo} "x - extracting tests (text)" sed 's/^X//' << 'SHAR_EOF' > 'tests' && #!/bin/sh # tests -- test shell script for testing mp5 (must be executable) # Author: Douglas Jones # Version: 2019-04-14 X echo echo "test xor gate example with suppressed short output pulse" cat > testdata << EOF gate a input 0 1.0 1 gate b xor 0.1 wire a 1.0 b 1.09 b EOF java MP5 testdata rm -f testdata read -p "Press Enter to continue" X echo echo "test xor gate example with unsuppressed output pulse" cat > testdata << EOF gate a input 0 1.0 1 gate b xor 0.1 wire a 1.0 b 1.11 b EOF java MP5 testdata rm -f testdata read -p "Press Enter to continue" X echo echo "test threshold gate 2 suppressed transitions" cat > testdata << EOF gate a input 0 0.1 2 gate b threshold 1 0.11 wire a 1.0 b EOF java MP5 testdata rm -f testdata read -p "Press Enter to continue" X echo echo "test threshold gate 3 transitions (one from 0->1 gets through)" cat > testdata << EOF gate a input 0 0.05 3 gate b threshold 1 0.11 wire a 1.0 b EOF java MP5 testdata rm -f testdata read -p "Press Enter to continue" X echo echo "test threshold gate 4 suppressed transitions" cat > testdata << EOF gate a input 0 0.0333 4 gate b threshold 1 0.11 wire a 1.0 b EOF java MP5 testdata rm -f testdata read -p "Press Enter to continue" X echo echo "test threshold gate 5 transitions (one from 0-> gets through)" cat > testdata << EOF gate a input 0 0.025 5 gate b threshold 1 0.11 wire a 1.0 b EOF java MP5 testdata rm -f testdata read -p "Press Enter to continue" X SHAR_EOF (set 20 19 04 14 18 26 49 'tests' eval "${shar_touch}") && \ chmod 0700 'tests' if test $? -ne 0 then ${echo} "restore of tests failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'tests': 'MD5 check failed' ) << \SHAR_EOF 7356d2b0e955a063ebd64cef3474b944 tests SHAR_EOF else test `LC_ALL=C wc -c < 'tests'` -ne 1434 && \ ${echo} "restoration warning: size of 'tests' is not 1434" fi fi # ============= classes ============== if test -n "${keep_file}" && test -f 'classes' then ${echo} "x - SKIPPING classes (file already exists)" else ${echo} "x - extracting classes (text)" sed 's/^X//' << 'SHAR_EOF' > 'classes' && Errors.java ScanSupport.java Simulation.java Gate.java InputCountGate.java XXorGate.java ThresholdGate.java InputGate.java OutputGate.java Wire.java MP5.java SHAR_EOF (set 20 19 04 14 18 12 58 'classes' eval "${shar_touch}") && \ chmod 0600 'classes' if test $? -ne 0 then ${echo} "restore of classes failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'classes': 'MD5 check failed' ) << \SHAR_EOF 7cea55cc88e56af9e50438b8f20a7a23 classes SHAR_EOF else test `LC_ALL=C wc -c < 'classes'` -ne 157 && \ ${echo} "restoration warning: size of 'classes' is not 157" fi fi # ============= Errors.java ============== if test -n "${keep_file}" && test -f 'Errors.java' then ${echo} "x - SKIPPING Errors.java (file already exists)" else ${echo} "x - extracting Errors.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'Errors.java' && // errors.java X /** Error reporting package X * Provide a standard prefix and behavior for error reporting X * @author Douglas W. Jones X * @version 2019-03-03 X * Lifted from RoadNetwork.java version 2019-03-01 X * augmented to count errors X */ public class Errors { X // prefix string for all error messages X private static String prefix = "??: "; X X // how many warnings have been issued (see warnings() method) X private static int warnCount = 0; X X /** Set prefix on error reports, should be done before any error reports X * @arg p the prefix on any error messages X */ X public static void setPrefix( String p ) { X prefix = p; X } X X /** Report nonfatal errors, output a message and return X * @arg m the message to output X */ X public static void warn( String m ) { X System.err.println( prefix + ": " + m ); X warnCount = warnCount + 1; X } X X /** Report the number of warnings that have been issued X * @returns the count X */ X public static int warnings() { X return warnCount; X } X X /** Report fatal errors, output a message and die X * @arg m the message to output X */ X public static void fatal( String m ) { X warn( m ); X System.exit( 1 ); X } } SHAR_EOF (set 20 19 04 12 10 02 22 'Errors.java' eval "${shar_touch}") && \ chmod 0600 'Errors.java' if test $? -ne 0 then ${echo} "restore of Errors.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'Errors.java': 'MD5 check failed' ) << \SHAR_EOF edeeeecf3d1efed70626316955d2be78 Errors.java SHAR_EOF else test `LC_ALL=C wc -c < 'Errors.java'` -ne 1222 && \ ${echo} "restoration warning: size of 'Errors.java' is not 1222" fi fi # ============= Gate.java ============== if test -n "${keep_file}" && test -f 'Gate.java' then ${echo} "x - SKIPPING Gate.java (file already exists)" else ${echo} "x - extracting Gate.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'Gate.java' && // Gate.java X import java.util.Iterator; import java.util.Scanner; import java.util.List; import java.util.LinkedList; X /** Subclasses of Gates are joined by Wires X * @author Douglas Jones X * @version 2019-04-03 X * Lightly edited from RoadNetwork.java class Intersection version 2019-02-15 X * then altered to become an abstract class with subclasses and a factory X * @see Wire X * @see InputCountGate X * @see InputGate X * @see OutputGate X */ public abstract class Gate { X X // a list of all of the gates in the universe X private static final List allGates = new LinkedList (); X X /** Allow outsiders to iterate over all the gates X * @returns an Iterator allowing access to gates X */ X public static Iterator iterator() { X return allGates.iterator(); X } X X /** look up a gate by name X * @param n the name of the gate, possibly null (matches nothing) X * @returns the Gate with that name, or null if no match X */ X public static Gate findGate( String n ) { X // stupid code, a linear search, but does it matter? X for (Gate g: allGates) { X if (g.name.equals( n )) return g; X } X return null; X } X X // attributes of individual gates X X /** The name of this gate X */ X public final String name; // the gate's name or null if broken X X // where the outputs from this gate go X protected final LinkedList outgoing = new LinkedList (); X X // where the inputs to this gate come from X protected int inCount = 0; // we only seem to need a count of inputs X X /** constructor, used only from within subclasses X * @param n the name of the new gate X * this is needed in order to make the name final X */ X protected Gate( String n ) { X name = n; X } X X /** build a new Gate and add it to the list of gates X * @param sc the scanner used to get the attributes of this gate X * @returns a new gate or null if it cannot be constructed X * When called, the keyword "gate" has already been scanned, X * so we are ready to scan the additional attributes, if any. X */ X public static void make( Scanner sc ) { X // first worry about the gate name X final String name X = ScanSupport.scanName( sc, () -> "Gate has missing name" ); X if (name == null) { X ScanSupport.finishLine( X sc, () -> "gate: followed by" X ); X return; // no gate added to allGates X } X if (findGate( name ) != null) { X Errors.warn( "gate " + name + ": name reused" ); X ScanSupport.finishLine( X sc, () -> "gate " + name + ": followed by" X ); X return; // no gate added to allGates X } X X // get the gate kind X final String kind = ScanSupport.scanName( X sc, () -> "Gate " + name + ": kind missing" X ); X if (kind == null) { X ScanSupport.finishLine( X sc, () -> "gate " + name + ": followed by" X ); X return; // no gate added to allGates X } X X // construct the right kind of gate X if ("xor".equals( kind )) { X allGates.add( new XorGate( sc, name ) ); X } else if ("threshold".equals( kind )) { X allGates.add( new ThresholdGate( sc, name ) ); X } else if ("input".equals( kind )) { X allGates.add( new InputGate( sc, name ) ); X } else if ("output".equals( kind )) { X allGates.add( new OutputGate( sc, name ) ); X } else { X Errors.warn( "gate " + name + " " + kind + ": kind unknown" ); X ScanSupport.finishLine( X sc, () -> "gate " + name + " " + kind + ": followed by" X ); X } X } X X /** Every subclass of gate offers a sanity check X * It should call Errors.warn() for each failure it detects X */ X public abstract void sanityCheck(); X X /** connect a wire as an input to this gate X * @arg w the wire X */ X public void connectTo( Wire w ) { X inCount = inCount + 1; // it seems that all we need to do is count them X } X X /** connect a wire as an output from this gate X * @arg w the wire X */ X public void connectFrom( Wire w ) { X outgoing.add( w ); X } X X public String toString() { X // note, we have a guarantee that name is not null, so X return "Gate " + name; X } X X // Simulation methods X X /** tell the gate that one of its inputs has changed X * @param now the time at which the change occurs X * @param value the new value of that input X * each subclass must implement this method X */ X public abstract void inputChange( float now, int value ); X X // actually change the output X protected void outputChange( float now, int value ) { X final int comp = 1 - value; // logical complement of the value X System.out.println( "time "+ now +" "+ comp +"->"+ value +" "+ this ); X for (Wire w: outgoing) w.inputChange( now, value ); X } } SHAR_EOF (set 20 19 04 12 10 02 32 'Gate.java' eval "${shar_touch}") && \ chmod 0600 'Gate.java' if test $? -ne 0 then ${echo} "restore of Gate.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'Gate.java': 'MD5 check failed' ) << \SHAR_EOF a48188b8bc09f48d9c65fa330ac645a8 Gate.java SHAR_EOF else test `LC_ALL=C wc -c < 'Gate.java'` -ne 4689 && \ ${echo} "restoration warning: size of 'Gate.java' is not 4689" fi fi # ============= InputCountGate.java ============== if test -n "${keep_file}" && test -f 'InputCountGate.java' then ${echo} "x - SKIPPING InputCountGate.java (file already exists)" else ${echo} "x - extracting InputCountGate.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'InputCountGate.java' && // InputCountGate.java X import java.util.Scanner; X /** Any kind of gate that needs to track its input count X * @author Douglas Jones X * @version 2019-04-03 X * @see Gate X * @see XorGate X * @see ThresholdGate X */ public abstract class InputCountGate extends Gate { X X private int inputCount = 0; // number of inputs that are currently one X private int oldOutput = 0; // the previous output (set by input changes) X private int newOutput = 0; // the previous output (set at output change) X protected float delay = Float.NaN; // default value allows this in err msgs X X /** constructor, used only from within subclasses X * @param n the name of the new gate X * this is a pass-through to Gate X */ X protected InputCountGate( String n ) { X super( n ); X } X X /** tell the gate that one of its inputs has changed X * @param now the time at which the change occurs X * @param value the new value of that input X * each subclass must implement this method X */ X public void inputChange( float now, int value ) { X if (value == 1) { // it change to 1 X inputCount = inputCount + 1; X } else { // it changed to 0 X inputCount = inputCount - 1; X } X X // the following code suppresses changes from 1 to 1 or 0 to 0 X // by gate input changes; eg (0 or 0) to (0 or 1) leaves output 0 X int myOutput = logicRule( inputCount ); X if (myOutput != oldOutput) { // the output changes X Simulation.schedule( X now + delay, (float t) -> this.outputChange( t, myOutput ) X ); X oldOutput = myOutput; X } X } X X // override the default output change event, needed to suppress short pulses X protected void outputChange( float now, int value ) { X X // first, suppress changes away from the value most recently set X // set by the input. This prevents short pulses from getting through. X if (value != oldOutput) return; X X // second, suppress changes from 1 to 1 or 0 to 0 X // caused, eg, by events that return the value to the approved value. X if (value == newOutput) return; X X // finally, we know that this output change should occur X super.outputChange( now, value ); X newOutput = value; X } X X /** compute the gate's logical value X * @param count the number of ones on the input X * each subclass must implement this method X */ X public abstract int logicRule( int count ); } SHAR_EOF (set 20 19 04 14 17 05 29 'InputCountGate.java' eval "${shar_touch}") && \ chmod 0600 'InputCountGate.java' if test $? -ne 0 then ${echo} "restore of InputCountGate.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'InputCountGate.java': 'MD5 check failed' ) << \SHAR_EOF 62422b3c3e023f64b95bcce91090725b InputCountGate.java SHAR_EOF else test `LC_ALL=C wc -c < 'InputCountGate.java'` -ne 2370 && \ ${echo} "restoration warning: size of 'InputCountGate.java' is not 2370" fi fi # ============= InputGate.java ============== if test -n "${keep_file}" && test -f 'InputGate.java' then ${echo} "x - SKIPPING InputGate.java (file already exists)" else ${echo} "x - extracting InputGate.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'InputGate.java' && // InputGate.java X import java.util.Scanner; X /** input gates will provide input to the simulation X * @author Douglas Jones X * @version 2019-04-03 X * @see Gate X */ public class InputGate extends Gate { X private float delay = Float.NaN; // default values allow this in err msgs X private int initial = 0; X private int changeCount = 0; X X public InputGate( Scanner sc, String name ){ X super( name ); X initial = ScanSupport.scanPositiveInt( sc, () -> this.toString() ); X delay = ScanSupport.scanPositiveFloat( sc, () -> this.toString() ); X changeCount = ScanSupport.scanPositiveInt( sc, () -> this.toString() ); X if (initial > 1) Errors.warn( this + ": initial value > 1" ); X ScanSupport.finishLine( sc, () -> this + " is followed by" ); X } X X /** Every subclass of gate offers a sanity check X * Calls Errors.warn() for any gates where input count > 0 X */ X public void sanityCheck() { X if (inCount != 0) { X Errors.warn( this.toString() + ": has unexpected input wires" ); X } X X // launch the simulation! X if (initial == 1) this.outputChange( 0.0F, 1 ); X if (changeCount > 0) Simulation.schedule( X delay, (float t) -> this.nextChange( t, 1 - initial ) X ); X } X X public String toString() { X return super.toString() + " input " X + initial + " " + delay + " " + changeCount; X } X X // Simulation methods X X /** tell this input gate that one of its inputs has changed X * @param now the time at which the change occurs X * @param value the new value of that input X * The sanity check guarantees that this will never be called X */ X public void inputChange( float now, int value ) { X Errors.warn( this.toString() + ": Impossible input change" ); X } X X // Output change process for sequence of inputs X private void nextChange( float now, int value ) { X // first change the output X this.outputChange( now, value ); X X // then schedule the next change, if any X changeCount = changeCount - 1; X if (changeCount > 0) Simulation.schedule( X now + delay, (float t) -> this.nextChange( t, 1 - value ) X ); X } } SHAR_EOF (set 20 19 04 12 10 02 50 'InputGate.java' eval "${shar_touch}") && \ chmod 0600 'InputGate.java' if test $? -ne 0 then ${echo} "restore of InputGate.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'InputGate.java': 'MD5 check failed' ) << \SHAR_EOF 447962fc015f2954e4fb0cf48ad1ab40 InputGate.java SHAR_EOF else test `LC_ALL=C wc -c < 'InputGate.java'` -ne 2101 && \ ${echo} "restoration warning: size of 'InputGate.java' is not 2101" fi fi # ============= MP5.java ============== if test -n "${keep_file}" && test -f 'MP5.java' then ${echo} "x - SKIPPING MP5.java (file already exists)" else ${echo} "x - extracting MP5.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'MP5.java' && // MP4.java X import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.Iterator; import java.util.List; import java.util.LinkedList; import java.util.Scanner; X /** Main program X * @author Douglas Jones X * @version 2019-04-03 X * Originated as RoadNetwork.java class RoadNetwork version 2019-02-13, X * With buildLogic code heavily edited from buildNetwork, X * and with the lists of gates and wires moved into those classes. X * @see Gate X * @see Wire X */ public class MP5 { X X // build the logic circuit by scanning a source file X private static void buildLogic( Scanner sc ) { X X while (sc.hasNext()) { X // pick off the next part of the logic circuit description X String command = sc.next(); X if ("--".equals( command )) { X sc.nextLine(); // discard remainder of comment line X // BUG: bad way to skip comments, requires whitespace post -- X } else if ("gate".equals( command )) { X Gate.make( sc ); X } else if ("wire".equals( command )) { X // because of multiple destinations, must get the source here X final String srcName X = ScanSupport.scanName( sc, () -> "Wire: has no source" ); X if (srcName != null) { X final Gate source = Gate.findGate( srcName ); X if (source != null) { X // now build at least one wire and possibly more X Wire.make( sc, source ); X while (sc.hasNextFloat()) { X Wire.make( sc, source ); X } X ScanSupport.finishLine( X sc, () -> "Wire " + srcName + ": followed by" X ); X } else { X Errors.warn( "Wire " + srcName + ": undefined source" ); X ScanSupport.finishLine( X sc, () -> "Wire " + srcName + ": followed by" X ); X } X } else { X // error message already done, but X ScanSupport.finishLine( sc, () -> "Wire: followed by" ); X } X } else { X Errors.warn( "invalid command " + command ); X ScanSupport.finishLine( sc, () -> command + ": followed by" ); X } X } X } X X // perform sanity checks on all gates X private static void sanityChecks() { X for (Iterator i = Gate.iterator(); i.hasNext();) { X i.next().sanityCheck(); X } X } X X // print out the entire logic circuit X private static void printLogic() { X for (Iterator i = Gate.iterator(); i.hasNext();) { X System.out.println( i.next() ); X } X for (Iterator i = Wire.iterator(); i.hasNext();) { X System.out.println( i.next() ); X } X } X X public static void main( String[] args ) { X Errors.setPrefix( "MP3" ); X if (args.length < 1) { X Errors.fatal( "missing argument" ); X } X if (args.length > 1) { X Errors.warn( "extra arguments" ); X } X try { X // args[0] is the text file holding the logic circuit description X buildLogic( new Scanner( new FileInputStream( args[0] ) ) ); X sanityChecks(); X printLogic(); // something testable! X if (Errors.warnings() == 0) Simulation.run(); X } catch( FileNotFoundException e ) { X Errors.fatal( "can't open file" ); X } X if (Errors.warnings() > 0) System.exit( 1 ); // exit failure X } } SHAR_EOF (set 20 19 04 14 18 13 34 'MP5.java' eval "${shar_touch}") && \ chmod 0600 'MP5.java' if test $? -ne 0 then ${echo} "restore of MP5.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'MP5.java': 'MD5 check failed' ) << \SHAR_EOF e074308eb3469c03df35264c6054ab1e MP5.java SHAR_EOF else test `LC_ALL=C wc -c < 'MP5.java'` -ne 3007 && \ ${echo} "restoration warning: size of 'MP5.java' is not 3007" fi fi # ============= OutputGate.java ============== if test -n "${keep_file}" && test -f 'OutputGate.java' then ${echo} "x - SKIPPING OutputGate.java (file already exists)" else ${echo} "x - extracting OutputGate.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'OutputGate.java' && // OutputGate.java X import java.util.Scanner; X /** output gates will provide output from the simulation X * @author Douglas Jones X * @version 2019-04-03 X * @see Gate X */ public class OutputGate extends Gate { X X public OutputGate( Scanner sc, String name ){ X super( name ); X X ScanSupport.finishLine( sc, () -> this + " is followed by" ); X } X X /** Every subclass of gate offers a sanity check X * Calls Errors.warn() for any gates where input count > 0 X */ X public void sanityCheck() { X if (this.outgoing.peek() != null) { // something in the outgoing list X Errors.warn( this.toString() + ": has outgoing wires" ); X } X } X X public String toString() { X return super.toString() + " output"; X } X X // Simulation methods X X /** tell this output gate that one of its inputs has changed X * @param now the time at which the change occurs X * @param value the new value of that input X */ X public void inputChange( float now, int value ) { X // due to the specs for MP4, nothing needs to be done here X // later spec changes might put all the output here X } } SHAR_EOF (set 20 19 04 12 10 03 10 'OutputGate.java' eval "${shar_touch}") && \ chmod 0600 'OutputGate.java' if test $? -ne 0 then ${echo} "restore of OutputGate.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'OutputGate.java': 'MD5 check failed' ) << \SHAR_EOF 20eca3e95869d4d0300ef3ec89839605 OutputGate.java SHAR_EOF else test `LC_ALL=C wc -c < 'OutputGate.java'` -ne 1105 && \ ${echo} "restoration warning: size of 'OutputGate.java' is not 1105" fi fi # ============= ScanSupport.java ============== if test -n "${keep_file}" && test -f 'ScanSupport.java' then ${echo} "x - SKIPPING ScanSupport.java (file already exists)" else ${echo} "x - extracting ScanSupport.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'ScanSupport.java' && // ScanSupport.java X import java.util.regex.Pattern; import java.util.Scanner; X /** Support package for application dependent extensions to class Scanner X * @author Douglas Jones X * @version 2019-03-04 X * Based on RoadNetwork.java version 2019-03-01 X * augmented to use lambda expressions for error messages X * and to scan floating point numbers X * @see Errors X * If class Scanner wasn't final, this could be a subclass X */ public class ScanSupport { X X // patterns used in methods below X private static final Pattern name = // match one legal name X Pattern.compile( "[A-Za-z]*[A-Za-z0-9]" ); X private static final Pattern blanks = // match any number of blanks X Pattern.compile( "[ \t]*" ); X private static final Pattern theRest = // match text up to newline X Pattern.compile( "[^\n]*" ); X X /** Support interface for passing deferred computation of message text X * set up so that lambda notation can be used X */ X public static interface MessageCarrier { X String content(); X } X X /** Scan and return one name, if available X * @arg sc the scanner to read from X * @arg msg the message to output if there is no name X * @returns the name, or null if there is no name X * Typically called as ScanSupport.scanName( sc, () -> string + expr ) X */ X public static String scanName( Scanner sc, MessageCarrier msg ) { X if (sc.hasNext( name )) return sc.next(name); X Errors.warn( msg.content() ); X return null; X } X X /** Scan and return one nonnegative int, if available X * @arg sc the scanner to read from X * @arg msg the message prefix to output if there is no int X * @returns the value, or 0 if there is no number X * Typically called as ...scanPositiveInt( sc, () -> string + expr ) X */ X public static int scanPositiveInt( Scanner sc, MessageCarrier msg ) { X if (sc.hasNextInt()) { X int value = sc.nextInt(); X if (value >= 0) return value; X Errors.warn( msg.content() + " " + value + ": must be positive" ); X } X Errors.warn( msg.content() + ": integer value expected" ); X return 0; X } X X /** Scan and return one nonnegative float, if available X * @arg sc the scanner to read from X * @arg msg the message prefix to output if there is no float X * @returns the value, or NaN if there is no number X * Typically called as ...scanPositiveFloat( sc, () -> string + expr ) X */ X public static float scanPositiveFloat( Scanner sc, MessageCarrier msg ) { X if (sc.hasNextFloat()) { X float value = sc.nextFloat(); X if (value >= 0.0F) return value; X Errors.warn( msg.content() + " " + value + ": must be positive" ); X } X Errors.warn( msg.content() + ": float value expected" ); X return Float.NaN; X } X X /** Skip the rest of this line, and complain if it's nonblank noncomment X * @arg sc the scanner to read from X * @arg msg the object that computes the message to output if needed X * Typically called as ScanSupport.finishLine( sc, () -> string + expr ) X * This code improves on the posted solution for homework 6, problem 2 X */ X public static void finishLine( Scanner sc, MessageCarrier msg ) { X // first skip trailing blanks X sc.skip( blanks ); X X // then get everything that remains on this line X sc.skip( theRest ); X final String remainder = sc.match().group( 0 ); X X // then see if it all makes sense X if ("".equals( remainder )) return; X if (remainder.startsWith ("--")) return; X Errors.warn( msg.content() + ": " + remainder ); X } } SHAR_EOF (set 20 19 04 12 10 03 22 'ScanSupport.java' eval "${shar_touch}") && \ chmod 0600 'ScanSupport.java' if test $? -ne 0 then ${echo} "restore of ScanSupport.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ScanSupport.java': 'MD5 check failed' ) << \SHAR_EOF 301237e5016a1eb8828af3be94444114 ScanSupport.java SHAR_EOF else test `LC_ALL=C wc -c < 'ScanSupport.java'` -ne 3555 && \ ${echo} "restoration warning: size of 'ScanSupport.java' is not 3555" fi fi # ============= Simulation.java ============== if test -n "${keep_file}" && test -f 'Simulation.java' then ${echo} "x - SKIPPING Simulation.java (file already exists)" else ${echo} "x - extracting Simulation.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'Simulation.java' && // Simulation.java X import java.util.PriorityQueue; X /** Simulation framework X * @author Douglas W. Jones X * @version 2019-03-08 X */ public class Simulation { X X // this interface is so we can schedule events with lambda expressions X public interface Action { X void trigger( float time ); X } X X // Events are scheduled on the event set X private static class Event { X final float time; // the simulated time of the event X final Action act; // the action to trigger at that time X X Event( float t, Action a ) { X time = t; X act = a; X } X } X X // the central organizing data structure of the simulation X private static final PriorityQueue eventSet X = new PriorityQueue ( X ( Event e1, Event e2 ) -> Float.compare( e1.time, e2.time ) X ); X X /** schedule a new event X * @param t the time at which the event should occur X * @param a the Action that should occur at that time X * A typical call will look like this X * Simulation.schedule( someTime, (float t)->codeToRunAt( t ) ); X * That is, the Action will be constructed by a lambda expression X */ X public static void schedule( float t, Action a ) { X eventSet.add( new Event( t, a ) ); X } X X /** run a simulation X * Call this after scheduling at least one event. X * The simulation will run until either there are no more events or X * some event terminates the program. X * From this point on, a typical simulation program will be event driven X * with the ordering of computations determined by chronological ordering X * of scheduled events. X */ X public static void run() { X while (!eventSet.isEmpty()) { X Event e = eventSet.remove(); X e.act.trigger( e.time ); X } X } } SHAR_EOF (set 20 19 04 12 10 03 30 'Simulation.java' eval "${shar_touch}") && \ chmod 0600 'Simulation.java' if test $? -ne 0 then ${echo} "restore of Simulation.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'Simulation.java': 'MD5 check failed' ) << \SHAR_EOF 73eaa412aab75e6a9fb7f8e7eadfbdb0 Simulation.java SHAR_EOF else test `LC_ALL=C wc -c < 'Simulation.java'` -ne 1748 && \ ${echo} "restoration warning: size of 'Simulation.java' is not 1748" fi fi # ============= ThresholdGate.java ============== if test -n "${keep_file}" && test -f 'ThresholdGate.java' then ${echo} "x - SKIPPING ThresholdGate.java (file already exists)" else ${echo} "x - extracting ThresholdGate.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'ThresholdGate.java' && // ThresholdGate.java X import java.util.Scanner; X /** threshold logic gates X * @author Douglas Jones X * @version 2019-04-03 X * @see Gate X */ public class ThresholdGate extends InputCountGate { X private int threshold = 0; X X public ThresholdGate( Scanner sc, String name ){ X super( name ); X threshold = ScanSupport.scanPositiveInt( sc, () -> this.toString() ); X delay = ScanSupport.scanPositiveFloat( sc, () -> this.toString() ); X ScanSupport.finishLine( sc, () -> this + " is followed by" ); X } X X /** Every subclass of gate offers a sanity check X * Calls Errors.warn() for any gate where threshold > input count X */ X public void sanityCheck() { X if (threshold > inCount) { X Errors.warn( this.toString() + ": has threshold > input wires" ); X } X } X X public String toString() { X return super.toString() + " threshold " + threshold + " " + delay; X } X X /** compute the gate's logical value X * @param count the number of ones on the input X * each subclass must implement this method X */ X public int logicRule( int count ) { X if (count >= threshold) return 1; X return 0; X } } SHAR_EOF (set 20 19 04 12 10 03 40 'ThresholdGate.java' eval "${shar_touch}") && \ chmod 0600 'ThresholdGate.java' if test $? -ne 0 then ${echo} "restore of ThresholdGate.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'ThresholdGate.java': 'MD5 check failed' ) << \SHAR_EOF a771cd2c3b78cc24bb16a896e2f57f83 ThresholdGate.java SHAR_EOF else test `LC_ALL=C wc -c < 'ThresholdGate.java'` -ne 1131 && \ ${echo} "restoration warning: size of 'ThresholdGate.java' is not 1131" fi fi # ============= Wire.java ============== if test -n "${keep_file}" && test -f 'Wire.java' then ${echo} "x - SKIPPING Wire.java (file already exists)" else ${echo} "x - extracting Wire.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'Wire.java' && // Wire.java X import java.util.Iterator; import java.util.List; import java.util.LinkedList; import java.util.Scanner; X /** Wires connect Gates X * @author Douglas Jones X * @version 2019-03-04 X * Lightly edited from RoadNetwork.java class Road version 2019-02-15, X * except for the constructor, which is heavily edited X * @see Gate X */ public class Wire { X X // a list of all of the wires in the universe X private static final List allWires = new LinkedList (); X X /** Allow outsiders to iterate over all the wires X * @returns an Iterator allowing access to wires X */ X public static Iterator iterator() { X return allWires.iterator(); X } X X // attributes of each Wire X private final Gate source; // where does this wire come from X private final Gate destination; // where does it go X private final float delay; // how long a signal takes to far end X X // construct a new Wire X private Wire( Gate src, Gate dst, Float del ) { X source = src; X destination = dst; X delay = del; X } X X /** build a new Gate and add it to the list of gates X * @param sc the scanner used to get the attributes of this wire X * @param src the source gate, guaranteed non null X * When called, the keyword "wire" and the name of the source gate X * have already been scanned, so we are ready to scan the delay and X * destination. X */ X public static void make( Scanner sc, Gate src ) { X // wire's delay and destination, until constructor call X final Float delay X = ScanSupport.scanPositiveFloat( sc, () -> "wire " + src.name ); X final String dstName = ScanSupport.scanName( X sc, () -> "Wire " + src.name + " " + delay + ": destination missing" X ); X X // all scanning is done now, may return at any time to avoid making wire X if (dstName == null) return; X X Gate dst = Gate.findGate( dstName ); X if (dst == null) { X Errors.warn( X "Wire " + src.name + " " + delay + " " + dstName X + ": undefined destination" X ); X return; X } X X // make the wire, after which w.toString is legal X Wire w = new Wire( src, dst, delay ); X X // now, we can actually wire the source and destination gates X src.connectFrom( w ); X dst.connectTo( w ); X X // finally, add wire to allWires X allWires.add( w ); X } X X public String toString() { X // note that source and destination are never null X return "Wire " + source.name + ' ' + delay + ' ' + destination.name; X } X X // Simulation methods X X /** tell the wire that its input has changed X * @param now the time at which the change occurs X * @param value the new value of that input X */ X public void inputChange( float now, int value ) { X Simulation.schedule( X now + delay, (float t) -> this.outputChange( t, value ) X ); X } X X private void outputChange( float now, int value ) { X final int comp = 1 - value; // logical complement of the value X System.out.println( "time "+ now +" "+ comp +"->"+ value +" "+ this ); X destination.inputChange( now, value ); X } } SHAR_EOF (set 20 19 04 12 10 03 47 'Wire.java' eval "${shar_touch}") && \ chmod 0600 'Wire.java' if test $? -ne 0 then ${echo} "restore of Wire.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'Wire.java': 'MD5 check failed' ) << \SHAR_EOF 34bf6cbb854bc605baedcece8b14ffc8 Wire.java SHAR_EOF else test `LC_ALL=C wc -c < 'Wire.java'` -ne 3033 && \ ${echo} "restoration warning: size of 'Wire.java' is not 3033" fi fi # ============= XorGate.java ============== if test -n "${keep_file}" && test -f 'XorGate.java' then ${echo} "x - SKIPPING XorGate.java (file already exists)" else ${echo} "x - extracting XorGate.java (text)" sed 's/^X//' << 'SHAR_EOF' > 'XorGate.java' && // XorGate.java X import java.util.Scanner; X /** Exclusive Or gates X * @author Douglas Jones X * @version 2019-04-03 X * @see Gate X */ public class XorGate extends InputCountGate { X X public XorGate( Scanner sc, String name ){ X super( name ); X delay = ScanSupport.scanPositiveFloat( sc, () -> this.toString() ); X ScanSupport.finishLine( sc, () -> this + " is followed by" ); X } X X /** Every subclass of gate offers a sanity check X * Calls Errors.warn() for any gate that has not got two inputs X */ X public void sanityCheck() { X if (inCount != 2) { X Errors.warn( this.toString() + ": input wire count must be two" ); X } X } X X public String toString() { X return super.toString() + " xor " + delay; X } X X /** compute the gate's logical value X * @param count the number of ones on the input X * each subclass must implement this method X */ X public int logicRule( int count ) { X return count % 2; X } } SHAR_EOF (set 20 19 04 12 10 03 59 'XorGate.java' eval "${shar_touch}") && \ chmod 0600 'XorGate.java' if test $? -ne 0 then ${echo} "restore of XorGate.java failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'XorGate.java': 'MD5 check failed' ) << \SHAR_EOF b22c46f4beaf0eb91fe30abe9bf964bd XorGate.java SHAR_EOF else test `LC_ALL=C wc -c < 'XorGate.java'` -ne 949 && \ ${echo} "restoration warning: size of 'XorGate.java' is not 949" fi fi if rm -fr ${lock_dir} then ${echo} "x - removed lock directory ${lock_dir}." else ${echo} "x - failed to remove lock directory ${lock_dir}." exit 1 fi exit 0