#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <map>
#include <string>
#include <sstream>

#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>

#include <sys/stat.h>
#include <unistd.h>
#include <time.h>

//#include "ClassFile.h"
#include "jstack.h"
extern "C" {
#include "jni.h"
}

//disassembler
extern "C" {
//#include "disasm2.c"
}

//#define OS_WINDOWS
#define OS_UNIX

#ifdef OS_UNIX
#include <dlfcn.h>
#endif

#ifdef OS_WINDOWS
#include <windows.h>
#endif

using namespace std;

//#define BC_DEBUG 

#define BC_ACONST_NULL 0x01

#define BC_LASTORE 0x50
#define BC_LALOAD 0x2F

#define BC_BASTORE 0x54
#define BC_BALOAD 0x33
#define BC_DALOAD 0x31
#define BC_DASTORE 0x52
#define BC_FASTORE 0x51
#define BC_FALOAD 0x30
#define BC_SASTORE 0x56
#define BC_SALOAD 0x35
#define BC_CASTORE 0x55
#define BC_CALOAD 0x34

#define BC_AALOAD 0x32
#define BC_AASTORE 0x53
#define BC_NEWARRAY 0xBC
#define BC_ANEWARRAY 0xBD
#define BC_ARRAYLENGTH 0xBE
#define BC_IASTORE 0x4F
#define BC_IALOAD 0x2E

#define BC_I2L 0xFFFFFF85
#define BC_I2F 0xFFFFFF86
#define BC_I2D 0xFFFFFF87
#define BC_L2I 0xFFFFFF88
#define BC_L2F 0xFFFFFF89
#define BC_L2D 0xFFFFFF8A
#define BC_F2I 0xFFFFFF8B
#define BC_F2L 0xFFFFFF8C
#define BC_F2D 0xFFFFFF8D
#define BC_D2I 0xFFFFFF8E
#define BC_D2L 0xFFFFFF8F
#define BC_D2F 0xFFFFFF90
#define BC_I2B 0xFFFFFF91
#define BC_I2C 0xFFFFFF92
#define BC_I2S 0xFFFFFF93

#define BC_IF_ACMPEQ 0xA5
#define BC_IF_ACMPNE 0xA6

#define BC_DCMPG 0x98
#define BC_DCMPL 0x97
#define BC_FCMPG 0x96
#define BC_FCMPL 0x95
#define BC_LCMP 0x94

#define BC_IFEQ 0x99
#define BC_IFNE 0x9A
#define BC_IFLT 0x9B
#define BC_IFGE 0x9C
#define BC_IFGT 0x9D
#define BC_IFLE 0x9E
#define BC_IFNONNULL 0xC7
#define BC_IFNULL 0xC6

#define BC_LSHL 0x79
#define BC_LSHR 0x7B
#define BC_LOR 0xFFFFFF81
#define BC_LAND 0x7F
#define BC_LXOR 0xFFFFFF83

#define BC_LCONST_0 0x09
#define BC_LCONST_1 0x0A

#define BC_ISHL 0x78
#define BC_ISHR 0x7A
#define BC_IOR 0xFFFFFF80
#define BC_IAND 0x7E
#define BC_IXOR 0xFFFFFF82

#define  BC_DADD 0x63
#define  BC_DSUB 0x67
#define  BC_DMUL 0x6B
#define  BC_DDIV 0x6F
#define  BC_DREM 0x73
#define  BC_DNEG 0x77

#define  BC_DLOAD_3 0x4A
#define  BC_DLOAD_2 0x49
#define  BC_DLOAD_1 0x48
#define  BC_DLOAD_0 0x47
#define  BC_DLOAD 0x39

#define  BC_DSTORE_3 0x29
#define  BC_DSTORE_2 0x28
#define  BC_DSTORE_1 0x27
#define  BC_DSTORE_0 0x26
#define  BC_DSTORE 0x18

#define  BC_LADD 0x61
#define  BC_LSUB 0x65
#define  BC_LMUL 0x69
#define  BC_LDIV 0x6D
#define  BC_LREM 0x71
#define  BC_LNEG 0x75

#define  BC_LDC2_W 0x14

#define  BC_LLOAD_3 0x21
#define  BC_LLOAD_2 0x20
#define  BC_LLOAD_1 0x1F
#define  BC_LLOAD_0 0x1E
#define  BC_LLOAD 0x16

#define  BC_LSTORE_3 0x42
#define  BC_LSTORE_2 0x41
#define  BC_LSTORE_1 0x40
#define  BC_LSTORE_0 0x3F
#define  BC_LSTORE 0x37

#define BC_INEG 0x74
//#define BC_FCMPG 0x96
#define BC_INVOKESTATIC 0xB8
#define BC_POP 0x57
#define BC_GOTO 0xA7
#define BC_IF_ICMPEQ 0x9F
#define BC_IF_ICMPNE 0xA0
#define BC_IF_ICMPLT 0xA1
#define BC_IF_ICMPGT 0xA3
#define BC_IF_ICMPGE 0xA2
#define BC_IF_ICMPLE 0xA4
#define BC_RETURN 0xB1
#define BC_IPUSH 16
#define BC_BIPUSH 1024
#define BC_LDC 0x12
#define BC_LDC2 (0x12 + 10000)
#define BC_ICONST 4
#define BC_ICONST_0  3
#define BC_ICONST_1  4
#define BC_ICONST_2  5
#define BC_ICONST_3  6
#define BC_ICONST_4  7
#define BC_ICONST_5  8
#define BC_ISTORE_4 61
#define BC_ISTORE_3 62
#define BC_ISTORE_2 60
#define BC_ISTORE 54
#define BC_ILOAD_5 28
#define BC_ILOAD_4 25
#define BC_ILOAD_3 29
#define BC_ILOAD_2 27
#define BC_ILOAD 21
#define BC_ALOAD_1 99
#define BC_ALOAD_0 0x2A
#define BC_ALOAD 0x1990
#define BC_ASTORE 0x3A
#define BC_IADD	 96
#define BC_ISUB	100
#define BC_IMUL 104
#define BC_IDIV 108
#define BC_IREM 0x70
#define BC_INVOKEVIRTUAL 0xB6
#define BC_INVOKESPECIAL 0xB7
#define BC_IINC 0x84

#define BC_NEW 0xBB
#define BC_DUP 0x59
#define BC_APUSH 0x3A
#define BC_PUTFIELD 0xB5
#define BC_GETFIELD 0xB4
#define BC_GETSTATIC 0xB2
#define BC_PUTSTATIC 0xB3

#define BC_FSTORE 0x38
#define BC_FSTORE_0 0x43
#define BC_FSTORE_1 0x44
#define BC_FSTORE_2 0x45
#define BC_FSTORE_3 0x46
#define BC_FLOAD 0x17
#define BC_FLOAD_0 0x22
#define BC_FLOAD_1 0x23
#define BC_FLOAD_2 0x24
#define BC_FLOAD_3 0x25
#define BC_FADD 0x62
#define BC_FSUB 0x66
#define BC_FMUL 0x6A
#define BC_FDIV 0x6E
#define BC_FREM 0x72
#define BC_FNEG 0x76

struct unknown_class { };
struct unknown_method { };

class JavaVM;
class JavaClass;
class JavaMethod;
class JavaField;
class JavaArray;

enum { MAX_BYTECODE = 1024 };

#ifdef OS_WINDOWS
#define RTLD_LAZY 0

void* dlopen(const char* dll, int flags)
{
   return LoadLibrary(dll);
}

void* dlsym(void* dll, const char* name)
{
   return (void*)GetProcAddress((HINSTANCE)dll, name);
}

void dlclose(void* dll)
{
   FreeLibrary((HMODULE)dll);
}
#endif

const char * pname = 0;
void Java_System_loadLibrary(void * arg1, void * arg2, const char * str);

string
to_string3(float value)
{
   enum { MAX = 1024 };
   char buffer[MAX];
   sprintf(buffer, "%f", value);
   return string(buffer);
}

string
to_string2(int index)
{
   enum { MAX = 1024 };
   char buffer[MAX];
   sprintf(buffer, "%d", index);
   return string(buffer);
}

class Instruction {
public:
   string label;
   int opcode;
   string arg1;
   string arg2;
   string arg3;
   string arg4;

   Instruction() {
      opcode = 0;
   }

   Instruction(const Instruction & i) {
      label = i.label;
      opcode = i.opcode;
      arg1 = i.arg1;
      arg2 = i.arg2;
      arg3 = i.arg3;
      arg4 = i.arg4;
   }

   ~Instruction() {

   }

   Instruction & operator=(const Instruction & cp) {
      label = cp.label;
      opcode = cp.opcode;
      arg1 = cp.arg1;
      arg2 = cp.arg2;
      arg3 = cp.arg3;
      arg4 = cp.arg4;
      return *this;
   }
};

typedef vector< string > string_vector_type;
typedef vector< Instruction > instruction_vector_type;

struct bad_array_index { };

class JavaArray {
   char * pointer;
   size_t size;
   size_t unit;
   string type;
public:
   JavaArray(const size_t s, const size_t u, const string & t) {
      size = s;
      type = t;
      unit = u;
      pointer = new char [ size * unit ];
      memset(pointer, 0, size * unit);
   }

   ~JavaArray() {
       delete [] pointer;
   }

   int & get_int(const size_t index) {
      if(index >= size)
         throw bad_array_index();
      int * ret = (int*)(pointer + (index * unit));
      return *ret;
   }
   char & get_char(const size_t index) {
      if(index >= size)
         throw bad_array_index();
      char * ret = (char*)(pointer + (index * unit));
      return *ret;
   }
   short & get_short(const size_t index) {
      if(index >= size)
         throw bad_array_index();
      short * ret = (short*)(pointer + (index * unit));
      return *ret;
   }
   float & get_float(const size_t index) {
      if(index >= size)
         throw bad_array_index();
      float * ret = (float*)(pointer + (index * unit));
      return *ret;
   }
   bool & get_boolean(const size_t index) {
      if(index >= size)
         throw bad_array_index();
      bool * ret = (bool*)(pointer + (index * unit));
      return *ret;

   }
   double & get_double(const size_t index) {
      if(index >= size)
         throw bad_array_index();
      double * ret = (double*)(pointer + (index * unit));
      return *ret;
   }
   long & get_long(const size_t index) {
      if(index >= size)
         throw bad_array_index();
      long * ret = (long*)(pointer + (index * unit));
      return *ret;
   }

   size_t length() {
      return size;
   }
};

class JavaVM {
public:
   //typedef stack< int > stack_type;
   typedef Stack stack_type;
   typedef vector< JavaClass* > class_vector_type;
   typedef vector< void* > dll_vector_type;
   typedef vector< JavaMethod* > native_vector_type;

   string get_string(const string & str);
   JavaClass* get_class(const string & name);
   bool read_line(string & line, ifstream & fin);
   void get_byte_code(const char * buffer2);
   void print_byte_code();
   int* get_address(int ci, int mi, int vi);
   int* get_address2(int ci, int mi, int vi);
   void link_byte_code();
   char* get_const2(int ci);
   int is_native(int class_index, int method_index);
   char* get_native(int class_index, int method_index);
   void clinit();
   void run_class(JavaMethod * p_method);
   JavaClass * load_class(const string & cls);
   void load_class2(const string & cls);
   int get_class_index(const string & cls);
   JavaClass* get_class(int class_index);
   void* get_function(const string & name);
   string get_class_name(const string & str);
   void run(const string & file);
   void do_push(int value);

   stack_type the_stack;
   class_vector_type class_vec;
   JavaClass * p_class;
   JavaMethod * p_method;
   JavaField * p_field;
   dll_vector_type dll_vec;
   native_vector_type native_vec;
   string_vector_type clinit_vec;
   string_vector_type const_vec;
   bool in_data;

