/**
   * Creates the print
   *
   * @return The print as an ArrayList
   */
  public ArrayList<String> createPrint() {
    ArrayList<String> info = new ArrayList<String>();
    ListIterator<?> it = mNode.instructions.iterator();
    boolean firstLabel = false;
    while (it.hasNext()) {
      AbstractInsnNode ain = (AbstractInsnNode) it.next();
      String line = "";
      if (ain instanceof VarInsnNode) {
        line = printVarInsnNode((VarInsnNode) ain, it);
      } else if (ain instanceof IntInsnNode) {
        line = printIntInsnNode((IntInsnNode) ain, it);
      } else if (ain instanceof FieldInsnNode) {
        line = printFieldInsnNode((FieldInsnNode) ain, it);
      } else if (ain instanceof MethodInsnNode) {
        line = printMethodInsnNode((MethodInsnNode) ain, it);
      } else if (ain instanceof LdcInsnNode) {
        line = printLdcInsnNode((LdcInsnNode) ain, it);
      } else if (ain instanceof InsnNode) {
        line = printInsnNode((InsnNode) ain, it);
      } else if (ain instanceof JumpInsnNode) {
        line = printJumpInsnNode((JumpInsnNode) ain, it);
      } else if (ain instanceof LineNumberNode) {
        line = printLineNumberNode((LineNumberNode) ain, it);
      } else if (ain instanceof LabelNode) {
        if (firstLabel
            && Decompiler.BYTECODE
                .getSettings()
                .isSelected(ClassNodeDecompiler.Settings.APPEND_BRACKETS_TO_LABELS)) info.add("}");

        line = printLabelnode((LabelNode) ain);

        if (Decompiler.BYTECODE
            .getSettings()
            .isSelected(ClassNodeDecompiler.Settings.APPEND_BRACKETS_TO_LABELS)) {
          if (!firstLabel) firstLabel = true;
          line += " {";
        }
      } else if (ain instanceof TypeInsnNode) {
        line = printTypeInsnNode((TypeInsnNode) ain);
      } else if (ain instanceof FrameNode) {
        line = "";
      } else if (ain instanceof IincInsnNode) {
        line = printIincInsnNode((IincInsnNode) ain);
      } else if (ain instanceof TableSwitchInsnNode) {
        line = printTableSwitchInsnNode((TableSwitchInsnNode) ain);
      } else if (ain instanceof LookupSwitchInsnNode) {
        line = printLookupSwitchInsnNode((LookupSwitchInsnNode) ain);
      } else if (ain instanceof InvokeDynamicInsnNode) {
        line = printInvokeDynamicInsNode((InvokeDynamicInsnNode) ain);
      } else {
        line += "UNADDED OPCODE: " + nameOpcode(ain.opcode()) + " " + ain.toString();
      }
      if (!line.equals("")) {
        if (match) if (matchedInsns.contains(ain)) line = "   -> " + line;

        info.add(line);
      }
    }
    if (firstLabel
        && Decompiler.BYTECODE
            .getSettings()
            .isSelected(ClassNodeDecompiler.Settings.APPEND_BRACKETS_TO_LABELS)) info.add("}");
    return info;
  }
 public int getJumpStackSize(int level) {
   int size = 0;
   for (int i = jumpStack.size(); i >= 0 && jumpStack.size() - i < level; i--) {
     JumpItem item = getJump(i);
     size += item.stackSize;
   }
   return size;
 }
  protected String printLookupSwitchInsnNode(LookupSwitchInsnNode lin) {
    String line = nameOpcode(lin.opcode()) + ": \n";
    List<?> keys = lin.keys;
    List<?> labels = lin.labels;

    for (int i = 0; i < keys.size(); i++) {
      int key = (Integer) keys.get(i);
      LabelNode label = (LabelNode) labels.get(i);
      line += "                val: " + key + " -> " + "L" + resolveLabel(label) + "\n";
    }
    line += "                default" + " -> L" + resolveLabel(lin.dflt) + "";
    return line;
  }
 protected String printTableSwitchInsnNode(TableSwitchInsnNode tin) {
   String line = nameOpcode(tin.opcode()) + " \n";
   List<?> labels = tin.labels;
   int count = 0;
   for (int i = tin.min; i < tin.max + 1; i++) {
     line +=
         "                val: "
             + i
             + " -> "
             + "L"
             + resolveLabel((LabelNode) labels.get(count++))
             + "\n";
   }
   line += "                default" + " -> L" + resolveLabel(tin.dflt) + "";
   return line;
 }
  private void replaceObfuscatedMethodNames(AsmagicDiffVisitor dv) {
    for (MethodNode mn : dv.newMethods) {
      if (mn.visibleAnnotations != null) {
        for (Object oan : mn.visibleAnnotations) {
          AnnotationNode an = (AnnotationNode) oan;
          if (an.desc.contains("AsmagicMethodReplace")) {
            List<Object> vals = an.values;

            String alias = null;
            if (vals != null || vals.size() > 1) {
              alias = (String) vals.get(1);
              dv.methodsToReplace.put(alias, 1);
              mn.name = alias;
            }
          }
        }
      }
    }
  }
  /**
   * It is assumed that ALL CLASSES regardless of nesting, have unique names In addition, it is
   * assumed that there is not multi-level nesting A SOURCE STRUCTURE OBJECT CAN ONLY HANDLE ONE
   * LEVEL OF CLASS NESTING
   *
   * @param targetClass
   * @param depth
   * @throws IOException
   */
  private void findNestedInnerClasses(ClassNode2 targetClass, int depth) throws IOException {

    // saves the depth of a particular inner class
    depth++;

    // get the inner classes of a class
    List<InnerClassNode2> innerClassNodes = targetClass.innerClasses;

    // returns if there are no inner classes
    if (innerClassNodes == null) {
      return;
    } else {

      // if there are inner classes, each inner class is converted to a ClassStructure
      // object and stored in an ArrayList
      for (int i = 0; i < innerClassNodes.size(); i++) {
        classStructures.add(new ClassStructure(innerClassNodes.get(i).name, depth));
      }
    }
  }
 public InstructionPrinter(MethodNode m, InstructionPattern pattern, TypeAndName[] args) {
   this.args = args;
   mNode = m;
   labels = new HashMap<LabelNode, Integer>();
   searcher = new InstructionSearcher(m.instructions, pattern);
   match = searcher.search();
   if (match) {
     for (AbstractInsnNode[] ains : searcher.getMatches()) {
       for (AbstractInsnNode ain : ains) {
         matchedInsns.add(ain);
       }
     }
   }
 }
 public void popJump() {
   jumpStack.remove(jumpStack.size() - 1);
 }
  public JumpItem getJump(int level) {
    if (jumpStack.size() - level < 0) return null;
    if (jumpStack.size() - level >= jumpStack.size()) return null;

    return jumpStack.get(jumpStack.size() - level);
  }
 public void pushJump(LabelNode breakLabel, LabelNode continueLabel, int stackSize) {
   jumpStack.add(new JumpItem(breakLabel, continueLabel, stackSize));
 }