Пример #1
0
  // 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;
  }
Пример #2
0
  // 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");
    }
  }