// Description of superclass and interfaces sections in class file of class c:
 // 1. superclass d:
 //   if c is an interface then d is java.lang.Object
 //   if c == java.lang.Object then d is null (has index 0 in constant pool)
 //   if c is a class other than java.lang.Object then d is the declared superclass of c
 // 2. interfaces S:
 //   if c is an interface then S is the set of interfaces c declares it extends
 //   if c is a class then S is the set of interfaces c declares it implements
 private void processClassFile(DataInputStream in, String className) {
   try {
     int magicNum = in.readInt(); // 0xCAFEBABE
     if (magicNum != 0xCAFEBABE) {
       throw new ClassFormatError("bad magic number: " + Integer.toHexString(magicNum));
     }
     in.readUnsignedShort(); // read minor_version
     in.readUnsignedShort(); // read major_version
     int constant_pool_count = in.readUnsignedShort();
     Object[] constant_pool = processConstantPool(in, constant_pool_count);
     char access_flags = (char) in.readUnsignedShort(); // read access_flags
     int self_index = in.readUnsignedShort();
     int super_index = in.readUnsignedShort();
     if (super_index == 0) {
       assert (className.equals("java.lang.Object"));
       classToDeclaredSuperclass.put(className, null);
       clintToKind.put(className, TypeKind.CONCRETE_CLASS);
     } else {
       int c = (Integer) constant_pool[super_index];
       Utf8 utf8 = (Utf8) constant_pool[c];
       String superclassName = utf8.toString().replace('/', '.');
       if (isInterface(access_flags)) {
         assert (superclassName.equals("java.lang.Object"));
         clintToKind.put(className, TypeKind.INTERFACE);
       } else {
         classToDeclaredSuperclass.put(className, superclassName);
         if (isAbstract(access_flags)) clintToKind.put(className, TypeKind.ABSTRACT_CLASS);
         else clintToKind.put(className, TypeKind.CONCRETE_CLASS);
       }
     }
     int n_interfaces = (int) in.readUnsignedShort();
     Set<String> interfaces = new ArraySet<String>(n_interfaces);
     clintToDeclaredInterfaces.put(className, interfaces);
     for (int i = 0; i < n_interfaces; ++i) {
       int interface_index = in.readUnsignedShort();
       int c = (Integer) constant_pool[interface_index];
       Utf8 utf8 = (Utf8) constant_pool[c];
       String interfaceName = utf8.toString().replace('/', '.');
       interfaces.add(interfaceName);
     }
     in.close();
   } catch (IOException ex) {
     ex.printStackTrace();
     System.exit(1);
   }
 }