1 30 31 32 33 package jbet; 34 import java.io.*; 35 import java.util.*; 36 37 public class Main 38 { 39 static Hashtable commands; 40 static Vector lexers = new Vector(); 41 static boolean writeDirty = true; 42 public static boolean verboseErrors = false; 43 static Vector javaclasspath = new Vector(); 44 static Vector cmdpath = new Vector(); 45 public static ClassPathElement JbetCPE = null; 46 47 static char[] _spaces; 48 static String jbethelp = "Use 'jbet help <topic>' for help.\n'jbet help' gives a list of commands and other help topics."; 49 static HashSet helpcmds; 50 51 static { 52 53 54 Jbet.loader = new ClassInfoLoader(); 55 String prop = System.getProperty("java.class.path"); 56 Jbet.loader.parseClassPath(prop); 57 58 for (int i = 0; i < Jbet.loader.classPath.size(); i++) { 59 try { 60 ClassPathElement cpe = Jbet.loader.getCPElement (i); 61 javaclasspath.addElement (cpe); 62 63 if (cpe.get ("jbet/Main.class") != null) { 64 JbetCPE = cpe; 65 cmdpath.addElement ("jbet.cmd"); 66 } 67 } catch (IOException e) { } 68 } 69 70 if (cmdpath.size() == 0) { 71 System.err.println ("java.class.path property does not contain an entry with jbet/Main."); 72 System.exit (1); 73 } 74 75 76 _spaces = new char[31]; 77 for (int i = 0; i <= 30; i++) _spaces[i] = ' '; 78 79 80 commands = new Hashtable(); 81 commands.put ("diagecho", new Command() { 82 public int helplevel() { return 5; } 83 public String shorthelp() { return "echoes a string if verbosity is >= info"; } 84 public String longhelp() { 85 return "jbet diagecho <string> echoes <string> if verbosity is >= info\n"; 86 } 87 public void run(Lexer lexer) throws Exception { 88 lexer.match(Token.END_OF_OPTS); 89 String s = lexer.parse_string(); 90 lexer.term(); 91 Jbet.info.println(s); 92 } 93 }); 94 commands.put ("echo", new Command() { 95 public int helplevel() { return 5; } 96 public String shorthelp() { return "echoes a string"; } 97 public String longhelp() { 98 return "jbet echo <string> echoes a string\n"; 99 } 100 public void run(Lexer lexer) throws Exception { 101 lexer.match(Token.END_OF_OPTS); 102 String s = lexer.parse_string(); 103 lexer.term(); 104 Jbet.output.println(s); 105 } 106 }); 107 commands.put ("getclasses", new Command() { 108 public int helplevel() { return 5; } 109 public String shorthelp() { return "getclasseses"; } 110 public String longhelp() { 111 return "jbet getclasses\n"; 112 } 113 public void run(Lexer lexer) throws Exception { 114 lexer.match(Token.END_OF_OPTS); 115 ClassInfo [] classes = lexer.getClasses(); 116 lexer.term(); 117 for (int i = 0; i < classes.length; i++) 118 Jbet.output.println(classes[i].name()); 119 } 120 }); 121 122 commands.put ("makezip", new Command() { 123 public int helplevel() { return 5; } 124 public String shorthelp() { return "makezip"; } 125 public String longhelp() { 126 return "jbet makezip\n"; 127 } 128 public void run(Lexer lexer) throws Exception { 129 lexer.match(Token.END_OF_OPTS); 130 Vector v = new Vector(); 131 lexer.getClasses(v); 132 lexer.term(); 133 Util.writeZip("zipfile.zip", v.iterator()); 134 } 135 }); 136 137 138 139 commands.put ("classpath", new Command() { 140 public int helplevel() { return 5; } 141 public String shorthelp() { return "sets the classpath"; } 142 public String longhelp() { 143 return "jbet classpath <string> sets the classpath\n"; 144 } 145 public void run(Lexer lexer) throws Exception { 146 lexer.match(Token.END_OF_OPTS); 147 String s = lexer.parse_string(); 148 lexer.term(); 149 Jbet.loader.clearPath(); 150 Jbet.loader.parseClassPath(s); 151 } 152 }); 153 commands.put ("classpathadd", new Command() { 154 public int helplevel() { return 5; } 155 public String shorthelp() { return ""; } 156 public String longhelp() { 157 return "jbet classpathadd <string> adds to the classpath\n"; 158 } 159 public void run(Lexer lexer) throws Exception { 160 lexer.match(Token.END_OF_OPTS); 161 String s = lexer.parse_string(); 162 lexer.term(); 163 Jbet.loader.parseClassPath(s); 164 } 165 }); 166 commands.put ("printpath", new Command() { 167 public int helplevel() { return 5; } 168 public String shorthelp() { return ""; } 169 public String longhelp() { 170 return "jbet printpath prints the current classpath\n"; 171 } 172 public void run(Lexer lexer) throws Exception { 173 lexer.match(Token.END_OF_OPTS); 174 lexer.term(); 175 Jbet.loader.print(Jbet.output); 176 } 177 }); 178 commands.put ("resolve_constants", new Command() { 179 public int helplevel() { return 5; }; 180 public String shorthelp() { return "call resolve constants"; } 181 public String longhelp() { return "jbet resolve_constants thing\n";} 182 public void run(Lexer lexer) throws Exception { 183 lexer.match(Token.END_OF_OPTS); 184 Object thing = lexer.getThing(Jbet.default_class); 185 lexer.term(); 186 if (thing instanceof ClassInfo) { 187 ((ClassInfo)thing).resolveConstants(); 188 Jbet.info.println("resolve_constants " + 189 ((ClassInfo)thing).thisClass); 190 } else if (thing instanceof MethodInfo) { 191 ((MethodInfo)thing).resolveConstants(); 192 Jbet.info.println("resolve_constants " + 193 ((MethodInfo)thing).qualifiedName()); 194 } else if (thing instanceof FieldInfo) { 195 ((FieldInfo)thing).resolveConstants(); 196 Jbet.info.println("resolve_constants " + 197 ((FieldInfo)thing).qualifiedName()); 198 } 199 } 200 }); 201 commands.put ("listmethods", new Command() { 202 public int helplevel() { return 5; }; 203 public String shorthelp() { return "list methods of a class"; } 204 public String longhelp() { return "jbet listmethods <class>\n";} 205 public void run(Lexer lexer) throws Exception { 206 lexer.match(Token.END_OF_OPTS); 207 ClassInfo cr = lexer.getClass(Jbet.default_class); 208 lexer.term(); 209 for (int i = 0; i < cr.methods.size(); i++) { 210 MethodInfo mi = cr.methodAt(i); 211 Jbet.output.println(cr.name() + "." + mi.name + ":" + 212 mi.descriptor); 213 } 214 } 215 }); 216 217 commands.put ("inners", new Command() { 218 public int helplevel() { return 5; }; 219 public String shorthelp() { return "inners"; } 220 public String longhelp() { return "inners\n";} 221 public void run(Lexer lexer) throws Exception { 222 lexer.match(Token.END_OF_OPTS); 223 ClassInfo cr = lexer.getClass(Jbet.default_class); 224 lexer.term(); 225 HashSet s = Util.findInnerClasses(cr.name()); 226 for (Iterator i = s.iterator(); i.hasNext();) { 227 Jbet.output.println(i.next()); 228 } 229 } 230 }); 231 232 commands.put ("setvar", new Command() { 233 public int helplevel() { return 5; }; 234 public String shorthelp() { return "set a variable"; } 235 public String longhelp() { return "set <varname> <varvalue>\n";} 236 public void run(Lexer lexer) throws Exception { 237 lexer.match(Token.END_OF_OPTS); 238 lexer.push(Lexer.ST_STRING); 239 String name = lexer.parse_string(); 240 String val = lexer.parse_string(); 241 Jbet.lexerVars.put(name, val); 242 lexer.pop(); 243 } 244 }); 245 246 helpcmds = new HashSet(); 247 helpcmds.add ("print"); 248 helpcmds.add ("printclass"); 249 helpcmds.add ("disassemble"); 250 helpcmds.add ("assemble"); 251 helpcmds.add ("listbbs"); 252 helpcmds.add ("listdags"); 253 helpcmds.add ("listmethods"); 254 helpcmds.add ("set"); 255 helpcmds.add ("verify"); 256 helpcmds.add ("verifyall"); 257 helpcmds.add ("findclasses"); 258 } 259 260 static Command getCommand (String name) throws Exception 261 { 262 Exception lastex = null; 263 Object o = commands.get(name); 264 if (o != null) 265 return (Command) o; 266 267 for (int i = 0; i < cmdpath.size(); i++) 268 try { 269 String cp = cmdpath.elementAt(i).toString(); 270 271 Class cls = Class.forName (cp + "." + name); 272 Command cmd = (Command) cls.newInstance(); 273 cmd.hashCode(); 274 commands.put (name, cmd); 275 return cmd; 276 } catch (Exception e) { lastex = e; } 277 278 if (lastex != null) 279 throw lastex; 280 else 281 throw new IllegalStateException ("something bad happened"); 282 } 283 284 static Command getCommand2 (String name) 286 { 287 try { 288 return getCommand (name); 289 } catch (Exception e) { 290 return null; 291 } 292 } 293 294 297 public static void usage (int helplevel) 298 { 299 Jbet.output.println ("Usage: jbet <options> <command> <arguments>\nCommands:"); 300 301 for (Iterator i = helpcmds.iterator(); i.hasNext(); ) { 302 String cname = i.next().toString(); 303 Command co = getCommand2 (cname); 304 305 if (co != null) { 306 String spaces = new String (_spaces, 0, 17 - cname.length()); 307 Jbet.output.println (cname + spaces + co.shorthelp()); 308 } 309 } 310 311 Jbet.output.println ("help <command> extended help on <command>"); 312 Jbet.output.println ("help options show help on commandline options"); 313 Jbet.output.println ("help syntax show help on argument syntax"); 314 } 315 316 318 public static void usage () 319 { 320 usage (3); 321 } 322 323 public static void usage (String text) 324 { 325 if (text.equals ("all")) { 326 usage (99); 327 return; 328 } 329 else if (text.equals ("options")) { 330 optionhelp (); 331 return; 332 } 333 334 else if (text.equals ("syntax")) { 335 Jbet.output.println 336 ("Class names:\n" + 337 " Use slashes in the names, such as java/lang/Object.\n" + 338 " The package name is always required.\n" + 339 "Method specification:\n" + 340 " Use <class>.<method> or <class>.<method>:<descriptor>.\n" + 341 " The descriptor is required only if there is more than one method\n" + 342 " with the same name.\n" + 343 "Method descriptors:\n" + 344 " Use the JNI descriptor syntax, which is (<arguments>)<return type>.\n" + 345 " Each type is one of the following:\n" + 346 " int I\n" + 347 " long J\n" + 348 " float F\n" + 349 " double D\n" + 350 " short S\n" + 351 " byte B\n" + 352 " char C\n" + 353 " boolean Z\n" + 354 " reference L<class-name>;\n" + 355 " So a method declared as int foo (String, long, Object) would be\n" + 356 " (Ljava/lang/String;JLjava/lang/Object;)I\n" 357 ); 358 return; 359 } 360 361 Command cmd = getCommand2 (text); 362 363 if (cmd == null) 364 Jbet.output.println ("invalid command " + text); 365 else { 366 Jbet.output.print (cmd.longhelp()); 367 } 368 } 369 370 375 static void doCommands (Lexer lexer) throws Exception 376 { 377 lexer.varFunction = Jbet.lexerVarFunction; 378 379 while (true) { 380 lexer.state = Lexer.ST_TAG; 381 382 Token tok; 383 do { tok = lexer.read(); } while ( tok.type == ';' ); 384 385 if (tok.type == Token.EOF) break; 386 if (tok.type != Token.TAG) lexer.unexpected(tok); 387 388 Command cmd = getCommand (tok.text); 389 390 if (cmd == null) 391 throw new ParseException ("invalid command " + tok.text + "; type 'jbet help' for a list"); 392 393 Jbet.debug.println ("executing command " + tok.text); 394 cmd.run (lexer); 395 } 396 } 397 398 static void doCommands (String s) throws Exception 399 { 400 doCommands (new Lexer (new StringReader (s), "cmdline")); 401 } 402 403 409 static void write (ClassInfo cr) throws Exception { 410 cr.write(); 411 } 412 413 419 public static void main (String [] args) { 420 int exitStatus = 0; 421 422 if (args.length == 0) 423 { 424 Jbet.output.println (jbethelp); 425 return; 426 } 427 428 try { 429 430 parseArgs (args); 432 if (lexers.size() == 0) { 433 Jbet.output.println (jbethelp); 434 return; 435 } 436 437 for (int i = 0; i < lexers.size(); i++) 438 doCommands((Lexer) lexers.elementAt(i)); 439 440 if (writeDirty) { 441 442 Enumeration classes = Jbet.loader.getClasses(); 443 ClassInfo cr; 444 while (classes.hasMoreElements()) { 445 cr = (ClassInfo) classes.nextElement(); 446 if (cr.dirty) 447 write(cr); 448 } 449 } 450 451 } catch (Throwable e) { 452 exitStatus = 1; 453 if (verboseErrors) { 454 Jbet.fatal.print("\n\n"); 455 e.printStackTrace(Jbet.fatal); 456 } else 457 if (e instanceof GlobalException || e instanceof ParseException || e instanceof ClassFileException) 458 Jbet.fatal.println( e.getMessage() ); 459 else 460 Jbet.fatal.println(e.getClass().getName() + ": " + e.getMessage() ); 461 } 462 System.exit(exitStatus); 463 } 464 465 static MyGetopt g; 466 467 471 static void parseArgs (String [] args) throws Exception { 472 MyLongOpt [] longs = new MyLongOpt[9]; 473 longs[0] = new MyLongOpt("classpath", MyGetopt.REQUIRED_ARG, 'p'); 474 longs[1] = new MyLongOpt("cmdpath", MyGetopt.REQUIRED_ARG, 'C'); 475 longs[2] = new MyLongOpt("nowrite", MyGetopt.NO_ARG, 'W'); 476 longs[3] = new MyLongOpt("pluspath", MyGetopt.REQUIRED_ARG, 'P'); 477 longs[4] = new MyLongOpt("outputdir", MyGetopt.REQUIRED_ARG, 'o'); 478 longs[5] = new MyLongOpt("verbosity", MyGetopt.REQUIRED_ARG, 'l'); 479 longs[6] = new MyLongOpt("comment", MyGetopt.NO_ARG, 'q'); 480 longs[7] = new MyLongOpt("default", MyGetopt.REQUIRED_ARG, 'd'); 481 longs[8] = new MyLongOpt("facility", MyGetopt.REQUIRED_ARG, 'F'); 482 483 if (g == null) 484 g = new MyGetopt (":c:vVeEjJvqWro:C:d:f:p:P:l:F:", args, longs); 485 int opt; 486 while ( (opt = g.getopt()) != -1 ) { 487 switch (opt) { 488 case 1: 489 490 StringBuffer output = new StringBuffer (); 491 for (int i = g.optind - 1; i < args.length; i++) { 492 output.append (args[i]); 493 output.append (" "); 494 } 495 lexers.addElement (new Lexer (new StringReader (output.toString()), "cmdline")); 496 return; 497 498 499 case 'C': 500 cmdpath.addElement(ClassInfoLoader.directory (g.optarg)); 501 break; 502 503 504 case 'v': 505 Jbet.logger.setLevel(Logger.INFO); 506 break; 507 case 'l': 508 int level = Logger.str2level(g.optarg); 509 if (level == -1) 510 throw new ParseException("bad verbosity level: " + g.optarg); 511 Jbet.logger.setLevel(level); 512 break; 513 case 'R': 514 Jbet.logger.setOut(System.err); 515 break; 516 case 'F': 517 Jbet.logger.addFacility (g.optarg); 518 break; 519 case 'V': 520 Jbet.logger.setLevel(Logger.WARN); 521 break; 522 case 'e': 523 verboseErrors = true; 524 break; 525 case 'E': 526 verboseErrors = false; 527 break; 528 529 530 case 'W': 531 writeDirty = false; 532 break; 533 case 'o': 534 Jbet.outputdir = g.optarg; 535 if (!Jbet.outputdir.endsWith("/")) 536 Jbet.outputdir = Jbet.outputdir + "/"; 537 break; 538 case 'q': 539 Jbet.compact = false; 540 break; 541 542 case 'd': 543 Jbet.setDefault(g.optarg); 544 break; 545 546 547 case 'c': 548 doCommands(new Lexer(new StringReader(g.optarg), "-c")); 549 break; 550 551 case 'f': 552 if (g.optarg.equals("-")) 553 lexers.addElement( new Lexer(System.in, "stdin")); 554 else { 555 FileInputStream fp = new FileInputStream(g.optarg); 556 lexers.addElement (new Lexer (fp, g.optarg)); 557 } 558 break; 559 560 561 case 'p': 562 Jbet.loader.clearPath(); 563 case 'P': 565 Jbet.loader.parseClassPath(g.optarg); 566 break; 567 case 'j': 568 Jbet.loader.clearPath(); 569 case 'J': 570 { 571 Vector cp = getSystemClassPath(); 572 for (Iterator i = cp.iterator(); i.hasNext(); ) 573 Jbet.loader.parseClassPath (i.next().toString(), false); 574 } 575 break; 576 577 case '?': 578 case ':': 579 throw new ParseException (g.error); 580 } 581 } 582 583 return; 584 } 585 586 588 static void optionhelp () 589 { 590 Jbet.output.println ( 591 " -p \t specify a classpath \n" + 592 " -P \t specify elemetns to add to the current classpath \n" + 593 " -j \t set classpath to Java system classpath\n" + 594 " -J \t append Java system classpath to classpath\n" + 595 " -v \t print a message for each action taken (same as -l info)\n"+ 596 " -e \t verbose errors \n"+ 597 " -W \t inhibit automatic writing of modified classes \n"+ 598 " -f \t specify a file to read commands from \n"+ 599 " -d \t specify a default class \n" + 600 " -R \t use stderr for log and error messages \n" + 601 " -l \t set log level (all, debug, info, warn, error, fatal) \n"+ 602 " -f \t show all messages from specified facility\n"+ 603 " -o \t specify an output directory" 604 ); 605 } 606 607 static Vector getSystemClassPath () { 608 try { 609 java.lang.reflect.Method jcl = ClassLoader .class.getDeclaredMethod ("getBootstrapClassPath", new Class [0]); 610 jcl.setAccessible (true); 611 sun.misc.URLClassPath cp = (sun.misc.URLClassPath) jcl.invoke (null, new Object [0]); 612 613 java.net.URL [] cps = cp.getURLs(); 614 615 Vector out = new Vector(); 616 for (int i = 0; i < cps.length; i++) 617 if (cps[i].getProtocol().equals ("file")) 618 out.addElement (java.net.URLDecoder.decode (cps[i].getPath())); 619 return out; 620 } catch (Exception e) { 621 throw new IllegalStateException (e.toString()); 622 } 623 } 624 } 625 | Popular Tags |