   JavaVM(char * sp, size_t maxSize) :the_stack(sp, maxSize){
      p_class = 0;
      p_method = 0;
      p_field = 0;
      in_data = false;
   }

   virtual ~JavaVM();

   JavaVM & operator=(const JavaVM & vm) {
      return *this;
   }
};

string
JavaVM::get_class_name(const string & str)
{
   string ret;
   size_t end = 0;
   size_t i;
   for(i = 0; i < str.size(); i++) {
      if(str[i] == '.') end = i;
   }
   for(i = 0; i < end; i++) {
      ret += str[i];
   }
   return ret;
}

JavaVM * p_jvm = 0;

int
main(int argc, char ** argv)
{
   if(argc < 2) {
      cerr << "usage: " << argv[0] << " <class-name> [-stackSize size]" << endl;
      exit(1);
   }

   pname = argv[1];   

   try {
      size_t maxStack = 1024 * 64;

      for(int i = 0; i < argc; i++) {
         if(strcmp(argv[i], "-maxStack") == 0) {
            i++;
            if(i < argc) {
               maxStack = atoi(argv[i]);
            }
         }
      }

      char * sp = (char*)alloca(maxStack);

      JavaVM jvm(sp, maxStack);

      p_jvm = &jvm;

      jvm.run(pname);
   }
   catch(stack_exception se) {
      cerr << "Stack exception..." << endl;
      cerr << "Message: " << se.message << endl;
      exit(1);
   }
   catch(...) {
      cerr << "Unknown exception..." << endl;
      exit(1);
   }

   return 0;
}

int
System(const string & cmd)
{
   int ret = system(cmd.c_str());
   return ret;
}

bool
is_native_type(const string & t) 
{
   bool ret = false;
   if(t == "int"
      || t == "float"
      || t == "long"
      || t == "short"
      || t == "char"
      || t == "byte"
      || t == "boolean"
      || t == "double") {
      ret = true;
   }
   return ret;
}

extern "C" {
extern void disassemble(const char * file, const char * out);
}

bool read_line(ifstream & fin, string & line)
{
   bool ret = false;
   line = "";
   char ch = fin.get();
   while(fin) {
      ret = true;
      if(ch == '\n') break;
      line += ch;
      ch = fin.get();
   }
   return ret;
}

string_vector_type tokenize(const string & line)
{
   string_vector_type vec;
   string temp;
   for(size_t i = 0; i < line.size(); i++) {
      if(line[i] == '\"') {
         if(temp.size()) {
            vec.push_back(temp);
            temp = "";
         }
         temp += line[i];
         i++;
         while(i < line.size()) {
            if(line[i] == '\"') {
               break;
            }
            temp += line[i];
            i++;
         }
         temp += line[i];
         vec.push_back(temp);
         temp = "";
      }
      else if(isspace(line[i])) {
         if(temp.size()) {
            vec.push_back(temp);
            temp = "";
         }
      }
      else {
         temp += line[i];
      }
   }
   if(temp.size()) vec.push_back(temp);
   return vec;
}

string to_string(string_vector_type & vec)
{
   string ret;
   for(size_t i = 0; i < vec.size(); i++) {
      ret += vec[i];
      if(vec[i].size()) {
         if(vec[i][0] == 'L') {
            ret += "\t";
         }
         else {
            ret += " ";
         }
      }
   }
   return ret;
}

string trim(const string & str) {
   string temp;
   for(size_t i = 0; i < str.size(); i++) {
      if(str[i] == ',')
         ;
      else
         temp += str[i];
   }
   return temp;
}


string to_easy(string_vector_type & vec)
{
   string ret,label;
   size_t offset = 0;
   bool done = false;
   if(vec.size()) {
      offset = 0;
      string temp = vec[offset];
      if(temp != "ldc" && temp != "ldc2") {
         if(temp.size()) {
            if(temp[0] == 'L') {
               label = temp;
               offset++;
            }
         }
      }
      temp = vec[offset];
      if(temp == "goto") {
         ret = "goto L" + vec[offset+1];
      }
      else if(temp == "iinc") {
         ret = "iinc temp" + trim(vec[offset+1]) + " " + vec[offset+2];
      }

      else if(temp == "putfield") {
         ret = "putfield " + vec[offset+2];
      }
      else if(temp == "getfield") {
         ret = "getfield " + vec[offset+2];
      }
      else if(temp == "getstatic") {
         ret = "getstatic " + vec[offset+2];
      }
      else if(temp == "putstatic") {
         ret = "putstatic " + vec[offset+2];
      }

      else if(temp == "apush_0") {
         ret = "apush temp0";
      }
      else if(temp == "aload_0") {
         ret = "aload temp0";
      }
      else if(temp == "astore_0") {
         ret = "astore temp0";
      }
      else if(temp == "apush_1") {
         ret = "apush temp1";
      }
      else if(temp == "aload_1") {
         ret = "aload temp1";
      }
      else if(temp == "astore_1") {
         ret = "astore temp1";
      }


      else if(temp == "iconst_0") {
         ret = "ipush 0";
      }
      else if(temp == "iconst_1") {
         ret = "ipush 1";
      }
      else if(temp == "iconst_2") {
         ret = "ipush 2";
      }
      else if(temp == "iconst_3") {
         ret = "ipush 3";
      }
      else if(temp == "iconst_4") {
         ret = "ipush 4";
      }
      else if(temp == "iconst_5") {
         ret = "ipush 5";
      }
      else if(temp == "iconst") {
         ret = "ipush " + vec[offset + 1];
      }
      else if(temp == "sipush") {
         ret = "ipush " + vec[offset + 1];
      }
      else if(temp == "bipush") {
         ret = "ipush " + vec[offset + 1];
      }

      else if(temp == "iload_0") {
         ret = "iload temp0";
      }
      else if(temp == "iload_1") {
         ret = "iload temp1";
      }
      else if(temp == "iload_2") {
         ret = "iload temp2";
      }
      else if(temp == "iload_3") {
         ret = "iload temp3";
      }
      else if(temp == "iload_4") {
         ret = "iload temp4";
      }
      else if(temp == "iload_5") {
         ret = "iload temp5";
      }
      else if(temp == "iload") {
         ret = "iload temp" + vec[offset + 1];
      }

      else if(temp == "istore_0") {
         ret = "istore temp0";
      }
      else if(temp == "istore_1") {
         ret = "istore temp1";
      }
      else if(temp == "istore_2") {
         ret = "istore temp2";
      }
      else if(temp == "istore_3") {
         ret = "istore temp3";
      }
      else if(temp == "istore_4") {
         ret = "istore temp4";
      }
      else if(temp == "istore_5") {
         ret = "istore temp5";
      }
      else if(temp == "istore") {
         ret = "istore temp" + vec[offset + 1];
      }

/*BUG NEW*/
      else if(temp == "new") {
         ret = "new " + vec[offset + 2];
         offset++;
      }

      else {
         done = true;
         ret = to_string(vec);
      }
      if(!done) {
/*BUG*/
         ret = label + "\t" + ret;
      }
      if(ret.find("//") != string::npos) {
         ret = "";
      }
   }
   return ret;
}

void make_code_easy(const string & infile, const string & outfile)
{
   ifstream fin(infile.c_str());
   ofstream fout(outfile.c_str(), ios::ate | ios::trunc);
   if(fin && fout) {
      string line,str,temp;
      string_vector_type vec;
      while(read_line(fin, line)) {
         vec = tokenize(line);
         if(vec.size() == 0)  {
            fout << "\n" << flush;
         }
         else if(vec[1] == "if_icmpge") {
            vec[2] = "L" + vec[2];
         }
         else if(vec[0].size()) {
            if(vec[0][0] == '.') {
               str = "";
            }
            else if(vec[0][0] == 'L') {
               str = "";
            }
            else {
               str  = "\t";
            }
         }
         temp = to_easy(vec);
         if(temp.size()) {
            fout << str + to_easy(vec) << endl << flush;
         }
      }
      fin.close();
      fout.flush();
      fout.close();
   }
}


void
JavaVM::load_class2(const string & cls)
{
//cout << "load_class2(" << cls << ")" << endl;

   if(is_native_type(cls)) return;

   string temp = cls + ".asm";

   //java::ClassFile class_file(cls);

   string name = cls + ".class";

   struct stat lm_temp, lm_name;

   stat(temp.c_str(), &lm_temp);

   stat(name.c_str(), &lm_name);

   time_t temp_mtime = lm_temp.st_mtime;

   time_t name_mtime = lm_name.st_mtime;

   if(name_mtime > temp_mtime) {
      string temp2 = temp + ".temp";
      disassemble(name.c_str(), temp.c_str());
      make_code_easy(temp, temp2);
      unlink(temp.c_str());
      rename(temp2.c_str(), temp.c_str());

      //string cmd = "java -classpath .:bcel-5.2.jar dis_asm " + name + " " + temp + " ";
      //string cmd = "./disasm " + name + " > " + temp;

      //if(System(cmd) == 0) {

      //}
   }

   ifstream fin(temp.c_str(), ios::in);
   if(fin) {
      string line;
      while(read_line(line, fin)) {
         get_byte_code(line.c_str());
      }
      fin.close();
   }
}

enum DATA_TYPE {
   NIL_TYPE,
   CHAR_TYPE,
   SHORT_TYPE,
   INT_TYPE,
   FLOAT_TYPE,
   DOUBLE_TYPE,
   LONG_TYPE,
   POINTER_TYPE
};

union DATA_VALUE {
   char cval;
   short sval;
   int ival;
   float fval;
   double dval;
   long long lval;
   char * ptr;
};

class DATA {
public:
   DATA_TYPE type;
   DATA_VALUE data;
   size_t reference_count;

   DATA() { 
      reference_count = 0U; 
      type = NIL_TYPE; 
   }

   DATA(const DATA & d) {
      type = d.type;
      memcpy(&data, &d.data, sizeof(DATA_VALUE));
      reference_count = d.reference_count;
   }

   DATA & operator=(const DATA & d) {
      reference_count--;
      data = d.data;
      memcpy(&data, &d.data, sizeof(DATA_VALUE));
      type = d.type;
      reference_count = d.reference_count;
      return *this;
   }

   ~DATA() { 
      reference_count--;
   }
};

class Var {
public:
   string type;
   string name;
   DATA data;

   Var(const string & t,
       const string & n,
       int d) 
   :type(t), name(n) {
      data.data.ival = d; 
   }
 
   Var() {  
   }

   Var(const Var & v) { 
      type = v.type; 
      name = v.name; 
      data = v.data; 
   }

   virtual ~Var() { 

   }

   Var & operator=(const Var & cp) {
      type = cp.type;
      name = cp.name;
      data = cp.data;
      return *this;
   }
};

typedef vector< Var > var_vector_type;

class JavaMethod {
public:
   string name;
   string return_type;
   string type_signature;
   int is_native;
   void* native_code;
   JavaClass * p_class;
   instruction_vector_type code;
   var_vector_type var_vec;

   JavaMethod() { 
      is_native = 0;
      native_code = 0;
      p_class = 0;
   }

   JavaMethod(const JavaMethod & cp) {
      name = cp.name;
      return_type = cp.return_type;
      type_signature = cp.type_signature;
      is_native = cp.is_native;
      p_class = cp.p_class;
      code = cp.code;
      var_vec = cp.var_vec; 
   }

   ~JavaMethod() {
   }

   int get_param_count() {
      int ret = 0;
      for(size_t i = 0; i < type_signature.size(); i++) {
         if(type_signature[i] == ';') {
            ret++;
         }
      }
      ret += var_vec.size();
      return ret;
   }

   JavaMethod & operator=(const JavaMethod & cp) {
      name = cp.name;
      return_type = cp.return_type;
      type_signature = cp.type_signature;
      is_native = cp.is_native;
      p_class = cp.p_class;
      code = cp.code;
      var_vec = cp.var_vec;
      return *this;
   }

