import org.apache.bcel.generic.*;
import org.apache.bcel.Constants;
import java.util.*;
import java.io.*;

/**
 * Simple Byte code assembly language based off of the BCEL.
 * 
 * @author Matthew W. Coan (July 1, 2002) matthewcoan@hotmail.com
 */
public class asm implements InstructionConstants {
   public InstructionList _il;
   public ConstantPoolGen _cp;
   public ClassGen _cg;
   public MethodGen _mg;
   public LocalVariableGen _lg;
   public String _fileName;
   public String _className;
   public BufferedReader _br;
   public LinkedList _code;
   public LinkedList _lineno;
   public int _linenoIndex;
   public Hashtable _symTbl;
   public Hashtable _gotoTbl;
   public Hashtable _nullTbl;
   public Hashtable _clsTbl = new Hashtable();
   public LinkedList tsc_list = new LinkedList();
   public TreeMap< String, MyCode > code_map = new TreeMap< String, MyCode >();
   public InstructionHandle h = null;

   public class MyCode {
      public void run(LinkedList data) {

      }
   }

   public class TableSwitchContext {
      public int match[] = null;
      public InstructionHandle target[] = null;
      public LinkedList label_list = null;
      public String def = null;
      public TABLESWITCH tableswitch = null;
      public InstructionHandle index = null;

      public void print() {
         System.out.print("TABLESWITCH ");
         if(match != null) {
            for(int i = 0; i < match.length; i++) {
               System.out.print(match[i] + ",");
            }
            System.out.print(" ");
         }
         if(label_list != null) {
            for(int i = 0; i < label_list.size(); i++) {
               System.out.print(label_list.get(i)+",");
            }
            System.out.print(" ");
         }
         if(def != null) {
            System.out.print(def);
         }
         System.out.println();
      }
   }

   public LinkedList parseTargetArray(String str) {
      StringTokenizer st = new StringTokenizer(str, ",");
      LinkedList l = new LinkedList();
      while(st.hasMoreTokens()) {
         l.add(st.nextToken());
      } 
      return l;
   }

   public int[] parseIntArray(String str) {
      StringTokenizer st = new StringTokenizer(str,",");
      LinkedList l = new LinkedList();
      while(st.hasMoreTokens()) {
         l.add(new Integer(Integer.parseInt(st.nextToken())));
      }
      int ret[] = new int[l.size()];
      for(int i = 0; i < l.size(); i++) {
         ret[i] = Integer.parseInt(l.get(i).toString());
      }
      return ret;
   }
   
   public void _loadCode()
   throws IOException {
      String line;
      int lineno = 0;
      while((line = _br.readLine()) != null) {
         lineno++;
         line = line.trim();
         if(line.length() == 0 || line.charAt(0) == ';')
            continue;
         _code.add(line);
         _lineno.add(new Integer(lineno));
      }
   }
   
   public void _expected(String op, int n, int got) {
      if(n != got)
         _error(op + " expects " + (n-1) + " arguments!");
   }
   
   public String _decodeString(String s) {
      StringBuffer buf = new StringBuffer();
      char ch;
      for(int i = 0; i < s.length(); i++) {
         ch = s.charAt(i);
         if(ch == '\\') {
            if(s.charAt(i+1) == '\\') {
               i++;
               buf.append('\\');
            }
            else {
               i++;
               ch = s.charAt(i);
/*
               switch (ch) {
               case '0':

               case '1':

               case '2':

               case '3':

               case '4':

               case '5':

               case '6':

               case '7':
*/
               if(ch >= '0' && ch <= '7') {
                   char leadch = ch;
                   int oct = Character.digit(ch, 8);
                   i++;
                   ch = s.charAt(i);
                   if ('0' <= ch && ch <= '7') {
                       oct = oct * 8 + Character.digit(ch, 8);
                       i++;
                       ch = s.charAt(i);
                       if (leadch <= '3' && '0' <= ch && ch <= '7') {
                           oct = oct * 8 + Character.digit(ch, 8);
                       }
                   }
                   buf.append((char) oct);
               }
               //break;

               //case 'b':
               else if(ch == 'b') 
                   buf.append('\b');
                   //break;

               //case 't':
               else if(ch == 't') 
                   buf.append('\t');
                   //break;

               //case 'n':
               else if(ch == 'n') 
                   buf.append('\n');
                   //break;

               //case 'f':
               else if(ch == 'f') 
                   buf.append('\f');
                   //break;

               //case 'r':
               else if(ch == 'r') 
                   buf.append('\r');
                   //break;

               //case '\'':
               else if(ch == '\'') 
                   buf.append('\'');
                   //break;

               //case '\"':
               else if(ch == '\"') 
                   buf.append('\"');
                   //break;

               //case '\\':
               else if(ch == '\\') 
                   buf.append('\\');
                   //break;

/*
               default:
                   _error("Bad string constant!");
               }
*/
            }
         }
         else
            buf.append((char)ch);
      }
      return buf.toString();
   }

   public LinkedList _tokenizeInstruction(String line) {
      LinkedList l = new LinkedList();
      StringBuffer buf = new StringBuffer();
      char ch;
      boolean inString = false;
      for(int i = 0; i < line.length(); i++) {
         ch = line.charAt(i);
         if(Character.isWhitespace(ch) && !inString) {
            if(buf.length() > 0) {
               l.add(buf.toString());
               buf = new StringBuffer();
            }
         }
         else if(Character.isWhitespace(ch))
            buf.append(ch);
         else
            buf.append(ch);
         if(ch == '\"' && !inString)
            inString = true;
         else if(ch == '\"') {
            if((i-1) >= 0) {
               if(line.charAt(i-1) == '\\')
                  ;
               else
                  inString = false;
            }
         }
      }
      if(buf.length() > 0)
         l.add(buf.toString());
      return l;
   }

   public class fieldref extends MyCode {
      public void run(LinkedList data) {
         _expected("fieldref", 5, data.size());
         String type = data.get(1).toString();
         String field = data.get(2).toString();
         String sig = data.get(3).toString();
         String name = data.get(4).toString();
         int address = _cp.addFieldref(type, field, sig);
         _symTbl.put(name, new Integer(address));
         h = _il.append(new NOP());
      }
   }

