package ga050426;

class STEntries {

	STEntries(String name, short value, boolean defined, STEntries prev,
			STEntries next) {
		this.name = name;
		this.value = value;
		this.defined = defined;
		this.next = next;
		this.prev = prev;
		this.number = 0;

	}

	STEntries(String name, boolean globdef, boolean globuse, STEntries prev,
			STEntries next) {
		this(name, prev, next);
		this.globdef = globdef;
		this.globuse = globuse;
		this.defined = globuse;
	}

	STEntries(String name, short value, STEntries prev, STEntries next) {
		this(name, value, true, prev, next);
	}

	STEntries(String name, STEntries prev, STEntries next) {
		this(name, (short) 0x0, false, prev, next);
	}

	String name;
	short value;
	int segment = 0; // Where it is defined
	boolean defined;
	boolean globdef = false;
	boolean globuse = false;
	int number;
	boolean apsolut = false;
	STEntries prev = null, next = null;
}

public class Symbols {
	public static Symbols instance = new Symbols();
	STEntries head = null, tail = null;
	public int defs = 0;
	public int undefs = 0;
	public static int stNumber = 0;

	private Symbols() {
	}

	public void enter(String name, boolean globdef, boolean globuse)
			throws SymbolDefinedException {
		for (STEntries cur = head; cur != null; cur = cur.next) {
			if (name.equals(cur.name)) {
				if (cur.globdef || cur.globuse)
					throw new SymbolDefinedException();
			}
		}
		if (tail != null)
			tail = tail.next = new STEntries(name, globdef, globuse, tail, null);
		else
			tail = head = new STEntries(name, globdef, globuse, tail, null);
		defs++;
		if (globdef)
			undefs++;
	}

	public void enter(String name, short value) throws SymbolDefinedException {
		for (STEntries cur = head; cur != null; cur = cur.next) {
			if (name.equals(cur.name)) {
				if (cur.defined == true)
					throw new SymbolDefinedException();
				else {
					cur.defined = true;
					cur.value = value;
					cur.segment = Segments.currentSegmentReference.number;
					if (cur.globdef)
						undefs--;
					return;
				}
			}
		}
		if (tail != null)
			tail = tail.next = new STEntries(name, value, true, tail, null);
		else
			tail = head = new STEntries(name, value, true, tail, null);
		tail.defined = true;
		tail.value = value;
		if (tail.globdef)
			undefs--;
	}


	public String toString() {
		StringBuffer buf = new StringBuffer(String.format("#Symbols (hex)%n"));
		for (STEntries cur = head; cur != null; cur = cur.next) {
			if (cur.globdef || cur.globuse) {
				buf.append(String.format(" %s\t%x\t%x\t%C%n", cur.name,
						cur.value, cur.segment, (cur.globdef ? 'D' : 'U')));
				cur.number = ++Symbols.stNumber;
			}
		}
		return new String(buf);
	}



	public STEntries getValueOf(String name) throws SymbolLeavedUndefinedException{
		for (STEntries cur = head; cur != null; cur = cur.next)
			if (cur.name.equals(name))
				return cur;
		throw new SymbolLeavedUndefinedException();
	}
	public void setValueFor(String name, short value) {
		for (STEntries cur = head; cur != null; cur = cur.next)
			if (cur.name.equals(name))
				cur.value=value;;
	}

}