   Var & get_variable(int index) {
      return var_vec[index];
   }

   void put_variable(const string & type, const string & name) {
      Var v;
      v.name = name;
      v.type = type;
      var_vec.push_back(v);
   }

   int get_variable_index(const string & name) {
      int i;
      for(i = 0; i < (int)var_vec.size(); i++) {
         if(var_vec[i].name == name) {
            break;
         }
      }
      if(i == (int)var_vec.size())
         i = -1;
      return i;
   }

   void put_var(int index, int value) {
      var_vec[index].data.data.ival = value;
   }
};

class JavaField {
public:
   string type;
   string name;
   DATA data;

   JavaField() { }
   JavaField(const string & name) { this->name = name; }
   JavaField(const JavaField & f) { data = f.data; type = f.type; name = f.name; }
   ~JavaField() { }
   JavaField & operator=(const JavaField & cp) {
      data = cp.data;
      return *this;
   }
};

string to_string(const int index);

class JavaClass {
public:
   typedef vector< Var > var_vector_type;
   typedef map< string, int > jmp_map_type;
   typedef vector< pair< string, int > > addr_vector_type;
   typedef vector< string > const_vector_type;
   typedef vector< JavaMethod* > method_vector_type;
   typedef vector< JavaField* > field_vector_type;

   JavaClass * super;
   var_vector_type var_vec;
   jmp_map_type jmp_map;
   addr_vector_type addr_vec;
   const_vector_type const_vec;
   method_vector_type method_vec;  
   field_vector_type field_vec;
   string name;

   JavaClass() { super = 0; }
   JavaClass(const JavaClass & cp) { 
      var_vec = cp.var_vec;
      jmp_map = cp.jmp_map;
      addr_vec = cp.addr_vec;
      const_vec = cp.const_vec;
      super = cp.super;

      for(size_t i = 0; i < cp.method_vec.size(); i++) {
         method_vec.push_back(new JavaMethod(*(cp.method_vec[i])));
      }

      for(size_t i = 0; i < cp.field_vec.size(); i++) {
         field_vec.push_back(new JavaField(*(cp.field_vec[i])));
      }

      name = cp.name;
   }
   ~JavaClass() { 
      size_t i;
      for(i = 0; i < method_vec.size(); i++)
         delete method_vec[i];
      method_vec.clear();
      for(i = 0; i < field_vec.size(); i++)
         delete field_vec[i];
      field_vec.clear();
   }

   JavaField * get_field(const size_t & index) {
      return field_vec[index];
   }

   JavaField * get_field(const string & name) {
      JavaField * p_field = 0;
      for(size_t i = 0; i < field_vec.size(); i++) {
         if(field_vec[i]->name == name) {
            return field_vec[i];
         }
      }
      return p_field;
   }

   JavaClass & operator=(const JavaClass & cp) {
      return *this;
   }

   int get_field_index(const string & name) {
      int ret = -1;
      for(int i = 0; i < (int)field_vec.size(); i++) {
         if(field_vec[i]->name == name) {
            ret = i;
            break;
         }
      }
      return ret;
   }

   int get_method_index(const string & name) {
      int ret = -1;
      for(size_t i = 0; i < method_vec.size(); i++) {
         if(method_vec[i]->name == name) {
            ret = i;
            break;
         }
      } 
      return ret;
   }

   JavaMethod* get_method(const string & str) {
      JavaMethod * p_method = 0;
      for(size_t i = 0; i < method_vec.size(); i++) {
         if(method_vec[i]->name == str) {
            p_method = method_vec[i];
            break;
         }
      }
      return p_method;
   }

   JavaMethod * get_method(const size_t i) {
      return method_vec[i];
   }

   JavaClass * new_instance() {
      JavaClass * pc = new JavaClass(*this);
      if(super) {
         pc->super = new JavaClass(*this->super);
         for(size_t i = 0; i < pc->super->method_vec.size(); i++) {
            for(size_t j = 0; j < pc->super->method_vec[i]->code.size(); j++) {
               switch(pc->super->method_vec[i]->code[j].opcode) {
               case BC_DLOAD:
               case BC_DSTORE:
               case BC_LLOAD:
               case BC_LSTORE:
               case BC_ILOAD:
               case BC_FLOAD:
               case BC_ISTORE:
               case BC_FSTORE:
               case BC_ALOAD:
               case BC_ASTORE:
               case BC_IINC:
                  pc->super->method_vec[i]->code[j].arg1 = to_string2((int)(pc));
               break;
               }
            }
         }
      }
      for(size_t i = 0; i < pc->method_vec.size(); i++) {
         for(size_t j = 0; j < pc->method_vec[i]->code.size(); j++) {
            switch(pc->method_vec[i]->code[j].opcode) {
            case BC_DLOAD:
            case BC_DSTORE:
            case BC_LLOAD:
            case BC_LSTORE:
            case BC_FLOAD:
            case BC_FSTORE:
            case BC_ILOAD:
            case BC_ISTORE:
            case BC_ALOAD:
            case BC_ASTORE:
            case BC_IINC:
               pc->method_vec[i]->code[j].arg1 = to_string2((int)(pc));
            break;
            }
         }
      }
      return pc;
   }
};

int
JavaVM::is_native(int class_index, int method_index)
{
   JavaClass * c = class_vec[class_index];
   JavaMethod * m = c->method_vec[method_index];
   return m->is_native;
}

char*
JavaVM::get_native(int class_index, int method_index)
{
   JavaClass * c = class_vec[class_index];
   JavaMethod * m = c->method_vec[method_index];
   return (char*)(m->native_code);
}

int
JavaVM::get_class_index(const string & name)
{
   int ret = -1;
   for(size_t i = 0; i < class_vec.size(); i++) {
      if(class_vec[i]->name == name) {
         ret = i;
         break;
      }
   }
   return ret;
}

JavaClass* 
JavaVM::get_class(int index)
{
   return class_vec[index];
}

JavaClass* 
JavaVM::get_class(const string & name)
{
   JavaClass * p = 0;
   for(size_t i = 0; i < class_vec.size(); i++) {
      if(class_vec[i]->name == name) {
         p = class_vec[i];
         break;
      }
   }
   return p;
}

string
JavaVM::get_string(const string & str)
{
   string ret;
   bool in = false;
   for(size_t i = 0; i < str.size(); i++) {
      if(str[i] == '\"')
         in = !in;
      else if(in)
         ret += str[i];
   }
   return ret;
}

char*
JavaVM::get_const2(int cindex)
{
   return (char*)(const_vec[cindex].c_str());
}

int *
JavaVM::get_address(int cindex, int mindex, int vindex)
{
   int * p = 0;
   if(cindex < (int)class_vec.size()) {
      if(mindex < (int)class_vec[cindex]->method_vec.size()) {
         if(vindex < (int)class_vec[cindex]->method_vec[mindex]->var_vec.size()) {
            p = &(class_vec[cindex]->method_vec[mindex]->var_vec[vindex].data.data.ival);
         }
      }
   }
   return p;
}

void 
JavaVM::link_byte_code()
{
}

void
JavaVM::clinit()
{
   for(size_t i = 0; i < clinit_vec.size(); i++) {
      JavaClass * pc = get_class(clinit_vec[i]);
      JavaMethod * m = pc->get_method("<clinit>");
      run_class(m);
   }
}

bool
JavaVM::read_line(string & str, ifstream & fin)
{
   bool ret = false; 
   char ch;
   ch = fin.get();
   str = "";
   while(fin) {
      ret = true;
      if(ch == '\n') break;
      str += ch;
      ch = fin.get();
   } 
   return ret;
}

JavaClass* 
JavaVM::load_class(const string & cname) 
{
   string name;
   size_t i;
   for(i = 0; i < cname.size(); i++) {
      if(cname[i] == '.') 
         name += "/";
      else
         name += cname[i];
   }

   JavaClass * claxx = p_class;
   JavaMethod * method = p_method;
   p_class = 0;
   p_method = 0;
   string n = name + ".asm";

   load_class2(name);

   JavaClass * ret = p_class;
   p_class = claxx;
   p_method = method;

   return ret;
}

string
to_cname(const string & str)
{
   string ret;
   for(size_t i = 0; i < str.size(); i++) {
      if(str[i] == '.')
         ret += "_";
      else
         ret += str[i];
   }
   return ret;
}

void
Java_System_loadLibrary(void * arg1, void * arg2, const char * str)
{
   string ext;
#ifdef OS_UNIX
   ext = ".so";
#endif
#ifdef OS_WINDOWS
   ext = ".dll";
#endif
   string temp2 = str;
   for(size_t i = 0; i < temp2.size(); i++) {
      if(temp2[i] == '.')
         temp2[i] = '_';
   }
   str = temp2.c_str();
   string dll_name = string("lib") + string(str) + ext;
   void * dll = dlopen(dll_name.c_str(), RTLD_LAZY);
   if(dll) {
      p_jvm->dll_vec.push_back(dll);
      for(size_t j = 0; j < p_jvm->class_vec.size(); j++) {
         for(size_t i = 0; i < p_jvm->class_vec[j]->method_vec.size(); i++) {
            if(p_jvm->class_vec[j]->method_vec[i]->is_native) {
               if(p_jvm->class_vec[j]->method_vec[i]->native_code == 0) {
                  string temp = "Java_" + to_cname(p_jvm->class_vec[j]->name) + "_" + p_jvm->class_vec[j]->method_vec[i]->name;
                  p_jvm->class_vec[j]->method_vec[i]->native_code = dlsym(dll, temp.c_str());
               }
            }
         }
      }
      for(size_t i = 0; i < p_jvm->native_vec.size(); i++) {
         if(p_jvm->native_vec[i]->native_code == 0) {
            string temp = "Java_" + to_cname(p_jvm->native_vec[i]->p_class->name) + "_" + p_jvm->native_vec[i]->name;
            p_jvm->native_vec[i]->native_code = p_jvm->get_function(temp);
         }
      }
   }
   else {
      cerr << "Unable to load DLL..." << endl;
      exit(1);
   }
}

void*
JavaVM::get_function(const string & name)
{
   void * ret = 0;
   void * temp;
   for(size_t i = 0; i < dll_vec.size(); i++) {
      temp = dlsym(dll_vec[i], name.c_str());
      if(temp != NULL) {
         ret = temp;
         break;
      }
   }
   return ret;
}


string get_method_name(const string & str)
{
   string ret;
   size_t index = 0;
   for(size_t i = 0; i < str.size(); i++) {
      if(str[i] == '.') 
         index = i + 1;
   }
   ret = str.substr(index);
   return ret;
}

string get_class_name(const string & str)
{
   string ret;
   size_t index = 0;
   for(size_t i = 0; i < str.size(); i++) {
      if(str[i] == '.') 
         index = i;
   }
   ret = str.substr(0, index);
   return ret;
}


void
JavaVM::get_byte_code(const char * buffer2)
{
   char * buffer = new char[strlen(buffer2) + 1];
   strcpy(buffer, buffer2);
   char * ptr = strtok(buffer, "\r\n\t, ");
   vector< string > vec;
   while(ptr != NULL) {
      vec.push_back(string(ptr));
      ptr = strtok(NULL, "\r\n\t, ");
   }
   delete [] buffer;
   string label;
   if(vec.size()) {
      if(vec[0][0] == 'L' && !in_data) {
         label = vec[0];
         vec.erase(vec.begin());
      }
      else {
         label = "";
      }
      if(vec[0] == "bipush") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_BIPUSH;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ipush") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IPUSH;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ishl") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ISHL;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ishr") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ISHR;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ior") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IOR;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "iand") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IAND;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ixor") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IXOR;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
