gt:         if (modules != null && modules.length > 0) {
context: /***
   * ASM: a very small and fast Java bytecode manipulation framework
   * Copyright (c) 2000-2011 INRIA, France Telecom
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. Neither the name of the copyright holders nor the names of its
   *    contributors may be used to endorse or promote products derived from
   *    this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   * THE POSSIBILITY OF SUCH DAMAGE.
   */
  package org.eclipse.persistence.internal.libraries.asm.util;
  
  import java.io.FileInputStream;
  import java.io.PrintWriter;
  import java.util.HashMap;
  import java.util.Map;
  
  import org.eclipse.persistence.internal.libraries.asm.Attribute;
  import org.eclipse.persistence.internal.libraries.asm.ClassReader;
  import org.eclipse.persistence.internal.libraries.asm.Handle;
  import org.eclipse.persistence.internal.libraries.asm.Label;
  import org.eclipse.persistence.internal.libraries.asm.Opcodes;
  import org.eclipse.persistence.internal.libraries.asm.Type;
  import org.eclipse.persistence.internal.libraries.asm.TypePath;
  import org.eclipse.persistence.internal.libraries.asm.TypeReference;
  import org.eclipse.persistence.internal.libraries.asm.signature.SignatureReader;
  
  /**
   * A {@link Printer} that prints a disassembled view of the classes it visits.
   *
   * @author Eric Bruneton
   */
  public class Textifier extends Printer {
  
      /**
       * Constant used in {@link #appendDescriptor appendDescriptor} for internal
       * type names in bytecode notation.
       */
      public static final int INTERNAL_NAME = 0;
  
      /**
       * Constant used in {@link #appendDescriptor appendDescriptor} for field
       * descriptors, formatted in bytecode notation
       */
      public static final int FIELD_DESCRIPTOR = 1;
  
      /**
       * Constant used in {@link #appendDescriptor appendDescriptor} for field
       * signatures, formatted in bytecode notation
       */
      public static final int FIELD_SIGNATURE = 2;
  
      /**
       * Constant used in {@link #appendDescriptor appendDescriptor} for method
       * descriptors, formatted in bytecode notation
       */
      public static final int METHOD_DESCRIPTOR = 3;
  
      /**
       * Constant used in {@link #appendDescriptor appendDescriptor} for method
       * signatures, formatted in bytecode notation
       */
      public static final int METHOD_SIGNATURE = 4;
  
      /**
       * Constant used in {@link #appendDescriptor appendDescriptor} for class
       * signatures, formatted in bytecode notation
       */
      public static final int CLASS_SIGNATURE = 5;
  
      /**
       * Constant used in {@link #appendDescriptor appendDescriptor} for field or
       * method return value signatures, formatted in default Java notation
       * (non-bytecode)
       */
      public static final int TYPE_DECLARATION = 6;
  
      /**
       * Constant used in {@link #appendDescriptor appendDescriptor} for class
       * signatures, formatted in default Java notation (non-bytecode)
       */
      public static final int CLASS_DECLARATION = 7;
  
      /**
       * Constant used in {@link #appendDescriptor appendDescriptor} for method
       * parameter signatures, formatted in default Java notation (non-bytecode)
       */
      public static final int PARAMETERS_DECLARATION = 8;
  
      /**
       * Constant used in {@link #appendDescriptor appendDescriptor} for handle
       * descriptors, formatted in bytecode notation
       */
      public static final int HANDLE_DESCRIPTOR = 9;
  
      /**
       * Tab for class members.
       */
      protected String tab = "  ";
  
      /**
       * Tab for bytecode instructions.
       */
      protected String tab2 = "    ";
  
      /**
       * Tab for table and lookup switch instructions.
       */
      protected String tab3 = "      ";
  
      /**
       * Tab for labels.
       */
      protected String ltab = "   ";
  
      /**
       * The label names. This map associate String values to Label keys.
       */
      protected Map<Label, String> labelNames;
  
      /**
       * Class access flags
       */
      private int access;
  
      private int valueNumber = 0;
  
      /**
       * Constructs a new {@link Textifier}. <i>Subclasses must not use this
       * constructor</i>. Instead, they must use the {@link #Textifier(int)}
       * version.
       *
       * @throws IllegalStateException
       *             If a subclass calls this constructor.
       */
      public Textifier() {
          this(Opcodes.ASM6);
          if (getClass() != Textifier.class) {
              throw new IllegalStateException();
          }
      }
  
      /**
       * Constructs a new {@link Textifier}.
       *
       * @param api
       *            the ASM API version implemented by this visitor. Must be one
       *            of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
       */
      protected Textifier(final int api) {
          super(api);
      }
  
      /**
       * Prints a disassembled view of the given class to the standard output.
       * <p>
       * Usage: Textifier [-debug] &lt;binary class name or class file name &gt;
       *
       * @param args
       *            the command line arguments.
       *
       * @throws Exception
       *             if the class cannot be found, or if an IO exception occurs.
       */
      public static void main(final String[] args) throws Exception {
          int i = 0;
          int flags = ClassReader.SKIP_DEBUG;
  
          boolean ok = true;
          if (args.length < 1 || args.length > 2) {
              ok = false;
          }
          if (ok && "-debug".equals(args[0])) {
              i = 1;
              flags = 0;
              if (args.length != 2) {
                  ok = false;
              }
          }
          if (!ok) {
              System.err
                      .println("Prints a disassembled view of the given class.");
              System.err.println("Usage: Textifier [-debug] "
                      + "<fully qualified class name or class file name>");
              return;
          }
          ClassReader cr;
          if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
                  || args[i].indexOf('/') > -1) {
              cr = new ClassReader(new FileInputStream(args[i]));
          } else {
              cr = new ClassReader(args[i]);
          }
          cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), flags);
      }
  
      // ------------------------------------------------------------------------
      // Classes
      // ------------------------------------------------------------------------
  
      @Override
      public void visit(final int version, final int access, final String name,
              final String signature, final String superName,
              final String[] interfaces) {
          if ((access & Opcodes.ACC_MODULE) != 0) {
              // visitModule will print the module
              return;
          }
          this.access = access;
          int major = version & 0xFFFF;
          int minor = version >>> 16;
          buf.setLength(0);
          buf.append("// class version ").append(major).append('.').append(minor)
                  .append(" (").append(version).append(")\n");
          if ((access & Opcodes.ACC_DEPRECATED) != 0) {
              buf.append("// DEPRECATED\n");
          }
          buf.append("// access flags 0x")
                  .append(Integer.toHexString(access).toUpperCase()).append('\n');
  
          appendDescriptor(CLASS_SIGNATURE, signature);
          if (signature != null) {
              TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
              SignatureReader r = new SignatureReader(signature);
              r.accept(sv);
              buf.append("// declaration: ").append(name)
                      .append(sv.getDeclaration()).append('\n');
          }
  
          appendAccess(access & ~(Opcodes.ACC_SUPER | Opcodes.ACC_MODULE));
          if ((access & Opcodes.ACC_ANNOTATION) != 0) {
              buf.append("@interface ");
          } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
              buf.append("interface ");
          } else if ((access & Opcodes.ACC_ENUM) == 0) {
              buf.append("class ");
          }
          appendDescriptor(INTERNAL_NAME, name);
  
          if (superName != null && !"java/lang/Object".equals(superName)) {
              buf.append(" extends ");
              appendDescriptor(INTERNAL_NAME, superName);
              buf.append(' ');
          }
          if (interfaces != null && interfaces.length > 0) {
              buf.append(" implements ");
              for (int i = 0; i < interfaces.length; ++i) {
                  appendDescriptor(INTERNAL_NAME, interfaces[i]);
                  buf.append(' ');
              }
          }
          buf.append(" {\n\n");
  
          text.add(buf.toString());
      }
  
      @Override
      public void visitSource(final String file, final String debug) {
          buf.setLength(0);
          if (file != null) {
              buf.append(tab).append("// compiled from: ").append(file)
                      .append('\n');
          }
          if (debug != null) {
              buf.append(tab).append("// debug info: ").append(debug)
                      .append('\n');
          }
          if (buf.length() > 0) {
              text.add(buf.toString());
          }
      }
      
      @Override
      public Printer visitModule(final String name, final int access,
              final String version) {
          buf.setLength(0);
          if ((access & Opcodes.ACC_OPEN) != 0) {
              buf.append("open ");
          }
          buf.append("module ")
             .append(name)
             .append(" { ")
             .append(version == null ? "" : "// " + version)
             .append("\n\n");
          text.add(buf.toString());
          Textifier t = createTextifier();
          text.add(t.getText());
          return t;
      }
  
      @Override
      public void visitOuterClass(final String owner, final String name,
              final String desc) {
          buf.setLength(0);
          buf.append(tab).append("OUTERCLASS ");
          appendDescriptor(INTERNAL_NAME, owner);
          buf.append(' ');
          if (name != null) {
              buf.append(name).append(' ');
          }
          appendDescriptor(METHOD_DESCRIPTOR, desc);
          buf.append('\n');
          text.add(buf.toString());
      }
  
      @Override
      public Textifier visitClassAnnotation(final String desc,
              final boolean visible) {
          text.add("\n");
          return visitAnnotation(desc, visible);
      }
  
      @Override
      public Printer visitClassTypeAnnotation(int typeRef, TypePath typePath,
              String desc, boolean visible) {
          text.add("\n");
          return visitTypeAnnotation(typeRef, typePath, desc, visible);
      }
  
      @Override
      public void visitClassAttribute(final Attribute attr) {
          text.add("\n");
          visitAttribute(attr);
      }
  
      @Override
      public void visitInnerClass(final String name, final String outerName,
              final String innerName, final int access) {
          buf.setLength(0);
          buf.append(tab).append("// access flags 0x");
          buf.append(
                  Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase())
                  .append('\n');
          buf.append(tab);
          appendAccess(access);
          buf.append("INNERCLASS ");
          appendDescriptor(INTERNAL_NAME, name);
          buf.append(' ');
          appendDescriptor(INTERNAL_NAME, outerName);
          buf.append(' ');
          appendDescriptor(INTERNAL_NAME, innerName);
          buf.append('\n');
          text.add(buf.toString());
      }
  
      @Override
      public Textifier visitField(final int access, final String name,
              final String desc, final String signature, final Object value) {
          buf.setLength(0);
          buf.append('\n');
          if ((access & Opcodes.ACC_DEPRECATED) != 0) {
              buf.append(tab).append("// DEPRECATED\n");
          }
          buf.append(tab).append("// access flags 0x")
                  .append(Integer.toHexString(access).toUpperCase()).append('\n');
          if (signature != null) {
              buf.append(tab);
              appendDescriptor(FIELD_SIGNATURE, signature);
  
              TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
              SignatureReader r = new SignatureReader(signature);
              r.acceptType(sv);
              buf.append(tab).append("// declaration: ")
                      .append(sv.getDeclaration()).append('\n');
          }
  
          buf.append(tab);
          appendAccess(access);
  
          appendDescriptor(FIELD_DESCRIPTOR, desc);
          buf.append(' ').append(name);
          if (value != null) {
              buf.append(" = ");
              if (value instanceof String) {
                  buf.append('\"').append(value).append('\"');
              } else {
                  buf.append(value);
              }
          }
  
          buf.append('\n');
          text.add(buf.toString());
  
          Textifier t = createTextifier();
          text.add(t.getText());
          return t;
      }
  
      @Override
      public Textifier visitMethod(final int access, final String name,
              final String desc, final String signature, final String[] exceptions) {
          buf.setLength(0);
          buf.append('\n');
          if ((access & Opcodes.ACC_DEPRECATED) != 0) {
              buf.append(tab).append("// DEPRECATED\n");
          }
          buf.append(tab).append("// access flags 0x")
                  .append(Integer.toHexString(access).toUpperCase()).append('\n');
  
          if (signature != null) {
              buf.append(tab);
              appendDescriptor(METHOD_SIGNATURE, signature);
  
              TraceSignatureVisitor v = new TraceSignatureVisitor(0);
              SignatureReader r = new SignatureReader(signature);
              r.accept(v);
              String genericDecl = v.getDeclaration();
              String genericReturn = v.getReturnType();
              String genericExceptions = v.getExceptions();
  
              buf.append(tab).append("// declaration: ").append(genericReturn)
                      .append(' ').append(name).append(genericDecl);
              if (genericExceptions != null) {
                  buf.append(" throws ").append(genericExceptions);
              }
              buf.append('\n');
          }
  
          buf.append(tab);
          appendAccess(access & ~(Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT));
          if ((access & Opcodes.ACC_NATIVE) != 0) {
              buf.append("native ");
          }
          if ((access & Opcodes.ACC_VARARGS) != 0) {
              buf.append("varargs ");
          }
          if ((access & Opcodes.ACC_BRIDGE) != 0) {
              buf.append("bridge ");
          }
          if ((this.access & Opcodes.ACC_INTERFACE) != 0
                  && (access & Opcodes.ACC_ABSTRACT) == 0
                  && (access & Opcodes.ACC_STATIC) == 0) {
              buf.append("default ");
          }
  
          buf.append(name);
          appendDescriptor(METHOD_DESCRIPTOR, desc);
          if (exceptions != null && exceptions.length > 0) {
              buf.append(" throws ");
              for (int i = 0; i < exceptions.length; ++i) {
                  appendDescriptor(INTERNAL_NAME, exceptions[i]);
                  buf.append(' ');
              }
          }
  
          buf.append('\n');
          text.add(buf.toString());
  
          Textifier t = createTextifier();
          text.add(t.getText());
          return t;
      }
  
      @Override
      public void visitClassEnd() {
          text.add("}\n");
      }
  
      // ------------------------------------------------------------------------
      // Module
      // ------------------------------------------------------------------------
      
      @Override
      public void visitMainClass(String mainClass) {
          buf.setLength(0);
          buf.append("  // main class ").append(mainClass).append('\n');
          text.add(buf.toString());
      }
      
      @Override
      public void visitPackage(String packaze) {
          buf.setLength(0);
          buf.append("  // package ").append(packaze).append('\n');
          text.add(buf.toString());
      }
      
      @Override
      public void visitRequire(String require, int access, String version) {
          buf.setLength(0);
          buf.append(tab).append("requires ");
          if ((access & Opcodes.ACC_TRANSITIVE) != 0) {
              buf.append("transitive ");
          }
          if ((access & Opcodes.ACC_STATIC_PHASE) != 0) {
              buf.append("static ");
          }
          buf.append(require)
             .append(";  // access flags 0x")
             .append(Integer.toHexString(access).toUpperCase())
             .append('\n');
          if (version != null) {
              buf.append("  // version ")
                 .append(version)
                 .append('\n');
          }
          text.add(buf.toString());
      }
      
      @Override
      public void visitExport(String export, int access, String... modules) {
          buf.setLength(0);
          buf.append(tab).append("exports ");
          buf.append(export);
  