/*
 * ProGuard -- shrinking, optimization, obfuscation, and preverification
 *             of Java bytecode.
 *
 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package proguard.classfile.editor;

import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.preverification.*;
import proguard.classfile.attribute.preverification.visitor.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;

/**
 * This AttributeVisitor accumulates instructions and exceptions, and then
 * copies them into code attributes that it visits.
 *
 * @author Eric Lafortune
 */
public class CodeAttributeComposer
extends      SimplifiedVisitor
implements   AttributeVisitor,
             InstructionVisitor,
             ExceptionInfoVisitor,
             StackMapFrameVisitor,
             VerificationTypeVisitor,
             LineNumberInfoVisitor,
             LocalVariableInfoVisitor,
             LocalVariableTypeInfoVisitor
{
    //*
    private static final boolean DEBUG = false;
    /*/
    public  static       boolean DEBUG = true;
    //*/


    private static final int MAXIMUM_LEVELS = 32;
    private static final int INVALID        = -1;


    private boolean allowExternalExceptionHandlers;

    private int maximumCodeLength;
    private int codeLength;
    private int exceptionTableLength;
    private int level = -1;

    private byte[]  code                  = new byte[ClassConstants.TYPICAL_CODE_LENGTH];
    private int[]   oldInstructionOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];

    private final int[]   codeFragmentOffsets  = new int[MAXIMUM_LEVELS];
    private final int[]   codeFragmentLengths  = new int[MAXIMUM_LEVELS];
    private final int[][] instructionOffsetMap = new int[MAXIMUM_LEVELS][ClassConstants.TYPICAL_CODE_LENGTH + 1];

    private ExceptionInfo[] exceptionTable = new ExceptionInfo[ClassConstants.TYPICAL_EXCEPTION_TABLE_LENGTH];

    private int expectedStackMapFrameOffset;

    private final StackSizeUpdater    stackSizeUpdater    = new StackSizeUpdater();
    private final VariableSizeUpdater variableSizeUpdater = new VariableSizeUpdater();