   public class fpush extends MyCode {
      public void run(LinkedList data) {
         _expected("fpush", 2, data.size());
         String arg = data.get(1).toString();
         float farg = 0;
         try {
            farg = new Float(arg).floatValue();
         }
         catch(NumberFormatException nfe) {
            _error("fpush expects a float constant argument.");
         }
         h = _il.append(new PUSH(_cp, farg));
      }
   }

   public class invokevirtual extends MyCode {
      public void run(LinkedList data) {
         _expected("invokevirtual", 5, data.size());
         String type = data.get(1).toString();
         String method = data.get(2).toString();
         String sig = data.get(3).toString();
         h = _il.append(new INVOKEVIRTUAL(_cp.addMethodref(type,
                        method, sig)));
      }
   }

   public class invokeinterface extends MyCode {
      public void run(LinkedList data) {
         _expected("invokeinterface", 5, data.size());
         String type = data.get(1).toString();
         String method = data.get(2).toString();
         String sig = data.get(3).toString();
         String cnt = data.get(4).toString();
         h = _il.append(new INVOKEINTERFACE(_cp.addMethodref(type,
                        method, sig), Integer.parseInt(cnt)));
      }
   }

   public class invokestatic extends MyCode {
      public void run(LinkedList data) {
         _expected("invokestatic", 5, data.size());
         h = _il.append(new INVOKESTATIC(_cp.addMethodref(data.get(1).toString(),
         data.get(2).toString(),
         data.get(3).toString())));
      }
   }

   public class invokespecial extends MyCode {
      public void run(LinkedList data) {
         _expected("invokespecial", 5, data.size());
         h = _il.append(new INVOKESPECIAL(_cp.addMethodref(data.get(1).toString(),
         data.get(2).toString(),
         data.get(3).toString())));
      }
   }

   public class invokedynamic extends MyCode {
      public void run(LinkedList data) {
         _expected("invokedynamic", 2, data.size());
         String index = data.get(1).toString();
         h = _il.append(new INVOKEDYNAMIC(Integer.parseInt(index)));
      }
   }

   public class Instanceof extends MyCode {
      public void run(LinkedList data) {
         _expected("instanceof", 2, data.size());
         String n = data.get(1).toString();
         h = _il.append(new INSTANCEOF(Integer.parseInt(n)));
      }
   }


   public class iconst extends MyCode {
      public void run(LinkedList data) {
         _expected("iconst", 2, data.size());
         String arg = data.get(1).toString();
         int iarg = 0;
         try {
            iarg = Integer.parseInt(arg);
         }
         catch(NumberFormatException nfe) {
            _error("ipush expects an integer constant argument.");
         }
         h = _il.append(new PUSH(_cp, iarg));
      }
   }
   