/*
#define BC_I2L 0xFFFFFF85
#define BC_I2F 0xFFFFFF86
#define BC_I2D 0xFFFFFF87
#define BC_L2I 0xFFFFFF88
#define BC_L2F 0xFFFFFF89
#define BC_L2D 0xFFFFFF8A
#define BC_F2I 0xFFFFFF8B
#define BC_F2L 0xFFFFFF8C
#define BC_F2D 0xFFFFFF8D
#define BC_D2I 0xFFFFFF8E
#define BC_D2L 0xFFFFFF8F
#define BC_D2F 0xFFFFFF90
#define BC_I2B 0xFFFFFF91
#define BC_I2C 0xFFFFFF92
#define BC_I2S 0xFFFFFF93
*/


      else if(vec[0] == "i2l") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_I2L;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "i2f") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_I2F;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "i2d") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_I2D;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "l2i") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_L2I;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "l2f") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_L2F;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "l2d") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_L2D;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "f2i") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_F2I;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "f2l") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_F2L;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "f2d") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_F2D;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "d2i") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_D2I;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "d2l") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_D2L;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "d2f") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_D2F;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "i2b") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_I2B;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "i2c") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_I2C;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "i2s") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_I2S;
         p_method->code.push_back(inst);
      }

      else if(vec[0] == "aconst_null") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ACONST_NULL;
         p_method->code.push_back(inst);
      }
/*
#define BASTORE 0x54 
#define BALOAD 0x33 
#define DALOAD 0x31 
#define DASTORE 0x52 
#define FASTORE 0x51 
#define FALOAD 0x30 
#define SASTORE 0x56 
#define SALOAD 0x35 
#define CASTORE 0x55 
#define CALOAD 0x34 
*/
      else if(vec[0] == "lastore") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LASTORE;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "laload") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LALOAD;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "bastore") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_BASTORE;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "baload") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_BALOAD;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "dastore") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DASTORE;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "daload") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DALOAD;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fastore") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FASTORE;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "faload") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FALOAD;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "sastore") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_SASTORE;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "saload") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_SALOAD;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "castore") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_CASTORE;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "caload") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_CALOAD;
         p_method->code.push_back(inst);
      }




/*
#define BC_AALOAD 0x32
#define BC_AASTORE 0x53
#define BC_NEWARRAY 0xBC
#define BC_ANEWARRAY 0xBD
#define BC_ARRAYLENGTH 0xBE
#define BC_IASTORE 0x4F
#define BC_IALOAD 0x2E
*/
      else if(vec[0] == "aaload") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_AALOAD;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "aastore") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_AASTORE;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "anewarray") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ANEWARRAY;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "newarray") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_NEWARRAY;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "arraylength") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ARRAYLENGTH;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "iastore") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IASTORE;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "iaload") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IALOAD;
         p_method->code.push_back(inst);
      }

      else if(vec[0] == "ifeq") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IFEQ;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ifne") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IFNE;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "iflt") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IFLT;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ifge") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IFGE;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ifgt") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IFGT;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ifle") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IFLE;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ifnonnull") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IFNONNULL;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ifnull") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IFNULL;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }

      else if(vec[0] == "dcmpg") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DCMPG;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "dcmpl") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DCMPL;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fcmpg") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FCMPG;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fcmpl") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FCMPL;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "lcmp") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LCMP;
         p_method->code.push_back(inst);
      }



      else if(vec[0] == "lshl") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LSHL;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "lshr") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LSHR;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "lor") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LOR;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "lxor") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LXOR;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "land") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LAND;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "lconst_0") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LCONST_0;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "lconst_1") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LCONST_1;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }

      else if(vec[0] == "iconst_0") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IPUSH;
         inst.arg1 = "0";
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "iconst_1") {
        Instruction inst;
         inst.label = label;
         inst.opcode = BC_IPUSH;
         inst.arg1 = "1";
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "iconst_2") {
        Instruction inst;
         inst.label = label;
         inst.opcode = BC_IPUSH;
         inst.arg1 = "2";
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "iconst_3") {
        Instruction inst;
         inst.label = label;
         inst.opcode = BC_IPUSH;
         inst.arg1 = "3";
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "iconst_4") {
        Instruction inst;
         inst.label = label;
         inst.opcode = BC_IPUSH;
         inst.arg1 = "4";
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "iconst_5") {
        Instruction inst;
         inst.label = label;
         inst.opcode = BC_IPUSH;
         inst.arg1 = "5";
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "iinc") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IINC;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = to_string2(p_method->get_variable_index(vec[1]));
         inst.arg4 = vec[2];
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[iinc " << inst.arg1 << " " << inst.arg2 << " " << inst.arg3 << " " << inst.arg4 << "]" << endl;
#endif
      }
      else if(vec[0] == "astore_0") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ASTORE;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = to_string2(0);
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[astore_0]" << endl;
#endif
      }
      else if(vec[0] == "astore_1") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ASTORE;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = to_string2(1);
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[astore_1]" << endl;
#endif
      }
      else if(vec[0] == "astore_2") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ASTORE;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = to_string2(2);
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[astore_1]" << endl;
#endif
      }
      else if(vec[0] == "astore_3") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ASTORE;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = to_string2(3);
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[astore_1]" << endl;
#endif
      }

      else if(vec[0] == "astore" || vec[0] == "apush") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ASTORE;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = to_string2(p_method->get_variable_index(vec[1]));
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[astore " + vec[1] + "]" << endl;
#endif
      }
      else if(vec[0] == "new") {
         string the_class = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_NEW;
         inst.arg1 = the_class;
         if(get_class(the_class) == 0) {
            load_class(the_class);
         }
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[new " + the_class + "]" << endl;
#endif
      }

      else if(vec[0] == "putstatic") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_PUTSTATIC;
         string c = get_class_name(vec[1]);
         if(get_class(c) == 0) {
            load_class(c);
         }
         string f = get_method_name(vec[1]);
         JavaClass * p_class2 = get_class(c);
         int cindex = get_class_index(c);
         int findex = p_class2->get_field_index(f);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(findex);
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[putstatic " + c + " " + f + "]" << endl;
#endif
      }

      else if(vec[0] == "getstatic") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_GETSTATIC;
         string c = get_class_name(vec[1]);
         if(get_class(c) == 0) {
            load_class(c);
         }
         string f = get_method_name(vec[1]);
         JavaClass * p_class2 = get_class(c);
         int cindex = get_class_index(c);
         int findex = p_class2->get_field_index(f);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(findex);
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[getstatic " + c + " " + f + "]" << endl;
#endif
     }
     else if(vec[0] == "getfield") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_GETFIELD;
         inst.arg1 = to_string2(p_class->get_field_index(get_method_name(vec[1])));
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[getfield]" << endl;
#endif
      }
      else if(vec[0] == "putfield") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_PUTFIELD;
         inst.arg1 = to_string2(p_class->get_field_index(get_method_name(vec[1])));
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[putfield]" << endl;
#endif
      }
      else if(vec[0] == "dup") {
#ifdef BC_DEBUG
cout << "[dup]" << endl;
#endif
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DUP;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ldc2_w") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LDC2_W;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "ldc") {
#ifdef BC_DEBUG
cout << "[ldc]" << endl;
#endif
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LDC;

         if(isdigit(vec[1][0])) {
            float f = atof(vec[1].c_str());
            inst.opcode = BC_LDC2;
            inst.arg1 = to_string3(f);
         } 
         else {
            string const_string = get_string(buffer2);
            int index = -1;
            bool found = false;
            for(size_t i = 0; i < const_vec.size(); i++) {
               if(const_string == const_vec[i]) {
                  index = i;
                  found = true;
                  break;
               } 
            }
            if(found) {
               inst.arg1 = to_string2(index);//const_vec.size());

               //const_vec.push_back(const_string);
            }
            else {
               inst.arg1 = to_string2(const_vec.size());

               const_vec.push_back(const_string);
            }
         }

         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[ldc " << inst.arg1 << "]" << endl;
#endif
      }
      else if(vec[0] == ".extends") {
         JavaClass * p_class2 = get_class(vec[1]);
         if(p_class2 == 0) {
            load_class(vec[1]);
            p_class2 = get_class(vec[1]);
         }
         p_class->super = p_class2;
      }
      else if(vec[0] == ".class") {
         string class_name = vec[1];
         p_class = new JavaClass();
         p_class->name = class_name;
         p_method = 0;
         class_vec.push_back(p_class);
#ifdef BC_DEBUG
cout << "[class: " << class_name << "]" << endl;
#endif
      }
      else if(vec[0] == ".extends") {
         string class_name = vec[1];
         if(get_class(class_name) == 0) {
            load_class(class_name); 
         }
      }
      else if(vec[0] == ".type") {
         p_field->type = vec[1];
         if(get_class(p_field->type) == 0) {
            load_class(p_field->type);
         }
         p_field = 0;
      }
      else if(vec[0] == ".field") {
         p_field = new JavaField(vec[1]);
         p_class->field_vec.push_back(p_field);
      }
      else if(vec[0] == ".method") {
         string method_name = vec[1];
         if(method_name == "<clinit>") {
            clinit_vec.push_back(p_class->name);
         }
         p_method = new JavaMethod();
         p_method->p_class = p_class;
         p_method->name = method_name;
         p_method->is_native = 0;
         p_method->native_code = 0;
         p_class->method_vec.push_back(p_method);

#ifdef BC_DEBUG
cout << "[method: " << p_class->name << "." << method_name << "]" << endl;
#endif
      }
      else if(vec[0] == ".modifiers") {
         //bool is_static = false;
         if(p_method) {
            for(size_t i = 1; i < vec.size(); i++) {
               if(vec[i] == "native") {
                  if(p_class->name == "java.lang.System" && p_method->name == "loadLibrary") {
                     p_method->is_native = 1;

                     p_method->native_code = (void*)Java_System_loadLibrary;
                  }
                  else {
                     p_method->is_native = 1;

                     native_vec.push_back(p_method);
                  }
               }
               //else if(vec[i] == "static") {
                  //is_static = true;
               //}
            }
         }

#ifdef BC_DEBUG
cout << "[.modifiers";
for(size_t i = 1; i < vec.size(); i++) {
   cout << " ";
   cout << vec[i];
}
cout << "]" << endl;
#endif
      }
      else if(vec[0] == ".end") {
         //for(int i = 0; i < MAX_BYTECODE; i++) {
            //p_method->byte_code[i] = byte_code[i];
         //}
         map< string, int > smap;
         for(int i = 0; i < (int)p_method->code.size(); i++) {
            smap[p_method->code[i].label] = i;
         }
         for(int i = 0; i < (int)p_method->code.size(); i++) {
             if(p_method->code[i].opcode == BC_IF_ICMPEQ
                || p_method->code[i].opcode == BC_IF_ICMPNE
                || p_method->code[i].opcode == BC_IF_ICMPLT
                || p_method->code[i].opcode == BC_IF_ICMPGT
                || p_method->code[i].opcode == BC_IF_ICMPLE
                || p_method->code[i].opcode == BC_IF_ICMPGE

                || p_method->code[i].opcode == BC_IF_ACMPEQ
                || p_method->code[i].opcode == BC_IF_ACMPNE

                || p_method->code[i].opcode == BC_IFEQ
                || p_method->code[i].opcode == BC_IFNE
                || p_method->code[i].opcode == BC_IFLT
                || p_method->code[i].opcode == BC_IFGE
                || p_method->code[i].opcode == BC_IFGT
                || p_method->code[i].opcode == BC_IFLE
                || p_method->code[i].opcode == BC_IFNONNULL
                || p_method->code[i].opcode == BC_IFNULL

                || p_method->code[i].opcode == BC_GOTO) {
                p_method->code[i].arg1 = to_string2(smap[p_method->code[i].arg1]);
             }
         }
         //p_method->code_size = offset;
         //offset = 0;
         //memset(byte_code, 0, MAX_BYTECODE);
#ifdef BC_DEBUG
cout << "[.end]" << endl;
#endif
      }
      else if(vec[0] == "goto") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_GOTO;
         inst.arg1 = vec[1];
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[goto " << vec[1] << "]" << endl;
#endif
      }

      else if(vec[0] == "fload") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fload_0") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(0);
         p_method->code.push_back(inst);

      }
      else if(vec[0] == "fload_1") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(1);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fload_2") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(2);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fload_3") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(3);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fstore") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fstore_0") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 0;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

      }
      else if(vec[0] == "fstore_1") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 1;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

      }
      else if(vec[0] == "fstore_2") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 2;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

      }
      else if(vec[0] == "fstore_3") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 3;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

      }
      else if(vec[0] == "fadd") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FADD;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fsub") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FSUB;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fmul") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FMUL;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fdiv") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FDIV;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "frem") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FREM;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "fneg") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FNEG;
         p_method->code.push_back(inst);
      }