//    private final InstructionWriter   instructionWriter   = new InstructionWriter();


    /**
     * Creates a new CodeAttributeComposer that doesn't allow external exception
     * handlers.
     */
    public CodeAttributeComposer()
    {
        this(false);
    }


    /**
     * Creates a new CodeAttributeComposer that optionally allows external
     * exception handlers.
     */
    public CodeAttributeComposer(boolean allowExternalExceptionHandlers)
    {
        this.allowExternalExceptionHandlers = allowExternalExceptionHandlers;
    }


    /**
     * Starts a new code definition.
     */
    public void reset()
    {
        maximumCodeLength    = 0;
        codeLength           = 0;
        exceptionTableLength = 0;
        level                = -1;
    }


    /**
     * Starts a new code fragment. Branch instructions that are added are
     * assumed to be relative within such code fragments.
     * @param maximumCodeFragmentLength the maximum length of the code that will
     *                                  be added as part of this fragment.
     */
    public void beginCodeFragment(int maximumCodeFragmentLength)
    {
        level++;

        if (level >= MAXIMUM_LEVELS)
        {
            throw new IllegalArgumentException("Maximum number of code fragment levels exceeded ["+level+"]");
        }

//        // TODO: Figure out some length.
//        if (level == 0)
//        {
//            // Prepare for possible widening of instructions.
//            instructionWriter.reset(2 * maximumCodeFragmentLength);
//        }

        // Make sure there is sufficient space for adding the code fragment.
        maximumCodeLength += maximumCodeFragmentLength;

        ensureCodeLength(maximumCodeLength);

        // Try to reuse the previous array for this code fragment.
        if (instructionOffsetMap[level].length <= maximumCodeFragmentLength)
        {
            instructionOffsetMap[level] = new int[maximumCodeFragmentLength + 1];
        }

        // Initialize the offset map.
        for (int index = 0; index <= maximumCodeFragmentLength; index++)
        {
            instructionOffsetMap[level][index] = INVALID;
        }

        // Remember the location of the code fragment.
        codeFragmentOffsets[level] = codeLength;
        codeFragmentLengths[level] = maximumCodeFragmentLength;
    }


    /**
     * Appends the given instruction with the given old offset.
     * @param oldInstructionOffset the old offset of the instruction, to which
     *                             branches and other references in the current
     *                             code fragment are pointing.
     * @param instruction          the instruction to be appended.
     */
    public void appendInstruction(int         oldInstructionOffset,
                                  Instruction instruction)
    {
        if (DEBUG)
        {
            println("["+codeLength+"] <- ", instruction.toString(oldInstructionOffset));
        }

        // Make sure the code array is large enough.
        int newCodeLength = codeLength + instruction.length(codeLength);

        ensureCodeLength(newCodeLength);

        // Remember the old offset of the appended instruction.
        oldInstructionOffsets[codeLength] = oldInstructionOffset;

        // Write the instruction.
//        instruction.accept(null,
//                           null,
//                           new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
//                           codeLength,
//                           instructionWriter);
        instruction.write(code, codeLength);

        // Fill out the new offset of the appended instruction.
        instructionOffsetMap[level][oldInstructionOffset] = codeLength;

        // Continue appending at the next instruction offset.
        codeLength = newCodeLength;
    }


    /**
     * Appends the given label with the given old offset.
     * @param oldInstructionOffset the old offset of the label, to which
     *                             branches and other references in the current
     *                             code fragment are pointing.
     */
    public void appendLabel(int oldInstructionOffset)
    {
        if (DEBUG)
        {
            println("["+codeLength+"] <- ", "[" + oldInstructionOffset + "] (label)");
        }

        // Fill out the new offset of the appended instruction.
        instructionOffsetMap[level][oldInstructionOffset] = codeLength;
    }


    /**
     * Appends the given exception to the exception table.
     * @param exceptionInfo the exception to be appended.
     */
    public void appendException(ExceptionInfo exceptionInfo)
    {
        if (DEBUG)
        {
            print("         ", "Exception ["+exceptionInfo.u2startPC+" -> "+exceptionInfo.u2endPC+": "+exceptionInfo.u2handlerPC+"]");
        }

        // Remap the exception right away.
        visitExceptionInfo(null, null, null, exceptionInfo);

        if (DEBUG)
        {
            System.out.println(" -> ["+exceptionInfo.u2startPC+" -> "+exceptionInfo.u2endPC+": "+exceptionInfo.u2handlerPC+"]");
        }

        // Don't add the exception if its instruction range is empty.
        if (exceptionInfo.u2startPC == exceptionInfo.u2endPC)
        {
            if (DEBUG)
            {
                println("         ", "  (not added because of empty instruction range)");
            }

            return;
        }

        // Make sure there is sufficient space in the exception table.
        if (exceptionTable.length <= exceptionTableLength)
        {
            ExceptionInfo[] newExceptionTable = new ExceptionInfo[exceptionTableLength+1];
            System.arraycopy(exceptionTable, 0, newExceptionTable, 0, exceptionTableLength);
            exceptionTable = newExceptionTable;
        }

        // Add the exception.
        exceptionTable[exceptionTableLength++] = exceptionInfo;
    }


    /**
     * Wraps up the current code fragment, continuing with the previous one on
     * the stack.
     */
    public void endCodeFragment()
    {
        if (level < 0)
        {
            throw new IllegalArgumentException("Code fragment not begun ["+level+"]");
        }

        // Remap the instructions of the code fragment.
        int instructionOffset = codeFragmentOffsets[level];
        while (instructionOffset < codeLength)
        {
            // Get the next instruction.
            Instruction instruction = InstructionFactory.create(code, instructionOffset);

            // Does this instruction still have to be remapped?
            if (oldInstructionOffsets[instructionOffset] >= 0)
            {
                // Adapt the instruction for its new offset.
                instruction.accept(null, null, null, instructionOffset, this);

                // Write the instruction back.
//                instruction.accept(null,
//                                   null,
//                                   new CodeAttribute(0, 0, 0, 0, code, 0, null, 0, null),
//                                   instructionOffset,
//                                   instructionWriter);
                instruction.write(code, instructionOffset);

                // Don't remap this instruction again.
                oldInstructionOffsets[instructionOffset] = -1;
            }

            // Continue remapping at the next instruction offset.
            instructionOffset += instruction.length(instructionOffset);
        }

        // Correct the estimated maximum code length, now that we know the
        // actual length of this code fragment.
        maximumCodeLength += codeLength - codeFragmentOffsets[level] -
                             codeFragmentLengths[level];

        // Try to remap the exception handlers that couldn't be remapped before.
        if (allowExternalExceptionHandlers)
        {
            for (int index = 0; index < exceptionTableLength; index++)
            {
                ExceptionInfo exceptionInfo = exceptionTable[index];

                // Unmapped exception handlers are still negated.
                int handlerPC = -exceptionInfo.u2handlerPC;
                if (handlerPC > 0)
                {
                    if (remappableInstructionOffset(handlerPC))
                    {
                        exceptionInfo.u2handlerPC = remapInstructionOffset(handlerPC);
                    }
                    else if (level == 0)
                    {
                        throw new IllegalStateException("Couldn't remap exception handler offset ["+handlerPC+"]");
                    }
                }
            }
        }

        level--;
    }


    // Implementations for AttributeVisitor.

    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}


    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
    {
        if (DEBUG)
        {
            System.out.println("CodeAttributeComposer: putting results in ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]");
        }

        if (level != -1)
        {
            throw new IllegalArgumentException("Code fragment not ended ["+level+"]");
        }

        level++;

        // Make sure the code attribute has sufficient space for the composed
        // code.
        if (codeAttribute.u4codeLength < codeLength)
        {
            codeAttribute.code = new byte[codeLength];
        }

        // Copy the composed code over into the code attribute.
        codeAttribute.u4codeLength = codeLength;
        System.arraycopy(code, 0, codeAttribute.code, 0, codeLength);

        // Remove exceptions with empty code blocks (done before).
        //exceptionTableLength =
        //    removeEmptyExceptions(exceptionTable, exceptionTableLength);

        // Make sure the exception table has sufficient space for the composed
        // exceptions.
        if (codeAttribute.exceptionTable.length < exceptionTableLength)
        {
            codeAttribute.exceptionTable = new ExceptionInfo[exceptionTableLength];
        }

        // Copy the exception table.
        codeAttribute.u2exceptionTableLength = exceptionTableLength;
        System.arraycopy(exceptionTable, 0, codeAttribute.exceptionTable, 0, exceptionTableLength);

        // Update the maximum stack size and local variable frame size.
        stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
        variableSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);

        // Remap  the line number table and the local variable table.
        codeAttribute.attributesAccept(clazz, method, this);

        // Remap the exception table.
        //codeAttribute.exceptionsAccept(clazz, method, this);

        // Remove exceptions with empty code blocks (done before).
        //codeAttribute.u2exceptionTableLength =
        //    removeEmptyExceptions(codeAttribute.exceptionTable,
        //                          codeAttribute.u2exceptionTableLength);

