BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file.getAbsolutePath()));
} catch (FileNotFoundException fnfe) {
throw new ProgramException("file does not exist");
}
int lineNumber = 0;
String line;
String label;
String instructionName;
String currentFunction = null;
short indexInFunction = 0;
byte opCode;
short arg0, arg1;
short pc = nextPC;
HVMInstructionSet instructionSet = HVMInstructionSet.getInstance();
isSlashStar = false;
try {
while ((line = unCommentLine(reader.readLine())) != null) {
lineNumber++;
if (!line.trim().equals("")) {
StringTokenizer tokenizer = new StringTokenizer(line);
instructionName = tokenizer.nextToken();
opCode = instructionSet.instructionStringToCode(instructionName);
if (opCode == HVMInstructionSet.UNKNOWN_INSTRUCTION)
throw new ProgramException("in line " + lineNumber +
": unknown instruction - " + instructionName);
switch (opCode) {
case HVMInstructionSet.PUSH_CODE:
String segment = tokenizer.nextToken();
try {
arg0 = translateSegment(segment, instructionSet, file.getName());
} catch (ProgramException pe) {
throw new ProgramException("in line " + lineNumber + pe.getMessage());
}
arg1 = Short.parseShort(tokenizer.nextToken());
if (arg1 < 0)
throw new ProgramException("in line " + lineNumber +
": Illegal argument - " + line);
if (arg0 == HVMInstructionSet.STATIC_SEGMENT_CODE && arg1 > largestStaticIndex)
largestStaticIndex = arg1;
instructions[pc] = new VMEmulatorInstruction(opCode, arg0, arg1,
indexInFunction);
break;
case HVMInstructionSet.POP_CODE:
int n = tokenizer.countTokens();
segment = tokenizer.nextToken();
try {
arg0 = translateSegment(segment, instructionSet, file.getName());
} catch (ProgramException pe) {
throw new ProgramException("in line " + lineNumber + pe.getMessage());
}
arg1 = Short.parseShort(tokenizer.nextToken());
if (arg1 < 0)
throw new ProgramException("in line " + lineNumber +
": Illegal argument - " + line);
if (arg0 == HVMInstructionSet.STATIC_SEGMENT_CODE && arg1 > largestStaticIndex)
largestStaticIndex = arg1;
instructions[pc] = new VMEmulatorInstruction(opCode, arg0, arg1,
indexInFunction);
break;
case HVMInstructionSet.FUNCTION_CODE:
currentFunction = tokenizer.nextToken();
indexInFunction = 0;
arg0 = Short.parseShort(tokenizer.nextToken());
if (arg0 < 0)
throw new ProgramException("in line " + lineNumber +
": Illegal argument - " + line);
instructions[pc] = new VMEmulatorInstruction(opCode, arg0, indexInFunction);
instructions[pc].setStringArg(currentFunction);
break;
case HVMInstructionSet.CALL_CODE:
String functionName = tokenizer.nextToken();
try {
arg0 = getAddress(functionName);
} catch (ProgramException pe) {
throw new ProgramException("in line " +
lineNumber + ": " +
pe.getMessage());
}
arg1 = Short.parseShort(tokenizer.nextToken());
if (arg1 < 0 || ((arg0 < 0 || arg0 > Definitions.ROM_SIZE) && arg0 != BUILTIN_FUNCTION_ADDRESS))
throw new ProgramException("in line " + lineNumber +
": Illegal argument - " + line);
instructions[pc] = new VMEmulatorInstruction(opCode, arg0, arg1,
indexInFunction);
instructions[pc].setStringArg(functionName);
break;
case HVMInstructionSet.LABEL_CODE:
label = currentFunction + "$" + tokenizer.nextToken();
instructions[pc] = new VMEmulatorInstruction(opCode, (short)(-1));
instructions[pc].setStringArg(label);
indexInFunction--; // since Label is not a "physical" instruction
break;
case HVMInstructionSet.GOTO_CODE:
label = currentFunction + "$" + tokenizer.nextToken();
Short labelAddress = (Short)symbols.get(label);
if (labelAddress == null)
throw new ProgramException("in line " + lineNumber +
": Unknown label - " + label);
arg0 = labelAddress.shortValue();
if (arg0 < 0 || arg0 > Definitions.ROM_SIZE)
throw new ProgramException("in line " + lineNumber +
": Illegal argument - " + line);
instructions[pc] = new VMEmulatorInstruction(opCode, arg0, indexInFunction);
instructions[pc].setStringArg(label);
break;
case HVMInstructionSet.IF_GOTO_CODE:
label = currentFunction + "$" + tokenizer.nextToken();
labelAddress = (Short)symbols.get(label);
if (labelAddress == null)
throw new ProgramException("in line " + lineNumber +
": Unknown label - " + label);
arg0 = labelAddress.shortValue();
if (arg0 < 0 || arg0 > Definitions.ROM_SIZE)
throw new ProgramException("in line " + lineNumber +
": Illegal argument - " + line);
instructions[pc] = new VMEmulatorInstruction(opCode, arg0, indexInFunction);
instructions[pc].setStringArg(label);
break;
// All other instructions have either 1 or 0 arguments and require no
// special treatment
default:
if (tokenizer.countTokens() == 0) {
instructions[pc] = new VMEmulatorInstruction(opCode, indexInFunction);
}
else {
arg0 = Short.parseShort(tokenizer.nextToken());
if (arg0 < 0)
throw new ProgramException("in line " + lineNumber +
": Illegal argument - " + line);
instructions[pc] = new VMEmulatorInstruction(opCode, arg0,
indexInFunction);
}
break;
}
// check end of command
if (tokenizer.hasMoreTokens())
throw new ProgramException("in line " + lineNumber +
": Too many arguments - " + line);
pc++;
indexInFunction++;
}
nextPC = pc;
}
reader.close();
} catch (IOException ioe) {
throw new ProgramException("Error while reading from file");
} catch (NumberFormatException nfe) {
throw new ProgramException("Illegal 16-bit value");
} catch (NoSuchElementException nsee) {
throw new ProgramException("In line " + lineNumber + ": unexpected end of command");
}
if (isSlashStar) {
throw new ProgramException("Unterminated /* comment at end of file");
}
}