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 incompleteOption(String opt)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 createReader(String fname)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 */ assemble(String fname)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 close(Closeable c)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 main(String args[])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 printUsage()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