/*
      else if(vec[0] == "fcmpg") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_FCMPG;
         p_method->code.push_back(inst);
      }
*/
      else if(vec[0] == "ineg") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_INEG;
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "invokestatic") {
         string arg = vec[1];
         string class_name;
         size_t i = 0;
         size_t index = 0;
         for(i = 0; i < arg.size(); i++) {
            if(arg[i] == '.') {
               index = i;
            }
         }
         for(i = 0; i < index; i++) {
            class_name += arg[i];
         }
         string method_name;
         i++;
         for(; i < arg.size(); i++) {
            method_name += arg[i];
         }
         JavaClass * temp = get_class(class_name);
         if(temp == 0) {
            temp = load_class(class_name); 
         }
         if(temp == 0) {
            cerr << "unable to load class: " << class_name << endl;
            exit(1);
         }
         int class_index = get_class_index(class_name);
         int method_index = temp->get_method_index(method_name);

         if(class_name == "java.lang.System" && method_name == "loadLibrary" && method_index < 0) {
            method_index = 1; 
         }

         if(class_index < 0)
            throw unknown_class();

         if(method_index < 0)
            throw unknown_method();

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_INVOKESTATIC; 
         inst.arg1 = to_string2(class_index);
         inst.arg2 = to_string2(method_index);
         inst.arg3 = vec[2];
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[invokestatic " << class_index << " " << method_index << " " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "invokevirtual") {
         string arg = vec[1];
         if(arg.find(".") == string::npos) arg = vec[2];
         string class_name;
         size_t i = 0;
         size_t index = 0;
         for(i = 0; i < arg.size(); i++) {
            if(arg[i] == '.') {
               index = i;
            }
         }
         for(i = 0; i < index ; i++) {
            class_name += arg[i];
         }
         string method_name;
         i++;
         for(; i < arg.size(); i++) {
            if(arg[i] == '(') break;
            method_name += arg[i];
         }
         JavaClass * temp = get_class(class_name);
         if(temp == 0) {
            temp = load_class(class_name);
         }
         if(temp == 0) {
            cerr << "class not found: \"" << class_name << "\"" << endl;
            exit(1);
         }
         int class_index = get_class_index(class_name);
         int method_index = temp->get_method_index(method_name);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_INVOKEVIRTUAL;
         inst.arg1 = to_string2((int)class_index);
         inst.arg2 = to_string2(method_index);
         if(vec[1].find(".") == string::npos)
            inst.arg3 = vec[3];
         else 
            inst.arg3 = vec[2];
         p_method->code.push_back(inst);
#ifdef BC_DEBUG
cout << "[invokevirtual " << class_index << " " << method_index << " " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "iload") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ILOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[iload " << arg << "]" << endl;
#endif
      }

      else if(vec[0] == "dload") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
               
#ifdef BC_DEBUG
cout << "[dload " << arg << " " << vindex << "]" << endl;
#endif
      }
      else if(vec[0] == "dload_0") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 0;//p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
               
#ifdef BC_DEBUG
cout << "[dload_0]" << endl;
#endif
      }
      else if(vec[0] == "dload_1") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 1;//p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
               
#ifdef BC_DEBUG
cout << "[dload_1]" << endl;
#endif
      }
      else if(vec[0] == "dload_2") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 2;//p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
               
#ifdef BC_DEBUG
cout << "[dload_2]" << endl;
#endif
      }
      else if(vec[0] == "dload_3") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 3;//p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
               
#ifdef BC_DEBUG
cout << "[lload]" << endl;
#endif
      }





      else if(vec[0] == "lload") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[lload]" << endl;
#endif
      }

      else if(vec[0] == "lload_0") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 0;//p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[lload]" << endl;
#endif   
      }
      else if(vec[0] == "lload_1") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 1;//p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[lload]" << endl;
#endif
      }
      else if(vec[0] == "lload_2") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 2;//p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[lload]" << endl;
#endif
      }
      else if(vec[0] == "lload_3") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LLOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 3;//p_method->get_variable_index(arg);
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[lload]" << endl;
#endif
      }




      else if(vec[0] == "iload_0") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ILOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index("temp0");
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[iload " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "iload_1") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ILOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index("temp1");
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[iload " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "iload_2") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ILOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index("temp2");
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[iload " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "iload_3") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ILOAD;
         int cindex = (int)(p_class);
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index("temp3");
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[iload " << arg << "]" << endl;
#endif
      }

      else if(vec[0] == "dstore") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index(arg);
            
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "dstore_0") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 0;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "dstore_1") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 1;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "dstore_2") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 2;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "dstore_3") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 3;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }






      else if(vec[0] == "lstore") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "lstore_0") {

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 0;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "lstore_1") {

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 1;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "lstore_2") {

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 2;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "lstore_3") {

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = 3;//p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LSTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }



      else if(vec[0] == "istore_0") {
         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index("temp0");

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ISTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "istore_1") {
         //string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index("temp1");

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ISTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

      }
      else if(vec[0] == "istore_2") {
         //string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index("temp2");

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ISTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

      }
      else if(vec[0] == "istore_3") {
         //string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index("temp3");

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ISTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);
      }
      else if(vec[0] == "istore") {
         string arg = vec[1];

         int cindex = (int)p_class;
         int mindex = p_class->get_method_index(p_method->name);
         int vindex = p_method->get_variable_index(arg);

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ISTORE;
         inst.arg1 = to_string2(cindex);
         inst.arg2 = to_string2(mindex);
         inst.arg3 = to_string2(vindex);
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[istore " << arg << "]" << endl;
#endif
      }

      else if(vec[0] == "dadd") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DADD;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[dadd]" << endl;
#endif

      }
      else if(vec[0] == "dsub") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DSUB;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[dsub]" << endl;
#endif

      }
      else if(vec[0] == "dmul") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DMUL;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[dmul]" << endl;
#endif

      }
      else if(vec[0] == "ddiv") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DDIV;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[ddiv]" << endl;
#endif

      }
      else if(vec[0] == "drem") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DREM;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[drem]" << endl;
#endif

      }
      else if(vec[0] == "dneg") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_DNEG;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[dneg]" << endl;
#endif

      }





      else if(vec[0] == "ladd") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LADD;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[ladd]" << endl;
#endif

      }
      else if(vec[0] == "lsub") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LSUB;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[lsub]" << endl;
#endif

      }
      else if(vec[0] == "lmul") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LMUL;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[lmul]" << endl;
#endif

      }
      else if(vec[0] == "ldiv") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LDIV;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[ldiv]" << endl;
#endif

      }
      else if(vec[0] == "lrem") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LREM;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[lrem]" << endl;
#endif

      }
      else if(vec[0] == "lneg") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_LNEG;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[lneg]" << endl;
#endif

      }
      else if(vec[0] == "iadd") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IADD;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[iadd]" << endl;
#endif
      }
      else if(vec[0] == "isub") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ISUB;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[isub]" << endl;
#endif
      }
      else if(vec[0] == "imul") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IMUL;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[imul]" << endl;
#endif
      }
      else if(vec[0] == "idiv") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IDIV;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[idiv]" << endl;
#endif
      }
      else if(vec[0] == "return") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_RETURN;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[return]" << endl;
#endif
      }
      else if(vec[0] == "irem") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IREM;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[irem]" << endl;
#endif
      }
      else if(vec[0] == "pop") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_POP;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[pop]" << endl;
#endif
      }
      else if(vec[0] == "if_acmpeq") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IF_ACMPEQ;
         inst.arg1 = arg;
         p_method->code.push_back(inst);
                
#ifdef BC_DEBUG
cout << "[if_icmpeq " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "if_acmpne") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IF_ICMPNE;
         inst.arg1 = arg;
         p_method->code.push_back(inst);
                
#ifdef BC_DEBUG
cout << "[if_icmpeq " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "if_icmpeq") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IF_ICMPEQ;
         inst.arg1 = arg;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[if_icmpeq " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "if_icmpne") {
         string arg = vec[1];

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IF_ICMPNE;
         inst.arg1 = arg;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[if_icmpne " << arg << "]" << endl;
#endif
      }


      else if(vec[0] == "if_icmplt") {
         string arg = vec[1];

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IF_ICMPLT;
         inst.arg1 = arg;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[if_icmplt " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "if_icmpgt") {
         string arg = vec[1];

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IF_ICMPGT;
         inst.arg1 = arg;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[if_icmpgt " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "if_icmpge") {
         string arg = vec[1];

         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IF_ICMPGE;
         inst.arg1 = arg;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[if_icmpge " << arg << "]" << endl;
#endif
      }
      else if(vec[0] == "if_icmple") {
         string arg = vec[1];
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_IF_ICMPLE;
         inst.arg1 = arg;
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[if_icmple " << arg << "]" << endl;
#endif
      }

      else if(vec[0] == "invokespecial") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_INVOKESPECIAL;
         string cn = get_class_name(vec[1]);
         if(get_class(cn) == 0) {
            load_class(cn);
         }
         string mn = get_method_name(vec[1]);
         inst.arg1 = to_string2(get_class_index(cn));
         JavaClass * p_class2 = get_class(cn);
         inst.arg2 = to_string2(p_class2->get_method_index(mn));
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[invokespecial " << cn << " " << mn << " " << inst.arg1 << " " << inst.arg2 << "]" << endl;
#endif
      }
      else if(vec[0] == "aload") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ALOAD;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = to_string2(p_method->get_variable_index(vec[1]));
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[aload]" << endl;
#endif
      }

      else if(vec[0] == "aload_3") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ALOAD;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = "3";
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[aload_1]" << endl;
#endif
      }
      else if(vec[0] == "aload_2") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ALOAD;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = "2";
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[aload_1]" << endl;
#endif
      }


      else if(vec[0] == "aload_1") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ALOAD;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = "1";
         p_method->code.push_back(inst);

#ifdef BC_DEBUG
cout << "[aload_1]" << endl;
#endif
      }


      else if(vec[0] == "aload_0") {
         Instruction inst;
         inst.label = label;
         inst.opcode = BC_ALOAD;
         inst.arg1 = to_string2((int)(p_class));
         inst.arg2 = to_string2(p_class->get_method_index(p_method->name));
         inst.arg3 = "0";
         p_method->code.push_back(inst);


#ifdef BC_DEBUG
cout << "[aload_0]" << endl;
#endif
      }
      else if(vec[0] == "int") {
         if(vec.size() == 2) {
            p_method->put_variable(vec[0], vec[1]);
#ifdef BC_DEBUG
cout << "[int " << vec[1] << "]" << endl;
#endif
         }
      }
      else if(vec[0] == "float") {
         if(vec.size() == 2) {
            p_method->put_variable(vec[0], vec[1]);
#ifdef BC_DEBUG
cout << "[float " << vec[1] << "]" << endl;
#endif
         }
      }
      else if(vec[0] == ".access") {
#ifdef BC_DEBUG
cout << "[.access]" << endl;
#endif
      }
      else if(vec[0] == ".extends") {
#ifdef BC_DEBUG
cout << "[.extends]" << endl;
#endif
      }
      else if(vec[0] == ".implements") {
#ifdef BC_DEBUG
cout << "[.implements]" << endl;
#endif
      }
      else if(vec[0] == ".maxStack") {
#ifdef BC_DEBUG
cout << "[.maxStack]" << endl;
#endif
      }
      else if(vec[0] == ".args") {
#ifdef BC_DEBUG
cout << "[.args]" << endl;
#endif
      }
      else if(vec[0] == ".data") {
         in_data = true;
#ifdef BC_DEBUG
cout << "[.data]" << endl;
#endif
      }
      else if(vec[0] == ".signature") {
         p_method->type_signature = vec[1];
#ifdef BC_DEBUG
cout << "[.signature]" << endl;
#endif
      }
      else if(vec[0] == ".code") {
         in_data = false;
#ifdef BC_DEBUG
cout << "[.code]" << endl;
#endif
      }
      else {
         if(in_data) {
            p_method->put_variable(vec[0], vec[1]);
         }
         else {
            cerr << "instruction: " << vec[0] << endl;
            cerr << "Unknown instruciton..." << endl;
            exit(1);
         }
      }
   }
}

