1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.dx.command.dump;
18
19import com.android.dex.util.FileUtils;
20import com.android.dx.cf.iface.ParseException;
21import com.android.dx.util.HexParser;
22import java.io.UnsupportedEncodingException;
23
24/**
25 * Main class for the class file dumper.
26 */
27public class Main {
28
29    private final Args parsedArgs = new Args();
30
31    /**
32     * This class is uninstantiable.
33     */
34    private Main() {
35        // This space intentionally left blank.
36    }
37
38    public static void main(String[] args) {
39        new Main().run(args);
40    }
41
42    /**
43     * Run!
44     */
45    private void run(String[] args) {
46        int at = 0;
47
48        for (/*at*/; at < args.length; at++) {
49            String arg = args[at];
50            if (arg.equals("--") || !arg.startsWith("--")) {
51                break;
52            } else if (arg.equals("--bytes")) {
53                parsedArgs.rawBytes = true;
54            } else if (arg.equals("--basic-blocks")) {
55                parsedArgs.basicBlocks = true;
56            } else if (arg.equals("--rop-blocks")) {
57                parsedArgs.ropBlocks = true;
58            } else if (arg.equals("--optimize")) {
59                parsedArgs.optimize = true;
60            } else if (arg.equals("--ssa-blocks")) {
61                parsedArgs.ssaBlocks = true;
62            } else if (arg.startsWith("--ssa-step=")) {
63                parsedArgs.ssaStep = arg.substring(arg.indexOf('=') + 1);
64            } else if (arg.equals("--debug")) {
65                parsedArgs.debug = true;
66            } else if (arg.equals("--dot")) {
67                parsedArgs.dotDump = true;
68            } else if (arg.equals("--strict")) {
69                parsedArgs.strictParse = true;
70            } else if (arg.startsWith("--width=")) {
71                arg = arg.substring(arg.indexOf('=') + 1);
72                parsedArgs.width = Integer.parseInt(arg);
73            } else if (arg.startsWith("--method=")) {
74                arg = arg.substring(arg.indexOf('=') + 1);
75                parsedArgs.method = arg;
76            } else {
77                System.err.println("unknown option: " + arg);
78                throw new RuntimeException("usage");
79            }
80        }
81
82        if (at == args.length) {
83            System.err.println("no input files specified");
84            throw new RuntimeException("usage");
85        }
86
87        for (/*at*/; at < args.length; at++) {
88            try {
89                String name = args[at];
90                System.out.println("reading " + name + "...");
91                byte[] bytes = FileUtils.readFile(name);
92                if (!name.endsWith(".class")) {
93                    String src;
94                    try {
95                        src = new String(bytes, "utf-8");
96                    } catch (UnsupportedEncodingException ex) {
97                        throw new RuntimeException("shouldn't happen", ex);
98                    }
99                    bytes = HexParser.parse(src);
100                }
101                processOne(name, bytes);
102            } catch (ParseException ex) {
103                System.err.println("\ntrouble parsing:");
104                if (parsedArgs.debug) {
105                    ex.printStackTrace();
106                } else {
107                    ex.printContext(System.err);
108                }
109            }
110        }
111    }
112
113    /**
114     * Processes one file.
115     *
116     * @param name {@code non-null;} name of the file
117     * @param bytes {@code non-null;} contents of the file
118     */
119    private void processOne(String name, byte[] bytes) {
120        if (parsedArgs.dotDump) {
121            DotDumper.dump(bytes, name, parsedArgs);
122        } else if (parsedArgs.basicBlocks) {
123            BlockDumper.dump(bytes, System.out, name, false, parsedArgs);
124        } else if (parsedArgs.ropBlocks) {
125            BlockDumper.dump(bytes, System.out, name, true, parsedArgs);
126        } else if (parsedArgs.ssaBlocks) {
127            // --optimize ignored with --ssa-blocks
128            parsedArgs.optimize = false;
129            SsaDumper.dump(bytes, System.out, name, parsedArgs);
130        } else {
131            ClassDumper.dump(bytes, System.out, name, parsedArgs);
132        }
133    }
134}
135