// Returns the numeric representation of the given string segment. // Throws an exception if unknown segment. private byte translateSegment(String segment, HVMInstructionSet instructionSet, String fileName) throws ProgramException { byte code = instructionSet.segmentVMStringToCode(segment); if (code == HVMInstructionSet.UNKNOWN_SEGMENT) throw new ProgramException(": Illegal memory segment - " + segment); return code; }
// Scans the given file and creates symbols for its functions & label names. private void buildProgram(File file, Hashtable symbols) throws ProgramException { 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"); } }