void
JavaVM::print_byte_code()
{
}


JavaVM::~JavaVM() {
   size_t i;

   for(i = 0; i < class_vec.size(); i++)
      delete (class_vec[i]);

   class_vec.clear();

   for(i = 0; i < dll_vec.size(); i++)
      dlclose(dll_vec[i]);

   dll_vec.clear();
}

void
JavaVM::run(const string & file)
{
   load_class2(file);

   clinit();

   JavaClass * p_class = get_class(file);

   if(p_class == 0) {
      cerr << "class: " << file << " not found...\n";
      exit(1);
   }

   int method_index = p_class->get_method_index("main");

   run_class(p_class->get_method(method_index));
}

int*
JavaVM::get_address2(int addr, int method, int variable)
{
   JavaClass * p_class = (JavaClass*)addr;
   JavaMethod * p_method = p_class->method_vec[method];
   Var & var = p_method->get_variable(variable);
   return &(var.data.data.ival);
}

int
get_param_count(const string & str)
{
   int count = 0;
   for(size_t i = 0; i < str.size(); i++) {
      if(str[i] == ';') {
         count++;
      }
   }
   return count;
}

char * 
get_string_utf_chars(JNIEnv * env, char * str, int b) 
{
   return str;
}

void
JavaVM::run_class(JavaMethod * p_method)
{
   size_t pc = 0;
   char carg1;
   int arg1,arg2,arg3,arg4;
   float farg1,farg2,farg3;
   double darg1,darg2,darg3;
   long long larg1,larg2,larg3;
   float * fptr1;
   string sarg1,sarg2;
   char * ptr;
   typedef void (*pf_t)(void*,void*,void*);
   typedef void (*pf2_t)(void*,void*,long long);
   typedef void (*pf3_t)(void*,void*,double);
   typedef void (*pf4_t)(void*,void*,short);
   typedef void (*pf5_t)(void*,void*,char);
   pf_t pf;
   pf2_t pf2;
   pf3_t pf3;
   pf4_t pf4;
   pf5_t pf5;
   int * ptr1;
   string class_name;
   JavaClass * p_class2, * p_class3;
   JavaMethod * p_method2;
   JavaField * p_field2;
   JavaArray * p_array2;
   string the_class_name;
   int temp;
   string ts;
   string temp_string;
   long long * lptr;
   double * dptr;
   int count;
   short sarg;
   _JNIEnv jni_env;
   JNIEnv jenv = &jni_env;
 
   jenv->GetStringUTFChars = get_string_utf_chars;

   while(pc < p_method->code.size()) {
#ifdef BC_DEBUG
cout << "pc=" << pc << endl;
#endif
      switch(p_method->code[pc].opcode) {
      case BC_INVOKESTATIC: 
#ifdef BC_DEBUG
cout << "invokestatic " << p_method->code[pc].arg1 << " " << p_method->code[pc].arg2 << endl;
#endif
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      if(is_native(arg1, arg2)) {
         ptr = get_native(arg1, arg2);
         if(get_class(arg1)->get_method(arg2)->type_signature.find("(J)") != string::npos) {
            pf2 = (pf2_t)ptr;
            larg3 = the_stack.top_long();
            the_stack.pop_long();
            pf2(&jenv,NULL,larg3);
         }
         else if(get_class(arg1)->get_method(arg2)->type_signature.find("(D)") != string::npos) {
            pf3 = (pf3_t)ptr;
            darg2 = the_stack.top_double();
            the_stack.pop_double();
            pf3(&jenv,NULL,darg2);
         }
         else if(get_class(arg1)->get_method(arg2)->type_signature.find("(S)") != string::npos) {
            pf4 = (pf4_t)ptr;
            sarg = the_stack.top_short();
            the_stack.pop_short();
            pf4(&jenv,NULL,sarg);
         }
         else if(get_class(arg1)->get_method(arg2)->type_signature.find("(C)") != string::npos) {
            pf5 = (pf5_t)ptr;
            carg1 = the_stack.top_char();
            the_stack.pop_char();
            pf5(&jenv,NULL,carg1);
         }
         else if(get_class(arg1)->get_method(arg2)->type_signature.find("(Z)") != string::npos) {
            pf = (pf_t)ptr;
            arg3 = the_stack.top_char();
            the_stack.pop_char();
            pf(&jenv,NULL,(void*)arg3);
         }
         else {
            pf = (pf_t)ptr;
            arg3 = the_stack.top_int();
            the_stack.pop_int();
            pf(&jenv,NULL,(void*)arg3);
         }
      }
      else {
         JavaClass * p_class = get_class(arg1);
         JavaMethod * pm = p_class->get_method(arg2);
         run_class(pm);
      }
      pc++;
      break;

      case BC_I2L:
#ifdef BC_DEBUG
cout << "i2l" << endl;
#endif

      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_long(arg1);
      pc++;
      break;

/*
#define BASTORE 0x54
#define BALOAD 0x33
#define DALOAD 0x31
#define DASTORE 0x52
#define FASTORE 0x51
#define FALOAD 0x30
#define SASTORE 0x56
#define SALOAD 0x35
#define CASTORE 0x55
#define CALOAD 0x34
*/

      case BC_LALOAD:
#ifdef BC_DEBUG
cout << "laload" << endl;
#endif
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      larg1 = p_array2->get_long(arg2);
      the_stack.push_long(larg1);


      pc++;

      break;

      case BC_LASTORE:
#ifdef BC_DEBUG
cout << "lastore" << endl;
#endif
      larg3 = the_stack.top_long();
      the_stack.pop_long();
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      p_array2->get_long(arg2) = larg3;
      
         
      pc++;
      break;

      case BC_BASTORE:
#ifdef BC_DEBUG
cout << "bastore" << endl;
#endif
      arg3 = the_stack.top_int();
      the_stack.pop_int();
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      p_array2->get_char(arg2) = (char)arg3;


      pc++;
      break;

      case BC_BALOAD:
#ifdef BC_DEBUG
cout << "baload" << endl;
#endif
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      arg1 = p_array2->get_int(arg2);
      the_stack.push_int(arg1);


      pc++;
      break;

      case BC_DALOAD:
#ifdef BC_DEBUG
cout << "daload" << endl;
#endif
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      darg1 = p_array2->get_double(arg2);
      the_stack.push_double(darg1);


      pc++;
      break;

      case BC_DASTORE:
#ifdef BC_DEBUG
cout << "dastore" << endl;
#endif
      darg3 = the_stack.top_double();
      the_stack.pop_double();
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      p_array2->get_double(arg2) = darg3;


      pc++;
      break;

      case BC_FASTORE:
#ifdef BC_DEBUG
cout << "fastore" << endl;
#endif
      farg3 = the_stack.top_float();
      the_stack.pop_float();
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      p_array2->get_float(arg2) = farg3;


      pc++;
      break;

      case BC_FALOAD:
#ifdef BC_DEBUG
cout << "faload" << endl;
#endif
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      farg1 = p_array2->get_float(arg2);
      the_stack.push_float(farg1);


      pc++;
      break;

      case BC_SASTORE:
#ifdef BC_DEBUG
cout << "sastore" << endl;
#endif
      sarg = the_stack.top_short();
      the_stack.pop_short();
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      p_array2->get_short(arg2) = sarg;

      pc++;
      break;

      case BC_SALOAD:
#ifdef BC_DEBUG
cout << "saload" << endl;
#endif
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      sarg = p_array2->get_short(arg2);
      the_stack.push_short(sarg);


      pc++;
      break;

      case BC_CASTORE:
#ifdef BC_DEBUG
cout << "castore" << endl;
#endif
      arg3 = the_stack.top_char();
      the_stack.pop_char();
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      p_array2->get_char(arg2) = arg3;


      pc++;
      break;

      case BC_CALOAD:
#ifdef BC_DEBUG
cout << "caload" << endl;
#endif
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      arg1 = p_array2->get_char(arg2);
      the_stack.push_char(arg1);


      pc++;
      break;


/*
#define BC_AALOAD 0x32
#define BC_AASTORE 0x53
#define BC_NEWARRAY 0xBC
#define BC_ANEWARRAY 0xBD
#define BC_ARRAYLENGTH 0xBE
#define BC_IASTORE 0x4F
#define BC_IALOAD 0x2E
*/


      case BC_AALOAD:
#ifdef BC_DEBUG
cout << "aaload" << endl;
#endif

      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      arg1 = p_array2->get_int(arg2);
      the_stack.push_int(arg1);
      pc++;
      break;

      case BC_AASTORE:
#ifdef BC_DEBUG
cout << "aastore" << endl;
#endif

      arg3 = the_stack.top_int();
      the_stack.pop_int();
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)(ptr);
      p_array2->get_int(arg2) = arg3;
      pc++;
      break;

      case BC_NEWARRAY: 
      count = the_stack.top_int();
      the_stack.pop_int();
      temp_string = p_method->code[pc].arg1;
#ifdef BC_DEBUG
cout << "newarray " << temp_string << endl;
#endif
      p_array2 = 0;
      if(temp_string == "int") {
         p_array2 = new JavaArray(count, sizeof(int), temp_string);
      }
      else if(temp_string == "float") {
         p_array2 = new JavaArray(count, sizeof(float), temp_string);
      }
      else if(temp_string == "char") {
         p_array2 = new JavaArray(count, sizeof(char), temp_string);
      }
      else if(temp_string == "short") {
         p_array2 = new JavaArray(count, sizeof(short), temp_string);
      }
      else if(temp_string == "double") {
         p_array2 = new JavaArray(count, sizeof(double), temp_string);
      }
      else if(temp_string == "long") {
         p_array2 = new JavaArray(count, sizeof(long long), temp_string);
      }
      else if(temp_string == "boolean") {
         p_array2 = new JavaArray(count, sizeof(bool), temp_string);
      }
      else if(temp_string == "byte") {
         p_array2 = new JavaArray(count, sizeof(char), temp_string);
      }
      else {
         p_array2 = new JavaArray(count, sizeof(int), temp_string);
      }
      the_stack.push_pointer((char*)p_array2);
      pc++;
      break;

      case BC_ANEWARRAY:
#ifdef BC_DEBUG
cout << "anewarray" << endl;
#endif
      count = the_stack.top_int();
      the_stack.pop_int();
      temp_string = p_method->code[pc].arg1;
      p_array2 = new JavaArray(count, sizeof(int), temp_string);
      the_stack.push_pointer((char*)p_array2);
      pc++;
      break;

      case BC_ARRAYLENGTH:
#ifdef BC_DEBUG
cout << "arraylength" << endl;
#endif

      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)ptr;
      the_stack.push_int(p_array2->length());
      pc++;
      break;

      case BC_IASTORE:
#ifdef BC_DEBUG
cout << "iastore" << endl;
#endif

      arg3 = the_stack.top_int();
      the_stack.pop_int();
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)ptr;
      p_array2->get_int(arg2) = arg3;
      pc++;
      break;

      case BC_IALOAD:
