package janala;
import dk.brics.automaton.Automaton;
import dk.brics.automaton.RegExp;
import dk.brics.automaton.State;
import janala.config.Config;
import janala.instrument.Coverage;
import janala.interpreters.OrValue;
import janala.utils.MyLogger;
import janala.utils.Inputs;
import java.io.*;
import java.util.HashSet;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/** Main runtime environment for parsing inputs and writing state files. */
public class Main {
private static final Logger logger = MyLogger.getLogger(Coverage.class.getName());
public static boolean isInPrefix = true;
public static boolean skipPath = false;
private static Inputs inputs;
private static int scopeDepth;
private static int inputDepth;
static {
scopeDepth = 0;
inputDepth = 0;
inputs = new Inputs(Config.instance.inputs);
}
/** Set the inputs of the system. */
static void setInput(Inputs inputsOverride) {
inputs = inputsOverride;
}
private static boolean isInputAvailable() {
if (inputs.isInputAvailable() && scopeDepth >= inputDepth) {
return !inputs.isBeginScope() && !inputs.isEndScope();
}
return false;
}
public static void skipPath() {
skipPath = true;
}
public static void ignore() {}
/** Assume a boolean value is true. */
public static void assume(int value) {
if (value == 0) {
System.out.println("Assumption failed!");
System.exit(0);
}
}
/** Make the boolean value truth, if possible. */
public static void forceTruth(int value) {
if (value == 0) {
System.out.print("f,");
} else {
System.out.print("t,");
}
}
public static void beginScope() {
scopeDepth++;
if (inputs.isInputAvailable()) {
if (inputs.isBeginScope()) {
inputs.next();
inputDepth++;
}
}
}
public static void endScope() {
scopeDepth--;
while (true) {
if (scopeDepth >= inputDepth) {
return;
}
if (inputs.isInputAvailable()) {
if (inputs.isBeginScope()) {
inputDepth++;
} else if (inputs.isEndScope()) {
inputDepth--;
}
inputs.next();
}
}
}
/** Insert a check that an abstract value is equal to the concrete value.
* @param predicate */
public static void abstractEqualsConcrete(boolean predicate) {}
public static boolean compare(Object valueA, Object valueB) {
return valueA.equals(valueB);
}
public static OrValue assumeOrBegin(int b) {
return new OrValue(b != 0);
}
public static OrValue assumeOr(int b, OrValue b2) {
return new OrValue(b != 0 || b2.boolValue());
}
public static void assumeOrEnd(OrValue b) {
if (!b.boolValue()) {
System.out.println("Assumption (OR) failed!");
System.exit(0);
}
}
// These functions will be handled in the concolic interpreter.
/**
* @param intValue
*/
public static void MakeSymbolic(int intValue) {}
/**
* @param longValue
*/
public static void MakeSymbolic(long longValue) {}
/**
* @param charValue
*/
public static void MakeSymbolic(char charValue) {}
/**
* @param byteValue
*/
public static void MakeSymbolic(byte byteValue) {}
/**
* @param shortValue
*/
public static void MakeSymbolic(short shortValue) {}
/**
* @param boolValue
*/
public static void MakeSymbolic(boolean boolValue) {}
/**
* @param stringValue
*/
public static void MakeSymbolic(String stringValue) {}
public static int readInt(int x) {
if (isInputAvailable()) {
String input = inputs.read();
return Integer.parseInt(input);
} else {
return x;
}
}
public static long readLong(long x) {
if (isInputAvailable()) {
String input = inputs.read();
//System.out.println(input);
return Long.parseLong(input);
} else {
//System.out.println(x);
return x;
}
}
public static char readChar(char x) {
if (isInputAvailable()) {
String input = inputs.read();
return (char) Integer.parseInt(input);
} else {
//System.out.println(x);
return x;
}
}
public static short readShort(short x) {
if (isInputAvailable()) {
String input = inputs.read();
return Short.parseShort(input);
} else {
return x;
}
}
public static byte readByte(byte x) {
if (isInputAvailable()) {
String input = inputs.read();
return Byte.parseByte(input);
} else {
return x;
}
}
public static boolean readBool(boolean x) {
if (isInputAvailable()) {
String input = inputs.read();
boolean ret = Integer.parseInt(input) != 0;
return ret;
} else {
return x;
}
}
public static String readString(String x) {
if (isInputAvailable()) {
String input = inputs.read();
return new String(input);
} else {
//System.out.println(x);
return new String(x);
}
}
private static State pathsState;
private static String pathRegex;
private static String eventPrefix = "";
private static boolean isRealInput = true;
public static void setRealInput(boolean isReal) {
Writer writer = null;
try {
if (isRealInput) {
writer =
new BufferedWriter(
new OutputStreamWriter(new FileOutputStream("isRealInput"), "utf-8"));
writer.write("" + isReal);
isRealInput = isReal;
}
} catch (IOException ex) {
} finally {
try {
writer.close();
} catch (Exception ex) {
}
}
}
public static void event(String eventName) {
eventPrefix = eventPrefix + " " + eventName;
int i, len = eventName.length();
for (i = 0; i < len; i++) {
char c = eventName.charAt(i);
pathsState = pathsState.step(c);
if (pathsState == null) {
System.out.println(
"Pruning path as event prefix '"
+ eventPrefix
+ "' is not in regular expression '"
+ pathRegex
+ "'");
Main.setRealInput(false);
System.exit(0);
}
}
}
public static void pathRegex(String regex) {
pathRegex = regex;
Automaton pathsAutomaton = (new RegExp(regex)).toAutomaton();
//System.out.println(pathsAutomaton.toDot());
pathsState = pathsAutomaton.getInitialState();
}
private static TreeMap<String, HashSet<Serializable>> oldStates;
private static boolean oldStatesChanged = false;
public static void readOldStates() {
if (oldStates == null) {
ObjectInputStream inputStream = null;
try {
inputStream = new ObjectInputStream(new FileInputStream(Config.instance.oldStates));
Object tmp = inputStream.readObject();
if (tmp instanceof TreeMap<?,?>) {
oldStates = (TreeMap<String, HashSet<Serializable>>) tmp;
} else {
oldStates = new TreeMap<String, HashSet<Serializable>>();
}
} catch (Exception e) {
oldStates = new TreeMap<String, HashSet<Serializable>>();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException ex) {
logger.log(Level.WARNING, "", ex);
}
}
}
}
public static void writeOldStates() {
if (oldStatesChanged) {
ObjectOutputStream outputStream;
try {
outputStream = new ObjectOutputStream(new FileOutputStream(Config.instance.oldStates));
outputStream.writeObject(oldStates);
outputStream.close();
} catch (IOException e) {
logger.log(Level.SEVERE, "", e);
System.exit(1);
}
}
}
public static void equivalent(String location, Serializable value) {
if (!isInPrefix) {
readOldStates();
HashSet<Serializable> states = oldStates.get(location);
if (states == null) {
states = new HashSet<Serializable>();
oldStates.put(location, states);
states.add(value);
oldStatesChanged = true;
} else {
if (!states.contains(value)) {
states.add(value);
oldStatesChanged = true;
} else {
System.out.println("Pruning path as equivalent state found");
Main.setRealInput(false);
System.exit(0);
}
}
}
}
}