   public class iastore extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new IASTORE());
      }
   }

   public class istore extends MyCode {
      public void run(LinkedList data) {
         _expected("istore", 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("istore expects a variable argument, \"" 
                   + arg + "\" not found!");
         }
         h = _il.append(new ISTORE(address.intValue()));
      }
   }

   public class fstore extends MyCode {
      public void run(LinkedList data) {
         _expected("fstore", 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("fstore expects a variable argument, \""
                   + arg + "\" not found!");
         }
         h = _il.append(new FSTORE(address.intValue()));
      }
   }

   public class aastore extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new AASTORE());
      }
   }

   public class Pop extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new POP());
      }
   }

   public class sipush extends MyCode {
      public void run(LinkedList data) {
         _expected("sipush", 2, data.size());
         String arg = data.get(1).toString();
         h = _il.append(new SIPUSH((short)Integer.parseInt(arg)));
      }
   }

   public class bipush extends MyCode {
      public void run(LinkedList data) {
         _expected("bipush", 2, data.size());
         String arg = data.get(1).toString();
         h = _il.append(new BIPUSH((byte)Integer.parseInt(arg)));
      }
   }

   public class iload extends MyCode {
      public void run(LinkedList data) {
         _expected("iload", 2, data.size());
         String arg = data.get(1).toString();
         h = _il.append(new ILOAD(Integer.parseInt(arg)));
      }
   }

   public class fload extends MyCode {
      public void run(LinkedList data) {
         _expected("fload", 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("iload expects a variable argument, \""
                   + arg + "\" not found!");
         }
         h = _il.append(new FLOAD(address.intValue()));     
      }
   }

   public class iaload extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new IALOAD());
      }
   }

   public class aaload extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new AALOAD());
      }
   }

   public class checkcast extends MyCode {
      public void run(LinkedList data) {
         _expected("checkcast", 2, data.size());
         String index = data.get(1).toString();
         h = _il.append(new CHECKCAST(Integer.parseInt(index)));
      }
   }

   public class tableswitch extends MyCode {
      public void run(LinkedList data) {
         _expected("tableswitch", 4, data.size());
         int match[] = parseIntArray(data.get(1).toString());
         LinkedList the_list = parseTargetArray(data.get(2).toString());
         TableSwitchContext tsc = new TableSwitchContext();
         tsc.label_list = the_list;
         tsc.match = match;
         tsc.index = _il.append(new NOP());
         if(data.size() == 4) {
            tsc.def = data.get(3).toString();
         }
         tsc_list.add(tsc);
      }
   }

   public class iadd extends MyCode {
      public void run(LinkedList data) {
         _expected("iadd", 1, data.size());
         h = _il.append(new IADD());
      }
   }

   public class iinc extends MyCode {
      public void run(LinkedList data) {
         _expected("iinc", 3, data.size());
         String id = data.get(1).toString();
         String n = data.get(2).toString();
         h = _il.append(new IINC(Integer.parseInt(id.substring(4)),Integer.parseInt(n)));
      }
   }

   public class isub extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new ISUB());
      }
   }
   public class imul extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new IMUL());
      }
   }
   public class idiv extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new IDIV());
      }
   }
   public class ineg extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new INEG());
      }
   }
   public class irem extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new IREM());
      }
   }
   public class ixor extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new IXOR());
      }
   }
   public class iand extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new IAND());
      }
   }
   public class ior extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new IOR());
      }
   }
   public class i2b extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(I2B);
      }
   }
   public class i2c extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new I2C());
      }
   }
   public class i2d extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new I2D());
      }
   }
   public class i2f extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new I2F());
      }
   }
   public class i2l extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new I2L());
      }
   }
   public class i2s extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new I2S());
      }
   }
   public class d2f extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new D2F());
      }
   }
   public class d2i extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new D2I());
      }
   }
   public class d2l extends MyCode {
      public void run(LinkedList data) {
         h = _il.append(new D2L());
      }
   }


   public void init() {
      code_map.put("fpush", new fpush());
      code_map.put("fieldref", new fieldref());
      code_map.put("instanceof", new Instanceof());
      code_map.put("invokevirtual", new invokevirtual());
      code_map.put("invokestatic", new invokestatic());
      code_map.put("invokedynamic", new invokedynamic());
      code_map.put("invokespecial", new invokespecial());
      code_map.put("invokeinterface", new invokeinterface());
      code_map.put("iconst", new iconst());
      code_map.put("iastore", new iastore());
      code_map.put("istore", new istore());
      code_map.put("fstore", new fstore());
      code_map.put("aastore", new aastore());
      code_map.put("pop", new Pop());
      code_map.put("sipush", new sipush());
      code_map.put("bipush", new bipush());
      code_map.put("iload", new iload());
      code_map.put("fload", new fload());
      code_map.put("iaload", new iaload());
      code_map.put("aaload", new aaload());
      code_map.put("checkcast", new checkcast());
      code_map.put("tableswitch", new tableswitch());
      code_map.put("iadd", new iadd());
      code_map.put("iinc", new iinc());
      code_map.put("isub", new isub());
      code_map.put("imul", new imul());
      code_map.put("idiv", new idiv());
      code_map.put("ineg", new ineg());
      code_map.put("irem", new irem());
      code_map.put("ixor", new ixor());
      code_map.put("iand", new iand());
      code_map.put("ior", new ior());
      code_map.put("i2b", new i2b());
      code_map.put("i2c", new i2c());
      code_map.put("i2d", new i2d());
      code_map.put("i2f", new i2f());
      code_map.put("i2l", new i2l());
      code_map.put("i2s", new i2s());
      code_map.put("d2f", new d2f());
      code_map.put("d2i", new d2i());
      code_map.put("d2l", new d2l());
  }
   
   public void _codeInstruction(String line) {
      LinkedList data = _tokenizeInstruction(line);
      if(data.size() == 0)
         _error("Instruction must have an opcode!");
      String op = data.get(0).toString();
      String lbl = null;
      String lbl2 = null;
      if(op.startsWith("L") && op.endsWith(":")) {
         lbl2 = lbl = op;
         lbl = lbl.substring(0,lbl.length()-1);
         data.remove(0);
         op = (String)data.get(0);
      }

      MyCode the_code = code_map.get(op);
      if(the_code != null) {
         the_code.run(data);
         if(lbl != null && h != null) {
            LinkedList gotoList = (LinkedList)_nullTbl.get(lbl);
            if(gotoList != null) {
               Iterator it = gotoList.iterator();
               BranchInstruction br;
               while(it.hasNext()) {
                  br = (BranchInstruction)it.next();
                  br.setTarget(h);
               }
            }
            _gotoTbl.put(lbl, h);
         }
         return;
      }

      //InstructionHandle h = null;
      if(op.compareTo("fieldref") == 0) {
         _expected(op, 5, data.size());
         String type = data.get(1).toString();
         String field = data.get(2).toString();
         String sig = data.get(3).toString();
         String name = data.get(4).toString();
         int address = _cp.addFieldref(type, field, sig);
         _symTbl.put(name, new Integer(address));
         h = _il.append(new NOP());
      }
      else if(op.compareTo("fpush") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         float farg = 0;
         try {
            farg = new Float(arg).floatValue();
         }
         catch(NumberFormatException nfe) {
            _error("fpush expects a float constant argument.");
         }
         h = _il.append(new PUSH(_cp, farg));
      }
      else if(op.compareTo("instanceof") == 0) {
         _expected(op, 2, data.size());
         String n = data.get(1).toString();
         h = _il.append(new INSTANCEOF(Integer.parseInt(n)));
      }
      else if(op.indexOf("iconst_") == 0) {
         String val = op.substring(7);
         if(val.equals("m1"))
            h = _il.append(new PUSH(_cp, -1));
         else
            h = _il.append(new PUSH(_cp, Integer.parseInt(val)));
      }
      else if(op.indexOf("dconst_") == 0) {
         String str = op.substring(7);
         double darg = 0.0;
         try {
            darg = new Double(str).floatValue();
         }
         catch(NumberFormatException nfe) {
            _error(nfe.getMessage());
         }
         h = _il.append(new DCONST(darg));
      }
      else if(op.indexOf("lconst_") == 0) {
         String str = op.substring(7);
         long larg = 0L;
         try {
            larg = new Long(str).longValue();
         }
         catch(NumberFormatException nfe) {
            _error(nfe.getMessage());
         }
         h = _il.append(new LCONST(larg));
      }
      else if(op.indexOf("fconst_") == 0) {
         String str = op.substring(7);
         float farg = 0.0F;
         try {
            farg = new Float(str).floatValue();
         }
         catch(NumberFormatException nfe) {
            _error(nfe.getMessage());
         }
         h = _il.append(new FCONST(farg));
      }
      else if(op.compareTo("iconst") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         int iarg = 0;
         try {
            iarg = Integer.parseInt(arg);
         }
         catch(NumberFormatException nfe) {
            _error("ipush expects an integer constant argument.");
         }
         h = _il.append(new PUSH(_cp, iarg));
      }
      else if(op.indexOf("istore_") == 0) {
         String n = op.substring(7); 
         h = _il.append(new ISTORE(Integer.parseInt(n)));
      }
      else if(op.compareTo("iastore") == 0) {
         h = _il.append(new IASTORE());
      }
      else if(op.compareTo("istore") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("istore expects a variable argument, \"" 
                   + arg + "\" not found!");
         }
         h = _il.append(new ISTORE(address.intValue()));
      }
      else if(op.compareTo("fstore") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("fstore expects a variable argument, \""
                   + arg + "\" not found!");
         }
         h = _il.append(new FSTORE(address.intValue()));      
      }
      else if(op.startsWith("astore_")) {
         String n = op.substring(7).trim();
         h = _il.append(new ASTORE(Integer.parseInt(n)));
      }
      else if(op.compareTo("aastore") == 0) {
         h = _il.append(new AASTORE());
      }
      else if(op.compareTo("astore") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("astore expects a variable argument, \"" 
                   + arg + "\" not found!");
         }
         h = _il.append(new ASTORE(address.intValue()));
      }
      else if(op.indexOf("iload_") == 0) {
         String n = op.substring(6);
         h = _il.append(new ILOAD(Integer.parseInt(n)));
      }
      else if(op.compareTo("pop") == 0) {
         h = _il.append(new POP());
      }
      else if(op.compareTo("sipush") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = _il.append(new SIPUSH((short)Integer.parseInt(arg)));
      }
      else if(op.compareTo("bipush") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = _il.append(new BIPUSH((byte)Integer.parseInt(arg)));
      }
      else if(op.compareTo("iload") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = _il.append(new ILOAD(Integer.parseInt(arg)));
      }
      else if(op.compareTo("fload") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("iload expects a variable argument, \""
                   + arg + "\" not found!");
         }
         h = _il.append(new FLOAD(address.intValue()));     
      }
      else if(op.compareTo("arraylength") == 0) {
         h = _il.append(new ARRAYLENGTH());
      }
      else if(op.indexOf("iaload") == 0) {
         h = _il.append(new IALOAD());
      }
      else if(op.indexOf("aaload") == 0) {
         h = _il.append(new AALOAD());
      }
      else if(op.indexOf("aload_") == 0) {
         String n = op.substring(6);
         h = _il.append(new ALOAD(Integer.parseInt(n)));
      }
      else if(op.compareTo("aload") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("aload expects a variable argument, \"" 
                   + arg + "\" not found!");
         }
         h = _il.append(new ALOAD(address.intValue()));
      }
      else if(op.compareTo("checkcast") == 0) {
         _expected(op, 2, data.size());
         String index = data.get(1).toString();
         h = _il.append(new CHECKCAST(Integer.parseInt(index)));
      }
      else if(op.compareTo("tableswitch") == 0) {
         _expected(op, 4, data.size());
         int match[] = parseIntArray(data.get(1).toString());
         LinkedList the_list = parseTargetArray(data.get(2).toString());
         TableSwitchContext tsc = new TableSwitchContext();
         tsc.label_list = the_list;
         tsc.match = match;
         tsc.index = _il.append(new NOP());
         if(data.size() == 4) {
            tsc.def = data.get(3).toString();
         }
         tsc_list.add(tsc);
      }
      else if(op.compareTo("iadd") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new IADD());
      }
      else if(op.compareTo("iinc") == 0) {
         _expected(op, 3, data.size());
         String id = data.get(1).toString();
         String n = data.get(2).toString();
         h = _il.append(new IINC(Integer.parseInt(id.substring(4)),Integer.parseInt(n)));
      }
      else if(op.compareTo("isub") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new ISUB());
      }
      else if(op.compareTo("imul") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new IMUL());
      }
      else if(op.compareTo("idiv") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new IDIV());
      }
      else if(op.compareTo("ineg") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new INEG());
      }
      else if(op.compareTo("irem") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new IREM());
      }
      else if(op.compareTo("ixor") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new IXOR());
      }
      else if(op.compareTo("iand") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new IAND());
      }
      else if(op.compareTo("ior") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new IOR());
      }
      else if(op.compareTo("i2b") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(I2B);
      }
      else if(op.compareTo("i2c") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new I2C());
      }
      else if(op.compareTo("i2d") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new I2D());
      }
      else if(op.compareTo("i2f") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new I2F());
      }
      else if(op.compareTo("i2l") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new I2L());
      }
      else if(op.compareTo("i2s") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new I2S());
      }
      else if(op.compareTo("d2f") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new D2F());
      }
      else if(op.compareTo("d2i") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new D2I());
      }
      else if(op.compareTo("d2l") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new D2L());
      }
      else if(op.compareTo("dadd") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new DADD());
      }
      else if(op.compareTo("dpush") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         double darg = 0.0;
         try {
            darg = new Double(arg).doubleValue();
         }
         catch(NumberFormatException nfe) {
            _error("dpush expects a double constant argument.");
         }
         h = _il.append(new PUSH(_cp, darg));
      }
      else if(op.compareTo("ddiv") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new DDIV());
      }
      else if(op.compareTo("dstore") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("dstore expects a variable argument, \"" 
                   + arg + "\" not found!");
         }
         h = _il.append(new DSTORE(address.intValue()));
      }
      else if(op.compareTo("dload") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("dload expects a variable argument, \"" 
                   + arg + "\" not found!");
         }
         h = _il.append(new DLOAD(address.intValue()));
      }
      else if(op.compareTo("dmul") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new DMUL());
      }
      else if(op.compareTo("fmul") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new FMUL());
      }
      else if(op.compareTo("dneg") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new DNEG());
      }
      else if(op.compareTo("drem") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new DREM());
      }
      else if(op.compareTo("dreturn") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new DRETURN());
      }
      else if(op.compareTo("ireturn") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new IRETURN());
      }
      else if(op.compareTo("dsub") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new DSUB());
      }
      else if(op.compareTo("fsub") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new FSUB());
      }
      else if(op.compareTo("f2d") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new F2D());
      }
      else if(op.compareTo("f2i") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new F2I());
      }
      else if(op.compareTo("f2l") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new F2L());
      }
      else if(op.compareTo("fadd") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new FADD());
      }
      else if(op.compareTo("fdiv") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new FDIV());
      }
      else if(op.compareTo("l2d") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new L2D());
      }
      else if(op.compareTo("l2f") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new L2F());
      }
      else if(op.compareTo("l2i") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new L2I());
      }
      else if(op.compareTo("ladd") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new LADD());
      }
      else if(op.compareTo("land") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new LAND());
      }
      else if(op.compareTo("lpush") == 0) {
         _expected(op, 1, data.size());
         String arg = data.get(1).toString();
         long larg = 0;
         try {
            larg = new Long(arg).longValue();
         }
         catch(NumberFormatException nfe) {
            _error("lpush expects a long constant argument.");
         }
         h = _il.append(new PUSH(_cp, larg));
      }
      else if(op.compareTo("lstore") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("lstore expects a variable argument, \"" 
                   + arg + "\" not found!");
         }
         h = _il.append(new LSTORE(address.intValue()));
      }
      else if(op.compareTo("lload") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         Integer address = (Integer)_symTbl.get(arg);
         if(address == null) {
            _error("lload expects a variable argument, \"" 
                   + arg + "\" not found!");
         }
         h = _il.append(new LLOAD(address.intValue()));
      }
      else if(op.compareTo("ldiv") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new LDIV());
      }
      else if(op.compareTo("lmul") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new LMUL());
      }
      else if(op.compareTo("lneg") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new LNEG());
      }
      else if(op.compareTo("lor") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new LOR());
      }
      else if(op.compareTo("lrem") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new LREM());
      }
      else if(op.compareTo("lreturn") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new LRETURN());
      }
      else if(op.compareTo("lsub") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new LSUB());
      }
      else if(op.compareTo("lxor") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new LXOR());
      }
      else if(op.compareTo("ldc_w") == 0) {
         _expected(op, 2, data.size());
         String s = data.get(1).toString();
         if(s.charAt(0) != '\"' || s.charAt(s.length()-1) != '\"')
            _error("Bad string constant!");
         s = _decodeString(s);
         h = _il.append(new PUSH(_cp, s.substring(1,s.length()-1)));
      }
      else if(op.compareTo("ldc") == 0) {
         _expected(op, 2, data.size());
         String s = data.get(1).toString();
         if(s.charAt(0) != '\"' || s.charAt(s.length()-1) != '\"')
            _error("Bad string constant!");
         s = _decodeString(s);
         h = _il.append(new PUSH(_cp, s.substring(1,s.length()-1)));
      }
      else if(op.compareTo("putstatic") == 0) {
         _expected(op, 4, data.size());
         String cls = data.get(1).toString();
         String field = data.get(2).toString();
         String signature = data.get(3).toString();
         int index1 = _cp.addFieldref(cls, field, signature);
         h = _il.append(new PUTSTATIC(index1));
      }
      else if(op.compareTo("getstatic") == 0) {
         _expected(op, 4, data.size());
         String cls = data.get(1).toString();
         String field = data.get(2).toString();
         String signature = data.get(3).toString();
         int index1 = _cp.addFieldref(cls, field, signature);
         h = _il.append(new GETSTATIC(index1));
      }
      else if(op.compareTo("newarray") == 0) {
         _expected(op, 2, data.size());
         String ch = data.get(1).toString();
         h = _il.append(new NEWARRAY((byte)Integer.parseInt(ch)));
      }
      else if(op.compareTo("invokeinterface") == 0) {
         _expected(op, 5, data.size());
         String type = data.get(1).toString();
         String method = data.get(2).toString();
         String sig = data.get(3).toString();
         String cnt = data.get(4).toString();
         h = _il.append(new INVOKEINTERFACE(_cp.addMethodref(type,
                        method, sig), Integer.parseInt(cnt)));
      }
      else if(op.compareTo("invokevirtual") == 0) {
         _expected(op, 5, data.size());
         String type = data.get(1).toString();
         String method = data.get(2).toString();
         String sig = data.get(3).toString();
         h = _il.append(new INVOKEVIRTUAL(_cp.addMethodref(type,
                        method, sig)));
      }
      else if(op.compareTo("invokedynamic") == 0) {
         _expected(op, 2, data.size());
         String index = data.get(1).toString();
         h = _il.append(new INVOKEDYNAMIC(Integer.parseInt(index)));
      }
      else if(op.compareTo("invokespecial") == 0) {
         _expected(op, 5, data.size());
         h = _il.append(new INVOKESPECIAL(_cp.addMethodref(data.get(1).toString(),
         data.get(2).toString(),
         data.get(3).toString())));
      }
      else if(op.compareTo("invokestatic") == 0) {
         _expected(op, 5, data.size());
         h = _il.append(new INVOKESTATIC(_cp.addMethodref(data.get(1).toString(),
         data.get(2).toString(),
         data.get(3).toString())));
      }
      else if(op.compareTo("getfield") == 0) {
         _expected(op, 4, data.size());
         String cls = data.get(1).toString();
         String field = data.get(2).toString();
         String signature = data.get(3).toString();
         int index1 = _cp.addFieldref(cls, field, signature);
         GETFIELD gf = new GETFIELD(index1);
         h = _il.append(gf);
      }
      else if(op.compareTo("putfield") == 0) {
         _expected(op, 4, data.size());
         String cls = data.get(1).toString();
         String field = data.get(2).toString();
         String signature = data.get(3).toString();
         int index1 = _cp.addFieldref(cls, field, signature);
         PUTFIELD pf = new PUTFIELD(index1);
         h = _il.append(pf);
      }
      else if(op.compareTo("areturn") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new ARETURN());
      }
      else if(op.compareTo("return") == 0) {
         _expected(op, 1, data.size());
         h = _il.append(new RETURN());
      }
      else if(op.compareTo("anewarray") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = _il.append(new ANEWARRAY(Integer.parseInt(arg)));
      }
      else if(op.compareTo("new_op") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         int addr = _cp.addClass(arg);
         h = _il.append(new NEW(addr));
      }
      else if(op.compareTo("this") == 0) {
         h = _il.append(THIS);
      }
      else if(op.compareTo("ishr") == 0) {
         h = _il.append(new ISHR());
      }
      else if(op.compareTo("dup_x1") == 0) {
         h = _il.append(new DUP_X1());
      }
      else if(op.compareTo("dup") == 0) {
         h = _il.append(DUP);
      }
      else if(op.compareTo("goto") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            GOTO g = new GOTO(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else {
            h = _il.append(new GOTO(h));
         }
      }
      else if(op.compareTo("ifnonnull") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IFNONNULL g = new IFNONNULL(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else {
            h = _il.append(new IFNONNULL(h));
         }
      }
      else if(op.compareTo("ifne") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IFNE g = new IFNE(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else {
            h = _il.append(new IFNE(h));
         }
      }
      else if(op.compareTo("ifge") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IFGE g = new IFGE(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else {
            h = _il.append(new IFGE(h));
         }
      }
      else if(op.compareTo("ifle") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IFLE g = new IFLE(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else {
            h = _il.append(new IFLE(h));
         }
      }
      else if(op.compareTo("iflt") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IFLT g = new IFLT(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else {
            h = _il.append(new IFLT(h));
         }
      }
      else if(op.compareTo("ifnull") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IFNULL g = new IFNULL(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else {
            h = _il.append(new IFNULL(h));
         }
      }
      else if(op.compareTo("ifeq") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IFEQ g = new IFEQ(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else {
            h = _il.append(new IFEQ(h));
         }
      }
      else if(op.compareTo("if_icmplt") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IF_ICMPLT g = new IF_ICMPLT(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else
            h = _il.append(new IF_ICMPLT(h));
      }
      else if(op.compareTo("if_icmple") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IF_ICMPLT g = new IF_ICMPLT(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else
            h = _il.append(new IF_ICMPLE(h));
      }
      else if(op.compareTo("if_icmpne") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IF_ICMPNE g = new IF_ICMPNE(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else
            h = _il.append(new IF_ICMPNE(h));
      }
      else if(op.compareTo("if_icmpge") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString().trim();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IF_ICMPGE g = new IF_ICMPGE(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else {
            h = _il.append(new IF_ICMPGE(h));
         }
      }
      else if(op.compareTo("if_icmpgt") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IF_ICMPGT g = new IF_ICMPGT(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else
            h = _il.append(new IF_ICMPGT(h));
      }
      else if(op.compareTo("if_icmplteq") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IF_ICMPLE g = new IF_ICMPLE(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else
            h = _il.append(new IF_ICMPLE(h));
      }
      else if(op.compareTo("if_icmpgteq") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IF_ICMPGE g = new IF_ICMPGE(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else
            h = _il.append(new IF_ICMPGE(h));
      }
      else if(op.compareTo("if_icmpeq") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IF_ICMPEQ g = new IF_ICMPEQ(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else
            h = _il.append(new IF_ICMPEQ(h));
      }

      else if(op.compareTo("if_icmpneq") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IF_ICMPNE g = new IF_ICMPNE(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else
            h = _il.append(new IF_ICMPNE(h));
      }


      else if(op.compareTo("if_acmpeq") == 0) {
         _expected(op, 2, data.size());
         String arg = data.get(1).toString();
         h = (InstructionHandle)_gotoTbl.get(arg);
         if(h == null) {
            IF_ACMPEQ g = new IF_ACMPEQ(null);
            h = _il.append(g);
            LinkedList l = (LinkedList)_nullTbl.get(arg);
            if(l == null)
               l = new LinkedList();
            l.add(g);
            _nullTbl.put(arg, l);
         }
         else {
            h = _il.append(new IF_ACMPEQ(h));
         }
      }
      else if(op.compareTo("nop") == 0) {
         h = _il.append(new NOP());
      }
      else if(op.compareTo("aconst_null") == 0) {
         h = _il.append(new ACONST_NULL());
      }
      else {
         _error("Unknown instruction: " + op);
         h = null;
      }
      if(lbl != null && h != null) {
         LinkedList gotoList = (LinkedList)_nullTbl.get(lbl);
         if(gotoList != null) {
            Iterator it = gotoList.iterator();
            BranchInstruction br;
            while(it.hasNext()) {
               br = (BranchInstruction)it.next();
               br.setTarget(h);
            }
         }
         _gotoTbl.put(lbl, h);
      }
   }
   
   public void _codeData(String line) {
      StringTokenizer sTok = new StringTokenizer(line, " ");
      LinkedList data = new LinkedList();
      while(sTok.hasMoreTokens())
         data.add(sTok.nextToken());
      if(data.size() != 2) {
         _error("Data can only be: <type name> <id>");
      }
      String type = data.get(0).toString();
      String name = data.get(1).toString();
      if(name.startsWith("global_")) return;
      if(_symTbl.get(name) != null)
         _error(name + ": is in already in the symbol table.");
      int address;
      if(type.compareTo("int") == 0)
         _lg = _mg.addLocalVariable(name, Type.INT, null, null);
      else if(type.compareTo("float") == 0)
         _lg = _mg.addLocalVariable(name, Type.FLOAT, null, null);
      else if(type.compareTo("double") == 0)
         _lg = _mg.addLocalVariable(name, Type.DOUBLE, null, null);
      else if(type.compareTo("long") == 0)
         _lg = _mg.addLocalVariable(name, Type.LONG, null, null);
      else if(type.compareTo("short") == 0)
         _lg = _mg.addLocalVariable(name, Type.SHORT, null, null);
      else if(type.compareTo("char") == 0)
         _lg = _mg.addLocalVariable(name, Type.CHAR, null, null);
      else if(type.compareTo("boolean") == 0)
         _lg = _mg.addLocalVariable(name, Type.BOOLEAN, null, null);
      else if(type.compareTo("byte") == 0)
         _lg = _mg.addLocalVariable(name, Type.BYTE, null, null);
      else
         _lg = _mg.addLocalVariable(name, new ObjectType(type), null, null);
      address = _lg.getIndex();
      _symTbl.put(name, new Integer(address));
   }
   
   public void _error(String msg) {
      System.err.println("line number: " + ((Integer)_lineno.get(_linenoIndex)).intValue());
      System.err.println(msg);
      System.exit(1);
   }
   
   public void _loadCodeIntoClass() {
      Iterator p = _code.iterator();
      String line, name, access, mod, sig, args;
      int i, acc, maxStack = 0;
      Type retType, argTypeArray[];
      StringTokenizer sTok;
      LinkedList list;
      String argNameArray[];
      i = 0;
      while(p.hasNext() && i < 6) {
         line = p.next().toString();
         i++;
      }
      int field_count = 0;
      _symTbl = new Hashtable(_clsTbl);
      MAINLOOP: while(p.hasNext()) {
         line = p.next().toString();
         _linenoIndex++;
         if(line.indexOf(".method ") == 0) {
            _symTbl = new Hashtable(_clsTbl);
            _gotoTbl = new Hashtable();
            _nullTbl = new Hashtable();
            i = line.indexOf(' ');
            if(i < 0)
               _error("Expected method name!");
            name = line.substring(i);
            name = name.trim();
            if(!p.hasNext())
               _error("Expected: .maxStack");
            line = p.next().toString();
            _linenoIndex++;
            i = line.indexOf(' ');
            if(i < 0) 
               _error("Expected integer for maxStack method opiton!");
            try {
               maxStack = Integer.parseInt(line.substring(i).trim());
            }
            catch(NumberFormatException nfe) {
               _error(".maxStack must have an integer argument!");
            }
            if(!p.hasNext())
               _error("Expected: .access");
            line = p.next().toString();
            _linenoIndex++;
            i = line.indexOf(' ');
            if(i < 0)
               access = "";
            else
               access = line.substring(i).trim();
            if(!p.hasNext())
               _error("Expected .modifyers");
            line = p.next().toString();
            _linenoIndex++;
            i = line.indexOf(' ');
            if(i < 0)
               mod = "";
            else
               mod = line.substring(i).trim();
            acc = this._getModiyers(access, mod, _METHOD);
            if(!p.hasNext())
               _error("Expected: .signature");
            line = p.next().toString();
            _linenoIndex++;
            i = line.indexOf(' ');
            if(i < 0)
               _error("Expected: method signature");
            sig = line.substring(i).trim();
            retType = Type.getReturnType(sig);
            argTypeArray = Type.getArgumentTypes(sig);
            if(!p.hasNext())
               _error("Expected: .args");
            line = p.next().toString();
            _linenoIndex++;
            i = line.indexOf(' ');
            if(i < 0)
               args = "";
            else 
               args = line.substring(i).trim();
            sTok = new StringTokenizer(args, " ,");
            list = new LinkedList();
            while(sTok.hasMoreTokens())
               list.add(sTok.nextToken());
            argNameArray = new String[list.size()];
            for(i = 0; i < argNameArray.length; i++) {
               argNameArray[i] = list.get(i).toString();
               if((acc & Constants.ACC_STATIC) == Constants.ACC_STATIC)
                  _symTbl.put(argNameArray[i], new Integer(i));
               else
                  _symTbl.put(argNameArray[i], new Integer(i+1));
            }
            if(!((acc & Constants.ACC_STATIC) == Constants.ACC_STATIC))
               _symTbl.put("this", new Integer(0));
System.err.println(_className+"."+name+"()");
            _il = new InstructionList();
            _mg = new MethodGen(acc,
                                retType,
                                argTypeArray, 
                                argNameArray,
                                name, 
                                _className, 
                                _il, 
                                _cp);
            //_mg.setMaxStack(maxStack);
            if(!p.hasNext())
               _error("Expected: .data");
            line = p.next().toString();
            _linenoIndex++;
            if(line.compareTo(".data") == 0) {
               DATALOOP: while(p.hasNext()) { // .data
                  line = p.next().toString();
                  _linenoIndex++;
                  if(line.compareTo(".code") == 0) {
                     while(p.hasNext()) { // .code
                        line = p.next().toString();
                        _linenoIndex++;
                        if(line.compareTo(".end") == 0) {
                           TableSwitchContext tsc = null;
                           for(int i0 = 0; i0 < tsc_list.size(); i0++) {
                              tsc = (TableSwitchContext)tsc_list.get(i0);
                              if(tsc == null) {
                                 continue;
                              }
                              tsc.target = new InstructionHandle[tsc.label_list.size()];
                              for(int j0 = 0; j0 < tsc.label_list.size(); j0++) {
                                 String temp = tsc.label_list.get(j0).toString();
                                 InstructionHandle h = (InstructionHandle)_gotoTbl.get(temp);
                                 tsc.target[j0] = h;
                              }
                              tsc.tableswitch = new TABLESWITCH(tsc.match, tsc.target, 
                                                (InstructionHandle)_gotoTbl.get(tsc.def));
                              //tsc.print();
                              _il.insert(tsc.index, tsc.tableswitch);
                           }
                           tsc_list = new LinkedList();
                           break DATALOOP;
                        }
                        _codeInstruction(line);
                     }
                     break DATALOOP;
                  }
                  else {
                     _codeData(line);
                  }
               }
            }
            //_mg.setMaxStack(maxStack);
            //try { 
               _mg.setMaxStack();
            //}
            //catch(NullPointerException npe) { 
               //System.err.println("NULL POINTER...");
//npe.printStackTrace(System.err);
            //}
            _cg.addMethod(_mg.getMethod());
         }
         else if(line.indexOf(".field ") == 0) {
            i = line.indexOf(' ');
            if(i < 0)
               _error("Expected filed name!");
            name = line.substring(i+1).trim();
            if(!p.hasNext())
               _error("Expected .access");
            access = p.next().toString(); // .access
            _linenoIndex++;
            i = access.indexOf(' ');
            if(i < 0)
               access = "";
            else 
               access = access.substring(i).trim();
            if(!p.hasNext())
               _error("Expected .modifyers");
            line = p.next().toString(); // .modifyers 
            _linenoIndex++;
            i = line.indexOf(' ');
            if(i < 0)
               mod = "";
            else
               mod = line.substring(i).trim();
            if(mod.equals(""))
               acc = 0;
            else 
               acc = this._getModiyers(access, mod, _FIELD);
            if(!p.hasNext())
               _error("Expected: .type");
            line = p.next().toString(); // .type
            _linenoIndex++;
            i = line.indexOf(' ');
            if(i < 0)
               _error("Expected a type name!");
            String the_type = line.substring(i).trim();
            _clsTbl.put(name, new Integer(field_count));
            field_count++;
            the_type = toASM(the_type);
            Type the_type_obj = Type.getType(the_type);
            FieldGen fg = new FieldGen(acc, the_type_obj, name, _cp);
            _cg.addField(fg.getField());
         }
         else {
            _error("expected .method or .field got: " + line);
         }
      }
      System.out.println("done...");
   }

   public static String toASM(String str) {
      if(str.equals("int"))
         str = "I";
      else if(str.equals("float"))
         str = "F";
      else if(str.equals("long"))
         str = "L";
      else if(str.equals("double"))
         str = "D";
      else if(str.equals("char"))
         str = "C";
      else if(str.equals("boolean"))
         str = "Z";
      else if(str.equals("byte"))
         str = "B";
      else
         str = "L" + str.replace(".", "/") + ";";
      return str;
   }
   
   public static final int _METHOD = 1;
   public static final int _CONSTRUCTOR = 2;
   public static final int _FIELD = 3;
   public static final int _CLASS = 4;
   
   public int _getModiyers(String acc, String mod, int which) {
      int ret = 0;
      if(acc.compareTo("public") == 0)
         ret |= Constants.ACC_PUBLIC;
      else if(acc.compareTo("private") == 0)
         ret |= Constants.ACC_PRIVATE;
      else if(acc.compareTo("protected") == 0)
         ret |= Constants.ACC_PROTECTED;
      else if(acc.length() == 0)
         ;
      else {
         _error("Bad access code!");
      }
      StringTokenizer sTok = new StringTokenizer(mod, " ");
      while(sTok.hasMoreTokens()) {
         mod = sTok.nextToken();
         if(mod.compareTo("static") == 0)
            ret |= Constants.ACC_STATIC;
         else if(mod.compareTo("abstract") == 0 && which == _METHOD)
            ret |= Constants.ACC_ABSTRACT;
         else if(mod.compareTo("final") == 0)
            ret |= Constants.ACC_FINAL;
         else if(mod.compareTo("native") == 0 && which == _METHOD)
            ret |= Constants.ACC_NATIVE;
         else if(mod.compareTo("super") == 0 && which == _CLASS)
            ret |= Constants.ACC_SUPER;
         else if(mod.compareTo("strict") == 0)
            ret |= Constants.ACC_STRICT;
         else if(mod.compareTo("synchronized") == 0) 
            ret |= Constants.ACC_SYNCHRONIZED;
         else if(mod.compareTo("transient") == 0 && which == _FIELD)
            ret |= Constants.ACC_TRANSIENT;
         else if(mod.compareTo("volatile") == 0 && which == _FIELD)
            ret |= Constants.ACC_VOLATILE;
         else {
            _error("Bad modifyer: \"" + mod + "\"");
         }
      }
      return ret;
   }
   
   public asm(String fileName) {
      _fileName = fileName;
      init();
   }

   public void run() {
   try {
      _br = new BufferedReader(new FileReader(_fileName));
      _code = new LinkedList();
      _lineno = new LinkedList();
      _loadCode();
      _linenoIndex = 0;
      if(_code.size() == 0)
         _error("Empty program!");
      
      _className = _code.get(0).toString();
     _linenoIndex++;
      int i = _className.lastIndexOf(' ');
      _className = _className.substring(i+1);
      String access = _code.get(1).toString();
      i = access.indexOf(' ');
      if(i >= 0) {
         access = access.substring(i);
         access = access.trim();
      }
      String modifyers = _code.get(2).toString();
      i = modifyers.indexOf(' ');
      if(i >= 0) {
         modifyers = modifyers.substring(i);
         modifyers = modifyers.trim();
      }
      else 
         modifyers = "";
      int accessFlags = _getModiyers(access, modifyers, _CLASS);
      String ext = _code.get(3).toString();
      i = ext.indexOf(' ');
      _linenoIndex = 3;
      if(i < 0)
         _error("New class must have a base class!");
      ext = ext.substring(i);
      ext = ext.trim();
      String imp = _code.get(4).toString();
      i = imp.indexOf(' ');
      String iArray[] = null;
      if(i >= 0) {
         imp = imp.substring(i);
         imp = imp.trim();
         StringTokenizer sTok = new StringTokenizer(imp, " ");
         LinkedList l = new LinkedList();
         while(sTok.hasMoreTokens())
            l.add(sTok.nextToken());
         iArray = new String[l.size()];
         for(i = 0; i < l.size(); i++) 
            iArray[i] = l.get(i).toString();
      }
      _linenoIndex++;

      String _package = _code.get(5).toString();
      _linenoIndex++;
      
      _cg = new ClassGen(_className, 
                         ext,
                         _fileName, 
                         accessFlags,
                         iArray);
      //_cg.setMajor(46);
      //_cg.setMinor(0);
System.out.println("Major="+_cg.getMajor());
System.out.println("Minor="+_cg.getMinor());
      _cp = _cg.getConstantPool();
      _loadCodeIntoClass();
      //_cg.addEmptyConstructor(Constants.ACC_PUBLIC);
      _il.dispose(); 
      try {
         _cg.getJavaClass().dump(_className + ".class");
      }
      catch(IOException e) {
      System.err.println("line number: " + ((Integer)_lineno.get(_linenoIndex)).intValue());
         System.err.println(e.getMessage()); 
         System.exit(1); 
      }      
      }
      catch(Exception ex) {
      System.err.println("line number: " + ((Integer)_lineno.get(_linenoIndex)).intValue());
         System.err.println(ex.getMessage()); 
         System.exit(1); 
      }
   }
   
   public static void main(String args[]) {
      if(args.length != 1) {
         System.err.println("Usage: asm <asm-file-name>");
         System.exit(1);
      }
      try {
         asm a = new asm(args[0]);
         a.run();
      }
      catch(Throwable t) {
         System.err.println("Unable to assemble file!");
         System.err.println("Message: " + t.getMessage());
         t.printStackTrace();
         System.exit(1);
      }
  }
}