//        // Make sure instructions are widened if necessary.
//        instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);

        level--;
    }


    public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
    {
        // Remap all stack map entries.
        expectedStackMapFrameOffset = -1;
        stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
    }


    public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
    {
        // Remap all stack map table entries.
        expectedStackMapFrameOffset = 0;
        stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
    }


    public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
    {
        // Remap all line number table entries.
        lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);

        // Remove line numbers with empty code blocks.
        lineNumberTableAttribute.u2lineNumberTableLength =
           removeEmptyLineNumbers(lineNumberTableAttribute.lineNumberTable,
                                  lineNumberTableAttribute.u2lineNumberTableLength,
                                  codeAttribute.u4codeLength);
    }


    public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
    {
        // Remap all local variable table entries.
        localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);

        // Remove local variables with empty code blocks.
        localVariableTableAttribute.u2localVariableTableLength =
            removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,
                                      localVariableTableAttribute.u2localVariableTableLength,
                                      codeAttribute.u2maxLocals);
    }


    public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
    {
        // Remap all local variable table entries.
        localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);

        // Remove local variables with empty code blocks.
        localVariableTypeTableAttribute.u2localVariableTypeTableLength =
            removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
                                          localVariableTypeTableAttribute.u2localVariableTypeTableLength,
                                          codeAttribute.u2maxLocals);
    }


    // Implementations for InstructionVisitor.

    public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}


    public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
    {
        // Adjust the branch offset.
        branchInstruction.branchOffset = remapBranchOffset(offset,
                                                           branchInstruction.branchOffset);
    }


    public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
    {
        // Adjust the default jump offset.
        switchInstruction.defaultOffset = remapBranchOffset(offset,
                                                            switchInstruction.defaultOffset);

        // Adjust the jump offsets.
        remapJumpOffsets(offset,
                         switchInstruction.jumpOffsets);
    }


    // Implementations for ExceptionInfoVisitor.

    public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
    {
        // Remap the code offsets. Note that the instruction offset map also has
        // an entry for the first offset after the code, for u2endPC.
        exceptionInfo.u2startPC = remapInstructionOffset(exceptionInfo.u2startPC);
        exceptionInfo.u2endPC   = remapInstructionOffset(exceptionInfo.u2endPC);

        // See if we can remap the handler right away. Unmapped exception
        // handlers are negated, in order to mark them as external.
        int handlerPC = exceptionInfo.u2handlerPC;
        exceptionInfo.u2handlerPC =
            !allowExternalExceptionHandlers ||
            remappableInstructionOffset(handlerPC) ?
                remapInstructionOffset(handlerPC) :
                -handlerPC;
    }


    // Implementations for StackMapFrameVisitor.

    public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
    {
        // Remap the stack map frame offset.
        int stackMapFrameOffset = remapInstructionOffset(offset);

        int offsetDelta = stackMapFrameOffset;

        // Compute the offset delta if the frame is part of a stack map frame
        // table (for JDK 6.0) instead of a stack map (for Java Micro Edition).
        if (expectedStackMapFrameOffset >= 0)
        {
            offsetDelta -= expectedStackMapFrameOffset;

            expectedStackMapFrameOffset = stackMapFrameOffset + 1;
        }

        stackMapFrame.u2offsetDelta = offsetDelta;
    }


    public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
    {
        // Remap the stack map frame offset.
        visitAnyStackMapFrame(clazz, method, codeAttribute, offset, sameOneFrame);

        // Remap the verification type offset.
        sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
    }


    public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
    {
        // Remap the stack map frame offset.
        visitAnyStackMapFrame(clazz, method, codeAttribute, offset, moreZeroFrame);

        // Remap the verification type offsets.
        moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
    }


    public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
    {
        // Remap the stack map frame offset.
        visitAnyStackMapFrame(clazz, method, codeAttribute, offset, fullFrame);

        // Remap the verification type offsets.
        fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
        fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
    }


    // Implementations for VerificationTypeVisitor.

    public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}


    public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
    {
        // Remap the offset of the 'new' instruction.
        uninitializedType.u2newInstructionOffset = remapInstructionOffset(uninitializedType.u2newInstructionOffset);
    }


    // Implementations for LineNumberInfoVisitor.

    public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
    {
        // Remap the code offset.
        lineNumberInfo.u2startPC = remapInstructionOffset(lineNumberInfo.u2startPC);
    }


    // Implementations for LocalVariableInfoVisitor.

    public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
    {
        // Remap the code offset and length.
        // TODO: The local variable frame might not be strictly preserved.
        int startPC = remapInstructionOffset(localVariableInfo.u2startPC);
        int endPC   = remapInstructionOffset(localVariableInfo.u2startPC + localVariableInfo.u2length);

        localVariableInfo.u2startPC = startPC;
        localVariableInfo.u2length  = endPC - startPC;
    }

    // Implementations for LocalVariableTypeInfoVisitor.

    public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
    {
        // Remap the code offset and length.
        // TODO: The local variable frame might not be strictly preserved.
        int startPC = remapInstructionOffset(localVariableTypeInfo.u2startPC);
        int endPC   = remapInstructionOffset(localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length);

        localVariableTypeInfo.u2startPC = startPC;
        localVariableTypeInfo.u2length  = endPC - startPC;
    }


    // Small utility methods.

    /**
     * Make sure the code arrays have at least the given size.
     */
    private void ensureCodeLength(int newCodeLength)
    {
        if (code.length < newCodeLength)
        {
            // Add 20% to avoid extending the arrays too often.
            newCodeLength = newCodeLength * 6 / 5;

            byte[] newCode = new byte[newCodeLength];
            System.arraycopy(code, 0, newCode, 0, codeLength);
            code = newCode;

            int[] newOldInstructionOffsets = new int[newCodeLength];
            System.arraycopy(oldInstructionOffsets, 0, newOldInstructionOffsets, 0, codeLength);
            oldInstructionOffsets = newOldInstructionOffsets;
        }
    }


    /**
     * Adjusts the given jump offsets for the instruction at the given offset.
     */
    private void remapJumpOffsets(int offset, int[] jumpOffsets)
    {
        for (int index = 0; index < jumpOffsets.length; index++)
        {
            jumpOffsets[index] = remapBranchOffset(offset, jumpOffsets[index]);
        }
    }


    /**
     * Computes the new branch offset for the instruction at the given new offset
     * with the given old branch offset.
     */
    private int remapBranchOffset(int newInstructionOffset, int branchOffset)
    {
        if (newInstructionOffset < 0 ||
            newInstructionOffset > codeLength)
        {
            throw new IllegalArgumentException("Invalid instruction offset ["+newInstructionOffset +"] in code with length ["+codeLength+"]");
        }

        int oldInstructionOffset = oldInstructionOffsets[newInstructionOffset];

        return remapInstructionOffset(oldInstructionOffset + branchOffset) -
               remapInstructionOffset(oldInstructionOffset);
    }


    /**
     * Computes the new instruction offset for the instruction at the given old
     * offset.
     */
    private int remapInstructionOffset(int oldInstructionOffset)
    {
        if (oldInstructionOffset < 0 ||
            oldInstructionOffset > codeFragmentLengths[level])
        {
            throw new IllegalArgumentException("Instruction offset ["+oldInstructionOffset +"] out of range in code fragment with length ["+codeFragmentLengths[level]+"] at level "+level);
        }

        int newInstructionOffset = instructionOffsetMap[level][oldInstructionOffset];
        if (newInstructionOffset == INVALID)
        {
            throw new IllegalArgumentException("Invalid instruction offset ["+oldInstructionOffset +"] in code fragment at level "+level);
        }

        return newInstructionOffset;
    }


    /**
     * Returns whether the given old instruction offset can be remapped at the
     */
    private boolean remappableInstructionOffset(int oldInstructionOffset)
    {
        return
            oldInstructionOffset <= codeFragmentLengths[level] &&
            instructionOffsetMap[level][oldInstructionOffset] > INVALID;
    }


    /**
     * Returns the given list of exceptions, without the ones that have empty
     * code blocks.
     */
    private int removeEmptyExceptions(ExceptionInfo[] exceptionInfos,
                                      int             exceptionInfoCount)
    {
        // Overwrite all empty exceptions.
        int newIndex = 0;
        for (int index = 0; index < exceptionInfoCount; index++)
        {
            ExceptionInfo exceptionInfo = exceptionInfos[index];
            if (exceptionInfo.u2startPC < exceptionInfo.u2endPC)
            {
                exceptionInfos[newIndex++] = exceptionInfo;
            }
        }

        // Clear the unused array entries.
        for (int index = newIndex; index < exceptionInfoCount; index++)
        {
            exceptionInfos[index] = null;
        }

        return newIndex;
    }


    /**
     * Returns the given list of line numbers, without the ones that have empty
     * code blocks or that exceed the code size.
     */
    private int removeEmptyLineNumbers(LineNumberInfo[] lineNumberInfos,
                                       int              lineNumberInfoCount,
                                       int              codeLength)
    {
        // Overwrite all empty line number entries.
        int newIndex = 0;
        for (int index = 0; index < lineNumberInfoCount; index++)
        {
            LineNumberInfo lineNumberInfo = lineNumberInfos[index];
            int startPC = lineNumberInfo.u2startPC;
            if (startPC < codeLength &&
                (index == 0 || startPC > lineNumberInfos[index-1].u2startPC))
            {
                lineNumberInfos[newIndex++] = lineNumberInfo;
            }
        }

        // Clear the unused array entries.
        for (int index = newIndex; index < lineNumberInfoCount; index++)
        {
            lineNumberInfos[index] = null;
        }

        return newIndex;
    }


    /**
     * Returns the given list of local variables, without the ones that have empty
     * code blocks or that exceed the actual number of local variables.
     */
    private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos,
                                          int                 localVariableInfoCount,
                                          int                 maxLocals)
    {
        // Overwrite all empty local variable entries.
        int newIndex = 0;
        for (int index = 0; index < localVariableInfoCount; index++)
        {
            LocalVariableInfo localVariableInfo = localVariableInfos[index];
            if (localVariableInfo.u2length > 0 &&
                localVariableInfo.u2index < maxLocals)
            {
                localVariableInfos[newIndex++] = localVariableInfo;
            }
        }

        // Clear the unused array entries.
        for (int index = newIndex; index < localVariableInfoCount; index++)
        {
            localVariableInfos[index] = null;
        }

        return newIndex;
    }


    /**
     * Returns the given list of local variable types, without the ones that
     * have empty code blocks or that exceed the actual number of local variables.
     */
    private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
                                              int                     localVariableTypeInfoCount,
                                              int                     maxLocals)
    {
        // Overwrite all empty local variable type entries.
        int newIndex = 0;
        for (int index = 0; index < localVariableTypeInfoCount; index++)
        {
            LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
            if (localVariableTypeInfo.u2length > 0 &&
                localVariableTypeInfo.u2index < maxLocals)
            {
                localVariableTypeInfos[newIndex++] = localVariableTypeInfo;
            }
        }

        // Clear the unused array entries.
        for (int index = newIndex; index < localVariableTypeInfoCount; index++)
        {
            localVariableTypeInfos[index] = null;
        }

        return newIndex;
    }


    private void println(String string1, String string2)
    {
        print(string1, string2);

        System.out.println();
    }

    private void print(String string1, String string2)
    {
        System.out.print(string1);

        for (int index = 0; index < level; index++)
        {
            System.out.print("  ");
        }

        System.out.print(string2);
    }


    public static void main(String[] args)
    {
        CodeAttributeComposer composer = new CodeAttributeComposer();

        composer.beginCodeFragment(4);
        composer.appendInstruction(0, new SimpleInstruction(InstructionConstants.OP_ICONST_0));
        composer.appendInstruction(1, new VariableInstruction(InstructionConstants.OP_ISTORE, 0));
        composer.appendInstruction(2, new BranchInstruction(InstructionConstants.OP_GOTO, 1));

        composer.beginCodeFragment(4);
        composer.appendInstruction(0, new VariableInstruction(InstructionConstants.OP_IINC, 0, 1));
        composer.appendInstruction(1, new VariableInstruction(InstructionConstants.OP_ILOAD, 0));
        composer.appendInstruction(2, new SimpleInstruction(InstructionConstants.OP_ICONST_5));
        composer.appendInstruction(3, new BranchInstruction(InstructionConstants.OP_IFICMPLT, -3));
        composer.endCodeFragment();

        composer.appendInstruction(3, new SimpleInstruction(InstructionConstants.OP_RETURN));
        composer.endCodeFragment();
    }
}
