Home | History | Annotate | Download | only in dasm
      1 /*
      2  * Copyright (C) 2008 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 
     17 package dasm;
     18 
     19 import java.io.BufferedReader;
     20 import java.io.Closeable;
     21 import java.io.File;
     22 import java.io.FileInputStream;
     23 import java.io.FileOutputStream;
     24 import java.io.FileWriter;
     25 import java.io.IOException;
     26 import java.io.InputStreamReader;
     27 import java.io.Reader;
     28 
     29 /**
     30  * DAsm entry point
     31  */
     32 public class Main {
     33 
     34     /**
     35      * The Dasm version
     36      */
     37     public static final String version = "v0.1";
     38     public static final boolean DEBUG = !false;
     39 
     40     /**
     41      * destination path to place .dex file(s)
     42      */
     43     private static String destPath = null;
     44 
     45     /**
     46      * generate human-readable files
     47      */
     48     private static boolean humanHeadable = false;
     49 
     50     /**
     51      * input files codepage
     52      */
     53     private static String encoding = null;
     54 
     55     /**
     56      * automatically generate line numbers
     57      */
     58     private static boolean generateLineNumbers = false;
     59 
     60     private static void incompleteOption(String opt) {
     61         System.err.println("Command line option " + opt
     62                 + " required argument missed");
     63         System.exit(-1);
     64     }
     65 
     66     private static Reader createReader(String fname) throws IOException {
     67         FileInputStream fs = new FileInputStream(fname);
     68         InputStreamReader ir;
     69         if (encoding == null)
     70             ir = new InputStreamReader(fs);
     71         else
     72             ir = new InputStreamReader(fs, encoding);
     73         return new BufferedReader(ir);
     74     }
     75 
     76     /**
     77      * Called to assemble a single file.
     78      *
     79      * @param fname
     80      *            is the name of the file containing the DAsm source code.
     81      */
     82     public static void assemble(String fname) {
     83         DAsm dAsm = new DAsm();
     84 
     85         // read and parse .d file
     86         Reader inp = null;
     87         try {
     88             inp = createReader(fname);
     89             dAsm.readD(inp, new File(fname).getName(), generateLineNumbers);
     90             close(inp);
     91         } catch (DasmError e) {
     92             if (DEBUG) e.printStackTrace();
     93             System.err.println("DASM Error: " + e.getMessage());
     94         } catch (Exception e) {
     95             if (DEBUG) e.printStackTrace();
     96             System.err.println("Exception <" + e.getClass().getName() + ">"
     97                     + e.getMessage() + " while reading and parsing " + fname);
     98             return;
     99 
    100         } finally {
    101             close(inp);
    102         }
    103 
    104         if (dAsm.errorCount() > 0) {
    105             System.err.println("Found " + dAsm.errorCount() + " errors "
    106                     + " while reading and parsing " + fname);
    107             return;
    108         }
    109 
    110         String class_path[] = Utils
    111                 .getClassFieldFromString(dAsm.getClassName());
    112         String class_name = class_path[1];
    113 
    114         // determine where to place .dex file
    115         String dest_dir = destPath;
    116         if (class_path[0] != null) {
    117             String class_dir = class_path[0].replaceAll("/|\\.", Character
    118                     .toString(File.separatorChar));
    119             if (dest_dir != null) {
    120                 dest_dir = dest_dir + File.separator + class_dir;
    121             } else {
    122                 dest_dir = class_dir;
    123             }
    124         }
    125 
    126         File out_file = null;
    127         File hr_file = null;
    128 
    129         if (dest_dir == null) {
    130             out_file = new File(class_name + ".dex");
    131             hr_file = new File(class_name + ".dxt");
    132         } else {
    133             out_file = new File(dest_dir, class_name + ".dex");
    134             hr_file = new File(dest_dir, class_name + ".dxt");
    135 
    136             // check that dest_dir exists
    137             File dest = new File(dest_dir);
    138             if (!dest.exists()) {
    139                 dest.mkdirs();
    140             }
    141 
    142             if (!dest.isDirectory()) {
    143                 System.err.println("Cannot create directory " + dest_dir);
    144                 return;
    145             }
    146         }
    147 
    148         // write output
    149         FileOutputStream outp = null;
    150         FileWriter hr_outp = null;
    151 
    152         try {
    153             outp = new FileOutputStream(out_file);
    154             if (humanHeadable) hr_outp = new FileWriter(hr_file);
    155             dAsm.write(outp, hr_outp);
    156         } catch (Exception e) {
    157             if (DEBUG) e.printStackTrace();
    158             System.err.println("Exception <" + e.getClass().getName() + ">"
    159                     + e.getMessage() + " while writing " + out_file.getPath());
    160 
    161             close(hr_outp);
    162             close(outp);
    163 
    164             hr_file.delete();
    165             out_file.delete();
    166 
    167             return;
    168         } finally {
    169             close(hr_outp);
    170             close(outp);
    171         }
    172 
    173         System.out.println("Generated: " + out_file.getPath());
    174     }
    175 
    176     private static void close(Closeable c) {
    177         if (c == null) return;
    178         try {
    179             c.close();
    180         } catch (IOException e) {
    181 
    182         }
    183     }
    184 
    185     public static void main(String args[]) {
    186         int i;
    187 
    188         String files[] = new String[args.length];
    189         int num_files = 0;
    190 
    191         if (args.length == 0) {
    192             printUsage();
    193             System.exit(-1);
    194         }
    195 
    196         for (i = 0; i < args.length; i++) {
    197             if (args[i].equals("-help") || args[i].equals("-?")) {
    198                 printUsage();
    199                 System.exit(0);
    200             }
    201             if (args[i].equals("-version")) {
    202                 System.out.println("DAsm version: " + version);
    203                 if (DEBUG) System.out.println("(compiled with DEBUG flag on)");
    204                 System.exit(0);
    205             }
    206             if (args[i].equals("-g")) {
    207                 generateLineNumbers = true;
    208             } else if (args[i].equals("-d")) {
    209                 if (++i >= args.length)
    210                     incompleteOption("-d");
    211                 else
    212                     destPath = args[i];
    213             } else if (args[i].equals("-h")) {
    214                 humanHeadable = true;
    215             } else if (args[i].equals("-e")) {
    216                 if (++i >= args.length)
    217                     incompleteOption("-e");
    218                 else
    219                     encoding = args[i];
    220             } else {
    221                 files[num_files++] = args[i];
    222             }
    223         }
    224 
    225         for (i = 0; i < num_files; i++) {
    226             assemble(files[i]);
    227         }
    228     }
    229 
    230     static void printUsage() {
    231         System.err
    232                 .println("dasm [-d <outpath>] [-g] [-h] [-e <encoding>] <file>"
    233                         + "[<file> ...]\n\n"
    234                         + "  -g - autogenerate linenumbers\n"
    235                         + "  -e - codepage for inputfile encoding\n"
    236                         + "  -d - path for generated classfiles\n"
    237                         + "  -h - generate human-readable output\n"
    238                         + "  file  - sourcefile\n"
    239                         + "or: dasm -version\n"
    240                         + "or: dasm -help");
    241     }
    242 };
    243