/* readclass : pancake / cathack */

char *buf;
int p; // pointer to data.

int getInt(int p)
{
 return( (*(buf+p)<<8)  + (*(buf+p+1))   );
}

int getInt4(int p)
{
 return( (*(buf+p+0)+1<<24) +
         (*(buf+p+1)+1<<16) +
         (*(buf+p+2)+1<< 8) +
         (*(buf+p+3))
       );
}

int checkMagic()
{
 if (getInt4(0)==0xCaFeBaBe) return 0;
 return 1;
}

int checkVersion()
{
 int min=getInt(4);
 int max=getInt(6);
 printf("Minor version %d. Major version %d.\n",min,max);
 return 0;
}

int ConstantPoolCount()
{
 return(getInt(8));
}



int
main(int argc, char *argv[])
{
int size, pool,i;
int fd=open(argv[1],0);

lseek(fd,0,0);

buf=(char *)malloc(8192);

size=read(fd,buf,8192);

printf("Using file: %s(%d)\n",argv[1],size);
if (size<50)
  {
   printf("Header ERROR: File too small\n");
  }
  if (!checkMagic())       printf ("Magic : OK   - CA FE BA BE\n");
      else   {             printf ("Magic : ERROR\n");    exit(0);   }
  if (checkVersion())      { printf("Version ERROR\n"); }
    pool=ConstantPoolCount();
    printf("Constants in pool : %d\n",--pool);
    
  for(p=10,i=pool;pool--;)
  {
   switch(*(buf+p))
     {
     case 1: // Utf8
           {
           char *s;
           int len=getInt(p+1);
           s=(char *)malloc(len+1);
           memcpy(s,  buf+p+3, len);
           s[len]=0;
           printf("%3d : Utf8  - \"%s\" - length : %d\n",i-pool,s,len);
           p+=3+len;
           free(s);
           break;
           }
     case 3: // Integer
     case 4: // Float
            printf ("%3d : %s - value %d\n",
                    i-pool, (*(buf+p)==3)?"Integer":"Float",
                       getInt4(p+1) );
            p+=5;
            break;
     case 5: // Long
     case 6: // Double
            printf("%3d : %s - value %d%d\n",
                    i-pool, (*(buf+p)==3)?"Long":"Double",
                       getInt4(p+1),getInt4(p+5) );
            p+=9;
            break;
     case 7: // CLASS
            printf("%3d : Class - index %d\n", i-pool,getInt(p+1) );
            p+=3;
            break;
     case 8: // STRING
            printf("%3d : String - index %d\n", i-pool,getInt(p+1) );
            p+=3; 
            break;
     case  9: // FieldRef
     case 10: // MethodRef
     case 11: // InterfaceMethodRef
            printf("%3d : %s - classindex:%d nameindex:%d\n",
                                    i-pool,
                                    (*(buf+p)==9)?"FieldRef":
                                    (*(buf+p)==10)?"MethodRef":
                                                   "InterfaceMethod",
                                    getInt(p+1),getInt(p+3) );
            p+=5;
            break;
      case 12: // NameAndType
            printf("%3d : NameAndType - name-index:%d descriptor-index:%d\n",
                   i-pool,getInt(p+1), getInt(p+3));
            p+=5;
            break;
      default:
            printf("%3d : Unknown (%d).\n",i-pool, (char)(*(buf+p)) );
            exit(1);
            break;
     }
  }
  
  // u2 ACCES_FLAGS
  {
  int f=getInt(p);
  printf ("Acces flags to this class: 0x%x (", f );
  if (f & 0x0001) printf("PUBLIC-");
  if (f & 0x0010) printf("FINAL-");
  if (f & 0x0020) printf("SUPER)\n");
  if (f & 0x0200) printf("INTERFACE)\n");
  if (f & 0x0400) printf("ABSTRACT)\n");
  p+=2;
  }
  
  // u2 THIS_CLASS
  printf ("This class points to constant_pool index %d.\n", getInt(p) );
  p+=2;
  
  // u2 SUPER_CLASS  
  printf ("Super class: %d.\n",getInt(p) );
  p+=2;
  
  // u2 Interface count
  {
  int i,n=getInt(p);
  printf ("Interface count: %d.\n",n);
  p+=2;
  for (i=n;n--;)
  {
   printf("%3d Interface points to constant_pool index %d",i-n,getInt(p+1));
   p+=3;
  }
  }
  
  // u2 Fields count
  {
  int i,n=getInt(p);
  printf ("Fields count: %d.\n",n);
  p+=2;
  for (i=n;n--;)
  {
   int f;
   printf("%3d Field : (",i-n);
   f=getInt(p);
   if (f & 0x0001) printf("PUBLIC-");
   if (f & 0x0002) printf("PRIVATE-");
   if (f & 0x0004) printf("PROTECTED-");
   if (f & 0x0008) printf("STATIC-");
   if (f & 0x0010) printf("FINAL)");
   if (f & 0x0040) printf("VOLATILE)");
   if (f & 0x0080) printf("TRANSIENT)");
   f=getInt(p+6);
   printf (" name_i: %d desc_i: %d attrs: %d\n",getInt(p+2),getInt(p+4),f);
   // don't show it's attributes
   p+=6+f;
  }
  }
  
  // u2 Methods count
  {
  int i,n=getInt(p);
  printf ("Method count: %d.\n",n);
  for (i=n;n--;)
  {
   printf("%3d Method points to constant_pool index %d\n",i-n,getInt(p+1));
   p+=3;
  }
  }
  
  // u2 Attributes count
  {
  int i,n=getInt(p);
  printf ("Attributes count: %d.\n",n);
  for (i=n;n--;)
  {
   printf("%3d Attributes points to constant_pool index %d\n",i-n,getInt(p+1));
   p+=3;
  }
  }
}