#ifdef BC_DEBUG
cout << "iaload" << endl;
#endif

      arg2 = the_stack.top_int();
      the_stack.pop_int();
      ptr = the_stack.top_pointer();
      the_stack.pop_pointer();
      p_array2 = (JavaArray*)ptr;
      arg1 = p_array2->get_int(arg2);
      the_stack.push_int(arg1);
      pc++;
      break;

      case BC_I2F:
#ifdef BC_DEBUG
cout << "i2f" << endl;
#endif

      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_float((float)arg1);
      pc++;
      break;

      case BC_I2D:
#ifdef BC_DEBUG
cout << "i2d" << endl;
#endif

      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_double(arg1);
      pc++;
      break;

      case BC_L2I:
#ifdef BC_DEBUG
cout << "l2i" << endl;
#endif

      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_int((int)larg1);
      pc++;
      break;

      case BC_L2F:
#ifdef BC_DEBUG
cout << "l2f" << endl;
#endif

      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_float((float)larg1);
      pc++;
      break;

      case BC_L2D:
#ifdef BC_DEBUG
cout << "l2d" << endl;
#endif

      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_double((double)larg1);
      pc++;
      break;

      case BC_F2I:
#ifdef BC_DEBUG
cout << "f2i" << endl;
#endif

      farg1 = the_stack.top_float();
      the_stack.pop_float();
      the_stack.push_int((int)farg1);
      pc++;
      break;

      case BC_F2L:
#ifdef BC_DEBUG
cout << "f2l" << endl;
#endif

      farg1 = the_stack.top_float();
      the_stack.pop_float();
      the_stack.push_long((long)farg1);
      pc++;
      break;

      case BC_F2D:
#ifdef BC_DEBUG
cout << "f2d" << endl;
#endif

      farg1 = the_stack.top_float();
      the_stack.pop_float();
      the_stack.push_double((double)farg1);
      pc++;
      break;

      case BC_D2I:
#ifdef BC_DEBUG
cout << "d2i" << endl;
#endif

      darg1 = the_stack.top_double();
      the_stack.pop_double();
      the_stack.push_int((int)darg1);
      pc++;
      break;

      case BC_D2L:
#ifdef BC_DEBUG
cout << "d2l" << endl;
#endif

      darg1 = the_stack.top_double();
      the_stack.pop_double();
      the_stack.push_long((long)darg1);
      pc++;
      break;

      case BC_D2F:
#ifdef BC_DEBUG
cout << "d2f" << endl;
#endif

      darg1 = the_stack.top_double();
      the_stack.pop_double();
      the_stack.push_float((float)darg1);
      pc++;
      break;

      case BC_I2B:
#ifdef BC_DEBUG
cout << "i2b" << endl;
#endif

      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1);
      pc++;
      break;

      case BC_I2C:
#ifdef BC_DEBUG
cout << "i2c" << endl;
#endif

      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_char((char)arg1);
      pc++;
      break;

      case BC_I2S:
#ifdef BC_DEBUG
cout << "i2s" << endl;
#endif

      sarg = (short)the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_short(sarg);
      pc++;
      break;

      case BC_ACONST_NULL:
#ifdef BC_DEBUG
cout << "aconst_null" << endl;
#endif
      the_stack.push_pointer(NULL);
      pc++;
      break;

//START NEW
      case BC_DCMPG:
      darg2 = the_stack.top_double();
      the_stack.pop_double();
      darg1 = the_stack.top_double();
      the_stack.pop_double();
      if(darg1 == darg2)
         the_stack.push_int(0);
      else if(darg1 < darg2)
         the_stack.push_int(-1);
      else
         the_stack.push_int(1);
      pc++;
      break;

      case BC_DCMPL:
      darg2 = the_stack.top_double();
      the_stack.pop_double();
      darg1 = the_stack.top_double();
      the_stack.pop_double();
      if(darg1 == darg2)
         the_stack.push_int(0);
      else if(darg1 < darg2)
         the_stack.push_int(-1);
      else
         the_stack.push_int(1);
      pc++;
      break;

      case BC_FCMPG:
      farg2 = the_stack.top_float();
      the_stack.pop_float();
      farg1 = the_stack.top_float();
      the_stack.pop_float();
      if(farg1 == farg2)
         the_stack.push_int(0);
      else if(farg1 < farg2)
         the_stack.push_int(-1);
      else
         the_stack.push_int(1);
      pc++;
      break;

      case BC_FCMPL:
      farg2 = the_stack.top_float();
      the_stack.pop_float();
      farg1 = the_stack.top_float();
      the_stack.pop_float();
      if(farg1 == farg2)
         the_stack.push_int(0);
      else if(farg1 < farg2)
         the_stack.push_int(-1);
      else 
         the_stack.push_int(1);
      pc++;
      break;

      case BC_LCMP: 
      larg2 = the_stack.top_long();
      the_stack.pop_long();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      if(larg1 == larg2)
         the_stack.push_int(0);
      else if(larg1 < larg2)
         the_stack.push_int(-1);
      else 
         the_stack.push_int(1);
      pc++;
      break;

      case BC_IFEQ:
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 == 0) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IFNE:
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 != 0) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IFLT:
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 < 0) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IFGE:
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 >= 0) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IFGT:
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 > 0) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IFLE:
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 <= 0) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IFNONNULL:
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 != 0) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IFNULL:
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 == 0) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;
//END NEW

      case BC_LSHR:
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(larg1 >> arg2);
      pc++;
      break;

      case BC_LSHL:
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(larg1 << arg2);
      pc++;
      break;

      case BC_LAND:
      larg2 = the_stack.top_long();
      the_stack.pop_long();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(larg1 & larg2);
      pc++;
      break;

      case BC_LOR:
      larg2 = the_stack.top_long();
      the_stack.pop_long();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(larg1 | larg2);
      pc++;
      break;

      case BC_LXOR:
      larg2 = the_stack.top_long();
      the_stack.pop_long();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(larg1 ^ larg2);
      pc++;
      break;

      case BC_LCONST_0:
      the_stack.push_long(0L);
      pc++;
      break;

      case BC_LCONST_1:
      the_stack.push_long(1L);
      pc++;
      break;

      case BC_ISHR:
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1 >> arg2);
      pc++;
      break;

      case BC_ISHL:
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1 << arg2);
      pc++;
      break;

      case BC_IOR:
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1 | arg2);
      pc++;
      break;

      case BC_IAND:
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1 & arg2);
      pc++;
      break;

      case BC_IXOR:
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1 ^ arg2);
      pc++;
      break;

      case BC_DUP:
#ifdef BC_DEBUG_
cout << "dup" << endl;
#endif
      arg1 = (int)the_stack.top_int();
      the_stack.push_int(arg1);
      pc++;
      break;
   
      case BC_NEW:
      the_class_name = p_method->code[pc].arg1;
      p_class2 = get_class(the_class_name);
#ifdef BC_DEBUG
cout << "new " << the_class_name << endl;
#endif
      if(p_class2 == 0) {
         cerr << "Unknown class: \"" << the_class_name << "\"" << endl;
         exit(1);
      }
      p_class3 = p_class2->new_instance();
      arg1 = (int)(p_class3);
      the_stack.push_int(arg1);
      pc++;
      break;

      case BC_PUTFIELD: 
#ifdef BC_DEBUG
cout << "putfield " << p_method->code[pc].arg1 << endl;
#endif
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      p_class2 = (JavaClass*)arg1;
      arg3 = atoi(p_method->code[pc].arg1.c_str());
      p_field2 = p_class2->get_field(arg3);
      p_field2->data.data.ival = arg2;
      pc++;
      break;

      case BC_PUTSTATIC:
#ifdef BC_DEBUG
cout << "putstatic " << p_method->code[pc].arg1 << " " << p_method->code[pc].arg2 << endl;
#endif
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      p_class2 = get_class(atoi(p_method->code[pc].arg1.c_str()));
      p_field2 = p_class2->get_field(atoi(p_method->code[pc].arg2.c_str()));
      p_field2->data.data.ival = arg1;
      pc++;
      break;

      case BC_GETSTATIC:
#ifdef BC_DEBUG
cout << "getstatic " << p_method->code[pc].arg1 << " " << p_method->code[pc].arg2 << endl;
#endif
      p_class2 = get_class(atoi(p_method->code[pc].arg1.c_str()));
      p_field2 = p_class2->get_field(atoi(p_method->code[pc].arg2.c_str()));
      the_stack.push_int(p_field2->data.data.ival);
      pc++;
      break;

      case BC_GETFIELD:
#ifdef BC_DEBUG
cout << "getfield " << p_method->code[pc].arg1 << endl;
#endif
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      p_class2 = (JavaClass*)arg1;
      arg3 = atoi(p_method->code[pc].arg1.c_str());
      p_field2 = p_class2->get_field(arg3);
      the_stack.push_int(p_field2->data.data.ival);
      pc++;
      break;


      case BC_POP: 
#ifdef BC_DEBUG
cout << "pop" << endl;
#endif
      the_stack.pop_int();
      pc++;
      break;

      case BC_GOTO: 
#ifdef BC_DEBUG
cout << "goto " << p_method->code[pc].arg1 << endl;
#endif
      pc = atoi(p_method->code[pc].arg1.c_str());
      break;

      case BC_IF_ACMPEQ: 
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 == arg2) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IF_ACMPNE:
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 != arg2) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IF_ICMPEQ: 
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 == arg2) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IF_ICMPNE: 
#ifdef BC_DEBUG
cout << "if_icmpne " << p_method->code[pc].arg1 << endl;
#endif
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 != arg2) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IF_ICMPLT:
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 < arg2) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IF_ICMPGT:
#ifdef BC_DEBUG
cout << "if_icmpgt " << p_method->code[pc].arg1 << endl;
#endif

      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 > arg2) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IF_ICMPGE: 
#ifdef BC_DEBUG
cout << "if_icmpge " << p_method->code[pc].arg1 << endl;
#endif
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 >= arg2) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_IF_ICMPLE: 
#ifdef BC_DEBUG
cout << "if_icmple " << p_method->code[pc].arg1 << endl;
#endif

      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      if(arg1 <= arg2) {
         pc = atoi(p_method->code[pc].arg1.c_str());
      }
      else {
         pc++;
      }
      break;

      case BC_RETURN: 
#ifdef BC_DEBUG
cout << "return" << endl;
#endif
      pc = p_method->code.size();
      break;

      case BC_BIPUSH: 
#ifdef BC_DEBUG
cout << "bipush " << p_method->code[pc].arg1 << endl;
#endif
      the_stack.push_int(atoi(p_method->code[pc].arg1.c_str()));
      pc++;
      break;

      case BC_IPUSH: 
#ifdef BC_DEBUG
cout << "ipush " << p_method->code[pc].arg1 << endl;
#endif
      the_stack.push_int(atoi(p_method->code[pc].arg1.c_str()));
      pc++;
      break;

      case BC_LDC2_W:
      if(p_method->code[pc].arg1.find(".") != string::npos) {
         darg1 = strtod(p_method->code[pc].arg1.c_str(), NULL);
         the_stack.push_double(darg1);
      }
      else {
         larg1 = atol(p_method->code[pc].arg1.c_str());
         the_stack.push_long(larg1);
      }
      pc++;
      break;

      case BC_LDC2:
      farg1 = atof(p_method->code[pc].arg1.c_str());
      the_stack.push_float(farg1);
      pc++;
      break;

      case BC_LDC:
#ifdef BC_DEBUG
cout << "ldc" << endl;
#endif
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = (int)get_const2(arg1);
      the_stack.push_int(arg2);
      pc++;
      break;

      case BC_ICONST: 
