/*
 *  Copyright 2004 Brian S O'Neill
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package cojen.classfile;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cojen.classfile.attr.CodeAttr;
import cojen.classfile.attr.SignatureAttr;

/**
 * Disassembles a class file, sending the results to standard out. The class
 * can be specified by name or by a file name. If the class is specified by
 * name, it must be available in the classpath.
 * <p>
 * Two output formats are supported: assembly and builder. The assembly format
 * is the default, and it produces a pseudo Java source file, where the method
 * bodies contain JVM assembly code.
 * <p>
 * The builder format produces a valid Java file, which uses the Cojen
 * classfile API. When compiled and run, it rebuilds the original class and
 * inner classes. This format makes it easier to understand how to use the
 * classfile API to generate new classes.
 *
 * @author Brian S O'Neill
 */
public class DisassemblyTool {
    /**
     * Disassembles a class file, sending the results to standard out. Accepts
     * the following arguments:
     * <pre>
     * args[0]: name of class or file
     * args[1]: output format, assembly (default) or builder
     * </pre>
     */
    public static void main(String[] args) throws Exception {
        ClassFileDataLoader loader;
        InputStream in;

        try {
            final File file = new File(args[0]);
            in = new FileInputStream(file);
            loader = new ClassFileDataLoader() {
                public InputStream getClassData(String name)
                    throws IOException
                {
                    name = name.substring(name.lastIndexOf('.') + 1);
                    File f = new File(file.getParentFile(), name + ".class");

                    if (f.exists()) {
                        return new FileInputStream(f);
                    }

                    return null;
                }
            };
        } catch (FileNotFoundException e) {
            if (args[0].endsWith(".class")) {
                System.err.println(e);
                return;
            }

            loader = new ResourceClassFileDataLoader();
            in = loader.getClassData(args[0]);

            if (in == null) {
                System.err.println(e);
                return;
            }
        }

        in = new BufferedInputStream(in);
        ClassFile cf = ClassFile.readFrom(in, loader, null);

        PrintWriter out = new PrintWriter(System.out);

        String style = null;
        if (args.length > 1) {
            style = args[1];
        }

        Printer p;
        if (style == null || style.equals("assembly")) {
            p = new AssemblyStylePrinter();
        } else if (style.equals("builder")) {
            p = new BuilderStylePrinter();
        } else {
            System.err.println("Unknown format style: " + style);
            return;
        }

        p.disassemble(cf, out);

        out.flush();
    }

    public static interface Printer {
        void disassemble(ClassFile cf, PrintWriter out);
    }
}

@@ -1924,139 +1924,167 @@
 out.
- Accepts%0A     * the following arguments:%0A     * %3Cpre%3E%0A     * args%5B0%5D: name of
+%0A     *%0A     * %3Cpre%3E%0A     * DisassemblyTool %5B-f &lt;format style&gt;%5D &lt;file or
  class 
-or file%0A     * args%5B1%5D: output format, 
+name&gt;%0A     * %3C/pre%3E%0A     * %0A     * The format style may be %22
 assembly
  (de
@@ -2079,18 +2079,23 @@
 assembly
+%22
  (
+the 
 default)
@@ -2102,29 +2102,18 @@
  or 
+%22
 builder
-%0A     * %3C/pre%3E
+%22.
 %0A   
@@ -2179,16 +2179,241 @@
 ption %7B%0A
+        String style;%0A        String name;%0A%0A        if (%22-f%22.equals(args%5B0%5D)) %7B%0A            style = args%5B1%5D;%0A            name = args%5B2%5D;%0A        %7D else %7B%0A            style = %22assembly%22;%0A            name = args%5B0%5D;%0A        %7D%0A%0A
         
@@ -2518,23 +2518,20 @@
 ew File(
-args%5B0%5D
+name
 );%0A     
@@ -3127,23 +3127,20 @@
     if (
-args%5B0%5D
+name
 .endsWit
@@ -3325,23 +3325,20 @@
 assData(
-args%5B0%5D
+name
 );%0A%0A    
@@ -3615,108 +3615,8 @@
 );%0A%0A
-        String style = null;%0A        if (args.length %3E 1) %7B%0A            style = args%5B1%5D;%0A        %7D%0A%0A
     

Change how options are passed in.