/* Variables.java -- Copyright (c) 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Classpath; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ package gnu.classpath.tools.rmic; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; class Variables { private final HashSet free = new HashSet(); private final HashMap names = new HashMap(); private final HashSet wides = new HashSet(); private final HashSet declared = new HashSet(); private boolean allocated = false; public void declare(Object name) { declare(name, 1); } public void declareWide(Object name) { declare(name, 2); } public void declare(Object name, int size) { if (allocated) throw new IllegalStateException("cannot declare after allocating"); if (size != 1 && size != 2) throw new IllegalArgumentException("size must be 1 or 2"); if (names.containsKey(name)) throw new IllegalStateException("already allocated " + name); allocateNew(name, size); declared.add(name); } private int allocateNew(Object name, int size) { // total allocation size is first unallocated slot int i = free.size() + names.size() + wides.size(); names.put(name, new Integer(i)); if (size == 2) wides.add(name); return i; } public int allocate(Object name) { return allocate(name, 1); } public int allocateWide(Object name) { return allocate(name, 2); } public int allocate(Object name, int size) { allocated = true; if (size != 1 && size != 2) throw new IllegalArgumentException("size must be 1 or 2"); if (names.containsKey(name)) throw new IllegalStateException("already allocated " + name); if (size == 2) { // look for consecutive free slots for (Iterator it = free.iterator(); it.hasNext(); ) { Integer i = (Integer) it.next(); Integer next = new Integer(i.intValue() + 1); if (free.contains(next)) { free.remove(i); free.remove(next); wides.add(name); names.put(name, i); return i.intValue(); } } } else if (free.size() > 0) { Integer i = (Integer) free.iterator().next(); free.remove(i); names.put(name, i); return i.intValue(); } return allocateNew(name, size); } public int deallocate(Object name) { if (! names.containsKey(name)) throw new IllegalArgumentException("no variable " + name); if (declared.contains(name)) throw new IllegalStateException(name + " can't be deallocated"); Integer i = (Integer) names.get(name); names.remove(name); free.add(i); if (wides.remove(name)) free.add(new Integer(i.intValue() + 1)); return i.intValue(); } public int get(Object name) { if (! names.containsKey(name)) throw new IllegalArgumentException("no variable " + name); return ((Integer) names.get(name)).intValue(); } }