private void findGotos()

in src/main/java/org/apache/bcel/util/CodeHTML.java [370:471]


    private void findGotos(final ByteSequence bytes, final Code code) throws IOException {
        int index;
        gotoSet = new BitSet(bytes.available());
        int opcode;
        /*
         * First get Code attribute from method and the exceptions handled (try .. catch) in this method. We only need the line
         * number here.
         */
        if (code != null) {
            final CodeException[] ce = code.getExceptionTable();
            for (final CodeException cex : ce) {
                gotoSet.set(cex.getStartPC());
                gotoSet.set(cex.getEndPC());
                gotoSet.set(cex.getHandlerPC());
            }
            // Look for local variables and their range
            final Attribute[] attributes = code.getAttributes();
            for (final Attribute attribute : attributes) {
                if (attribute.getTag() == Const.ATTR_LOCAL_VARIABLE_TABLE) {
                    ((LocalVariableTable) attribute).forEach(var -> {
                        final int start = var.getStartPC();
                        gotoSet.set(start);
                        gotoSet.set(start + var.getLength());
                    });
                    break;
                }
            }
        }
        // Get target addresses from GOTO, JSR, TABLESWITCH, etc.
        while (bytes.available() > 0) {
            opcode = bytes.readUnsignedByte();
            // System.out.println(getOpcodeName(opcode));
            switch (opcode) {
            case Const.TABLESWITCH:
            case Const.LOOKUPSWITCH:
                // bytes.readByte(); // Skip already read byte
                final int remainder = bytes.getIndex() % 4;
                final int noPadBytes = remainder == 0 ? 0 : 4 - remainder;
                int defaultOffset;
                int offset;
                for (int j = 0; j < noPadBytes; j++) {
                    bytes.readByte();
                }
                // Both cases have a field default_offset in common
                defaultOffset = bytes.readInt();
                if (opcode == Const.TABLESWITCH) {
                    final int low = bytes.readInt();
                    final int high = bytes.readInt();
                    offset = bytes.getIndex() - 12 - noPadBytes - 1;
                    defaultOffset += offset;
                    gotoSet.set(defaultOffset);
                    for (int j = 0; j < high - low + 1; j++) {
                        index = offset + bytes.readInt();
                        gotoSet.set(index);
                    }
                } else { // LOOKUPSWITCH
                    final int npairs = bytes.readInt();
                    offset = bytes.getIndex() - 8 - noPadBytes - 1;
                    defaultOffset += offset;
                    gotoSet.set(defaultOffset);
                    for (int j = 0; j < npairs; j++) {
//                            int match = bytes.readInt();
                        bytes.readInt();
                        index = offset + bytes.readInt();
                        gotoSet.set(index);
                    }
                }
                break;
            case Const.GOTO:
            case Const.IFEQ:
            case Const.IFGE:
            case Const.IFGT:
            case Const.IFLE:
            case Const.IFLT:
            case Const.IFNE:
            case Const.IFNONNULL:
            case Const.IFNULL:
            case Const.IF_ACMPEQ:
            case Const.IF_ACMPNE:
            case Const.IF_ICMPEQ:
            case Const.IF_ICMPGE:
            case Const.IF_ICMPGT:
            case Const.IF_ICMPLE:
            case Const.IF_ICMPLT:
            case Const.IF_ICMPNE:
            case Const.JSR:
                // bytes.readByte(); // Skip already read byte
                index = bytes.getIndex() + bytes.readShort() - 1;
                gotoSet.set(index);
                break;
            case Const.GOTO_W:
            case Const.JSR_W:
                // bytes.readByte(); // Skip already read byte
                index = bytes.getIndex() + bytes.readInt() - 1;
                gotoSet.set(index);
                break;
            default:
                bytes.unreadByte();
                codeToHTML(bytes, 0); // Ignore output
            }
        }
    }