git @ Cat's Eye Technologies Zplet / master src / main / java / org / zplet / zmachine / zmachine5 / ZDictionary5.java
master

Tree @master (Download .tar.gz)

ZDictionary5.java @masterraw · history · blame

/* Zplet, a Z-Machine interpreter in Java */
/* Copyright 1996,2001 Matthew T. Russotto */
/* As of 23 February 2001, this code is open source and covered by the */
/* Artistic License, found within this package */

package org.zplet.zmachine.zmachine5;

import org.zplet.zmachine.ZDictionary;
import org.zplet.zmachine.ZMachine;

public class ZDictionary5 extends ZDictionary {
	ZMachine zm;
	String separators;
	int nentries;
	int wtable_addr;
	int dict_address;
	int entry_length;

	public ZDictionary5(ZMachine zm, int dict_address) {
		int n, i;
		char separray[];

		this.zm = zm;
		this.dict_address = dict_address;
		n = zm.memory_image[dict_address] & 0xFF;
		separray = new char[n];

		for (i = 0; i < n; i++)
			separray[i] = (char) zm.memory_image[dict_address + i + 1];

		separators = new String(separray);
		// System.err.println("separators: " + separators);
		entry_length = zm.memory_image[dict_address + n + 1];
		nentries = (zm.memory_image[dict_address + n + 2] << 8)
				| ((zm.memory_image[dict_address + n + 3]) & 0xFF);
		wtable_addr = dict_address + n + 4;
	}

	public ZDictionary5(ZMachine zm) {
		this(zm, zm.header.dictionary());
	}

	@Override
	public boolean parse_word(int textloc, int wordloc, int wordlength,
			int parseloc) {
		return parse_word(textloc, wordloc, wordlength, parseloc, true);
	}

	public boolean parse_word(int textloc, int wordloc, int wordlength,
			int parseloc, boolean flagunknown) {
		short encword[];
		long enclong;
		long dictlong;
		int dictloc;
		int first = 0;
		int last = nentries - 1;
		int middle;
		int parseentry;

		// System.err.println("parse_word: textloc wordloc wordlength parseloc "
		// +
		// Integer.toString(textloc, 16) + " " +
		// Integer.toString(wordloc, 16) + " " +
		// wordlength + " " +
		// Integer.toString(parseloc, 16));
		if (zm.memory_image[parseloc] == zm.memory_image[parseloc + 1])
			return true;

		encword = zm.encode_word(wordloc, wordlength, 3);
		enclong = (((long) encword[0] & 0xFFFF) << 32)
				| (((encword[1]) & 0xFFFF) << 16) | ((encword[2] & 0xFFFF));
		middle = (last + first) / 2;
		while (true) {
			// System.err.print("bsearch " + first + " " + middle + " " + last);
			dictloc = wtable_addr + (middle * entry_length);
			dictlong = (((long) zm.memory_image[dictloc] & 0xFF) << 40)
					| (((long) zm.memory_image[dictloc + 1] & 0xFF) << 32)
					| (((long) zm.memory_image[dictloc + 2] & 0xFF) << 24)
					| (((long) zm.memory_image[dictloc + 3] & 0xFF) << 16)
					| (((long) zm.memory_image[dictloc + 4] & 0xFF) << 8)
					| ((long) zm.memory_image[dictloc + 5] & 0xFF);
			// System.err.println(" " + Long.toString(enclong, 16) + " " +
			// Long.toString(dictlong, 16));
			if (enclong < dictlong) {
				if (first == middle)
					break;
				last = middle - 1;
				middle = (first + middle) / 2;
			} else if (enclong > dictlong) {
				if (last == middle)
					break;
				first = middle + 1;
				middle = (middle + last + 1) / 2;
			} else
				break;
		}
		if (enclong != dictlong) {
			dictloc = 0;
		}
		// System.err.println("dictloc " + Integer.toString(dictloc,16));
		// System.err.println("wordlength " + Integer.toString(wordlength,16));
		// System.err.println("wordloc " + Integer.toString(wordloc -
		// textloc,16));
		if ((dictloc != 0) || flagunknown) {
			parseentry = parseloc
					+ ((zm.memory_image[parseloc + 1] & 0xFF) * 4) + 2;
			zm.memory_image[parseentry] = (byte) ((dictloc & 0xFF00) >> 8);
			zm.memory_image[parseentry + 1] = (byte) (dictloc & 0xFF);
			zm.memory_image[parseentry + 2] = (byte) wordlength;
			zm.memory_image[parseentry + 3] = (byte) (wordloc - textloc + 2);
			/* +1 in V3, + 2 in V5 on line above */
		}
		zm.memory_image[parseloc + 1]++;
		if (zm.memory_image[parseloc] == zm.memory_image[parseloc + 1])
			return true;
		return false;
	}

	@Override
	public void tokenise(int textloc, int textlength, int parseloc) {
		tokenise(textloc, textlength, parseloc, true);
	}

	public void tokenise(int textloc, int textlength, int parseloc,
			boolean parseunknown) {
		int wordloc, wordlength;
		int textleft = textlength;
		char ch;
		boolean pbfull;

		// System.err.println("tokenise: textloc textlength parseloc"
		// + Integer.toString(textloc,16) + " " + textlength
		// + " " + Integer.toString(parseloc,16));
		if ((zm.memory_image[parseloc] & 0xFF) < 1)
			zm.fatal("Parse buffer less than 1 word (6 bytes)");
		zm.memory_image[parseloc + 1] = (byte) 0;
		wordloc = textloc;
		wordlength = 0;
		pbfull = false;
		while (!pbfull && (textleft-- > 0)) {
			ch = (char) zm.memory_image[wordloc + wordlength];
			// System.err.println("ch @ " + Integer.toString(wordloc +
			// wordlength, 16) + " : " + ch);
			if (separators.indexOf(ch) != -1) {
				if (wordlength > 0)
					parse_word(textloc, wordloc, wordlength, parseloc);
				pbfull = parse_word(textloc, wordloc + wordlength, 1, parseloc);
				wordloc = wordloc + wordlength + 1;
				wordlength = 0;
			} else if (ch == ' ') {
				if (wordlength > 0)
					pbfull = parse_word(textloc, wordloc, wordlength, parseloc);
				wordloc = wordloc + wordlength + 1;
				wordlength = 0;
			} else
				wordlength++;
		}

		if (!pbfull && (wordlength > 0))
			parse_word(textloc, wordloc, wordlength, parseloc);
	}
}