#ifdef BC_DEBUG
cout << "iconst" << endl;
#endif
      pc++;
      break;

      case BC_LSTORE:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
#ifdef BC_DEBUG
      cout << "dstore " << arg1 << " " << arg2 << " " << arg3 << endl;
#endif
      lptr = (long long*)get_address2(arg1, arg2, arg3);
      larg2 = the_stack.top_long();
      the_stack.pop_long();
      *lptr = larg2;
      pc++;
      break;

      case BC_LLOAD:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
#ifdef BC_DEBUG
      cout << "lstore " << arg1 << " " << arg2 << " " << arg3 << endl;
#endif
      lptr = (long long*)get_address2(arg1, arg2, arg3);
      the_stack.push_long(*lptr);
      pc++;
      break;


      case BC_FSTORE:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
#ifdef BC_DEBUG
      cout << "fstore " << arg1 << " " << arg2 << " " << arg3 << endl;
#endif
      fptr1 = (float*)get_address2(arg1, arg2, arg3);
      farg2 = the_stack.top_float();
      the_stack.pop_float();
      *fptr1 = farg2;
      pc++;
      break;

      case BC_ISTORE:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
#ifdef BC_DEBUG
      cout << "istore " << arg1 << " " << arg2 << " " << arg3 << endl;
#endif
      ptr1 = (int*)get_address2(arg1, arg2, arg3);
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      *ptr1 = arg2;
      pc++;
      break;

      case BC_DSTORE:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
#ifdef BC_DEBUG
      cout << "dstore " << arg1 << " " << arg2 << " " << arg3 << endl;
#endif
      dptr = (double*)get_address2(arg1, arg2, arg3);
      darg2 = the_stack.top_double();
      the_stack.pop_double();
      *dptr = darg2;
      pc++;
      break;


      case BC_FLOAD:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
#ifdef BC_DEBUG
      cout << "fload " << arg1 << " " << arg2 << " " << arg3 << endl;
#endif
      fptr1 = (float*)get_address2(arg1, arg2, arg3);
      farg2 = (*fptr1);
      the_stack.push_float(farg2);
      pc++;
      break;

      case BC_DLOAD:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
#ifdef BC_DEBUG
      cout << "dload " << arg1 << " " << arg2 << " " << arg3 << endl;
#endif
      dptr = (double*)get_address2(arg1, arg2, arg3);
      the_stack.push_double(*dptr);
      pc++;
      break;

      case BC_ILOAD:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
#ifdef BC_DEBUG
      cout << "iload " << arg1 << " " << arg2 << " " << arg3 << endl;
#endif
      ptr1 = (int*)get_address2(arg1, arg2, arg3);
      the_stack.push_int(*ptr1);
      pc++;
      break;

      case BC_ALOAD:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
#ifdef BC_DEBUG
      cout << "aload " << arg1 << " " << arg2 << " " << arg3 << endl;
#endif
      ptr1 = (int*)get_address2(arg1, arg2, arg3);
      the_stack.push_int(*ptr1);
      pc++;
      break;

      case BC_ASTORE:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
#ifdef BC_DEBUG
      cout << "astore " << arg1 << " " << arg2 << " " << arg3 << endl;
#endif
      ptr1 = (int*)get_address2(arg1, arg2, arg3);
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      *ptr1 = arg2;
      pc++;
      break;

      case BC_LADD:
#ifdef BC_DEBUG
      cout << "ladd" << endl;
#endif

      larg2 = the_stack.top_long();
      the_stack.pop_long();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(larg1 + larg2);
      pc++;
      break;

      case BC_LSUB:
#ifdef BC_DEBUG
      cout << "ladd" << endl;
#endif

      larg2 = the_stack.top_long();
      the_stack.pop_long();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(larg1 - larg2);
      pc++;
      break;

      case BC_LMUL:
#ifdef BC_DEBUG
      cout << "lmul" << endl;
#endif

      larg2 = the_stack.top_long();
      the_stack.pop_long();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(larg1 * larg2);
      pc++;
      break;

      case BC_LDIV:
#ifdef BC_DEBUG
      cout << "ldiv" << endl;
#endif

      larg2 = the_stack.top_long();
      the_stack.pop_long();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(larg1 / larg2);
      pc++;
      break;


      case BC_LREM:
#ifdef BC_DEBUG
      cout << "lrem" << endl;
#endif

      larg2 = the_stack.top_long();
      the_stack.pop_long();
      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(larg1 % larg2);
      pc++;
      break;

      case BC_LNEG:
#ifdef BC_DEBUG
      cout << "lneg" << endl;
#endif

      larg1 = the_stack.top_long();
      the_stack.pop_long();
      the_stack.push_long(-larg1);
      pc++;
      break;



      case BC_INEG:
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(-arg1);
      pc++;
      break;

      case BC_IADD:
#ifdef BC_DEBUG
      cout << "iadd" << endl; 
#endif

      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1 + arg2);
      pc++;
      break;

      case BC_ISUB:
#ifdef BC_DEBUG
      cout << "isub" << endl; 
#endif

      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1 - arg2);
      pc++;
      break;

      case BC_IMUL:
#ifdef BC_DEBUG
      cout << "imul" << endl; 
#endif

      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1 * arg2);
      pc++;
      break;

      case BC_IDIV:
#ifdef BC_DEBUG
      cout << "idiv" << endl; 
#endif

      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1 / arg2);
      pc++;
      break;

      case BC_IREM:
#ifdef BC_DEBUG
      cout << "irem" << endl; 
#endif
      arg2 = the_stack.top_int();
      the_stack.pop_int();
      arg1 = the_stack.top_int();
      the_stack.pop_int();
      the_stack.push_int(arg1 % arg2);
      pc++;
      break;

      case BC_INVOKEVIRTUAL:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      ts = p_method->code[pc].arg3;
#ifdef BC_DEBUG
cout << "invokevirtual " << arg1 << " " << arg2 << endl;
#endif
      if(is_native(arg1, arg2)) {
         ptr = get_native(arg1, arg2);
         pf = (pf_t)ptr;
         arg1 = the_stack.top_int();
         the_stack.pop_int();
         pf(NULL,NULL,(void*)arg1);
      }
      else {
         p_class2 = class_vec[arg1];
         p_method2 = p_class2->get_method(arg2);
         int count = get_param_count(ts);

         var_vector_type var_vec(count+1);
         for(int i = count; i >= 0; i--) {
            var_vec[i].data.data.ival = the_stack.top_int();
            the_stack.pop_int();
         }

         int temp = var_vec[0].data.data.ival;

         JavaClass * p_class = (JavaClass*)temp;
         JavaMethod * pm = p_class->get_method(arg2);
         var_vector_type temp_vec = pm->var_vec;
         pm->var_vec = var_vec;

         run_class(pm);

         pm->var_vec = temp_vec;
      }
      pc++;
      break;

      case BC_INVOKESPECIAL:
      sarg1 = p_method->code[pc].arg1;
      sarg2 = p_method->code[pc].arg2;

      arg1 = atoi(sarg1.c_str());
      arg2 = atoi(sarg2.c_str());

#ifdef BC_DEBUG
cout << "invokespecial " << arg1 << " " << arg2 << " " << sarg1 << " " << sarg2 << endl;
#endif

      temp = the_stack.top_int();
      the_stack.pop_int();

      p_class2 = (JavaClass*)temp;
      p_class3 = class_vec[arg1];
      if(p_class2->name != p_class3->name) {
         if(p_class2->super) {
            p_class3 = p_class2;
            p_class2 = p_class2->super;
            arg2 = p_class2->get_method_index(p_class3->method_vec[arg2]->name);
         }
      }
      p_method2 = p_class2->method_vec[arg2];

      ptr1 = (int*)get_address2(temp, arg2, 0);
      *ptr1 = temp;

      run_class(p_method2);
      pc++;
      break;

      case BC_IINC:
      arg1 = atoi(p_method->code[pc].arg1.c_str());
      arg2 = atoi(p_method->code[pc].arg2.c_str());
      arg3 = atoi(p_method->code[pc].arg3.c_str());
      arg4 = atoi(p_method->code[pc].arg4.c_str());
      ptr1 = (int*)get_address2(arg1, arg2, arg3);
      *ptr1 += arg4;
#ifdef BC_DEBUG
cout << "iinc " << arg1 << " " << arg2 << " " << arg3 << " " << arg4 << endl;
cout << "iinc " << p_method->code[pc].arg1 << " " << p_method->code[pc].arg2 << " " << p_method->code[pc].arg3 << " " << p_method->code[pc].arg4 << endl;
cin.get();cin.get();
#endif
      pc++;
      break;


      case BC_DADD:
      darg2 = the_stack.top_double();
      the_stack.pop_double();
      darg1 = the_stack.top_double();
      the_stack.pop_double();
      the_stack.push_double(darg1 + darg2);
      pc++;
      break;

      case BC_DSUB:
      darg2 = the_stack.top_double();
      darg2 = the_stack.top_double();
      the_stack.pop_double();
      darg1 = the_stack.top_double();
      the_stack.pop_double();
      the_stack.push_double(darg1 - darg2);
      pc++;
      break;

      case BC_DMUL:
      darg2 = the_stack.top_double();
      the_stack.pop_double();
      darg1 = the_stack.top_double();
      the_stack.pop_double();
      the_stack.push_double(darg1 * darg2);
      pc++;
      break;

      case BC_DDIV:
      darg2 = the_stack.top_double();
      the_stack.pop_double();
      darg1 = the_stack.top_double();
      the_stack.pop_double();
      the_stack.push_double(darg1 / darg2);
      pc++;
      break;

      case BC_DREM:
      darg2 = the_stack.top_double();
      the_stack.pop_double();
      darg1 = the_stack.top_double();
      the_stack.pop_double();
      the_stack.push_double(fmod(darg1, darg2));
      pc++;
      break;

      case BC_DNEG:
      darg1 = the_stack.top_double();
      the_stack.pop_double();
      darg1 = -darg1;
      the_stack.push_double(darg1);
      pc++;
      break;

      case BC_FADD:
      farg2 = the_stack.top_float();
      the_stack.pop_float();
      farg1 = the_stack.top_float();
      the_stack.pop_float();
      the_stack.push_float(farg1 + farg2);
      pc++;
      break;

      case BC_FSUB:
      farg2 = the_stack.top_float();
      the_stack.pop_float();
      farg1 = the_stack.top_float();
      the_stack.pop_float();
      the_stack.push_float(farg1 - farg2);
      pc++;
      break;

      case BC_FMUL:
      farg2 = the_stack.top_float();
      the_stack.pop_float();
      farg1 = the_stack.top_float();
      the_stack.pop_float();
      the_stack.push_float(farg1 * farg2);
      pc++;
      break;

      case BC_FDIV:
      farg2 = the_stack.top_float();
      the_stack.pop_float();
      farg1 = the_stack.top_float();
      the_stack.pop_float();
      the_stack.push_float(farg1 / farg2);
      pc++;
      break;

      case BC_FREM:
      farg2 = the_stack.top_float();
      the_stack.pop_float();
      farg1 = the_stack.top_float();
      the_stack.pop_float();
      the_stack.push_float(fmod(farg1, farg2));
      pc++;
      break;

      case BC_FNEG:
      farg1 = the_stack.top_float();
      the_stack.pop_float();
      farg1 = -farg1;
      the_stack.push_float(farg1);
      pc++;
      break;

/*
      case BC_FCMPG:
      farg2 = the_stack.top_float();
      the_stack.pop_float();
      farg1 = the_stack.top_float();
      the_stack.pop_float();
      farg2 = farg1 > farg2;
      the_stack.push_float(farg2);
      pc++;
      break;
*/

      default:
         cerr << "BYTE_CODE=" << p_method->code[pc].opcode << endl;
         cerr << "Bad instrction..." << endl;
         exit(1);
      }
   }
}

