diff options
author | ilyas <ilyas@epfl.ch> | 2009-01-15 14:13:37 +0000 |
---|---|---|
committer | ilyas <ilyas@epfl.ch> | 2009-01-15 14:13:37 +0000 |
commit | e877601ffbf61d79c8241bcce948cdde99efb0f1 (patch) | |
tree | 55a7cc2ef8ddb5229b1bdf89336837671eeca186 /src/compiler/scala/tools/scalap/Main.scala | |
parent | 5e9bf6564f03456355d63a58944d2f5d2202732d (diff) | |
download | scala-e877601ffbf61d79c8241bcce948cdde99efb0f1.tar.gz scala-e877601ffbf61d79c8241bcce948cdde99efb0f1.tar.bz2 scala-e877601ffbf61d79c8241bcce948cdde99efb0f1.zip |
scalap classes added
Diffstat (limited to 'src/compiler/scala/tools/scalap/Main.scala')
-rw-r--r-- | src/compiler/scala/tools/scalap/Main.scala | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/scalap/Main.scala b/src/compiler/scala/tools/scalap/Main.scala new file mode 100644 index 0000000000..6e91e00234 --- /dev/null +++ b/src/compiler/scala/tools/scalap/Main.scala @@ -0,0 +1,266 @@ +/* ___ ____ ___ __ ___ ___ +** / _// __// _ | / / / _ | / _ \ Scala classfile decoder +** __\ \/ /__/ __ |/ /__/ __ |/ ___/ (c) 2003-2009, LAMP/EPFL +** /____/\___/_/ |_/____/_/ |_/_/ http://scala-lang.org/ +** +*/ + +// $Id: Main.scala 9834 2007-01-31 16:31:25Z michelou $ + +package scala.tools.scalap + + +import java.io.{File, PrintStream, OutputStreamWriter, ByteArrayOutputStream} +import scala.tools.nsc.util.ClassPath +import scalax.rules.scalasig._ + +/**The main object used to execute scalap on the command-line. + * + * @author Matthias Zenger, Stephane Micheloud, Burak Emir, Ilya Sergey + */ +object Main { + val SCALA_SIG = "ScalaSig" + val versionMsg = "Scala classfile decoder " + + Properties.versionString + " -- " + + Properties.copyrightString + + /**Verbose program run? + */ + var verbose = false + + /**Prints usage information for scalap. + */ + def usage: Unit = { + Console.println("usage: scalap {<option>} <name>") + Console.println("where <option> is") + Console.println(" -private print private definitions") + Console.println(" -verbose print out additional information") + Console.println(" -version print out the version number of scalap") + Console.println(" -help display this usage message") + Console.println(" -classpath <path> specify where to find user class files") + Console.println(" -cp <path> specify where to find user class files") + } + + def isScalaFile(bytes: Array[Byte]): Boolean = { + val byteCode = ByteCode(bytes) + val classFile = ClassFileParser.parse(byteCode) + classFile.attribute("ScalaSig") match {case Some(_) => true; case None => false} + } + + /**Processes the given Java class file. + * + * @param clazz the class file to be processed. + */ + def processJavaClassFile(clazz: Classfile): Unit = { + // construct a new output stream writer + val out = new OutputStreamWriter(Console.out) + val writer = new JavaWriter(clazz, out) + // print the class + writer.printClass + out.flush() + } + + def parseScalaSignature(scalaSig: ScalaSig) = { + val baos = new ByteArrayOutputStream + val stream = new PrintStream(baos) + val syms = scalaSig.topLevelClasses ::: scalaSig.topLevelObjects + syms.first.parent match { + //Partial match + case Some(p) if (p.name != "<empty>") => { + stream.print("package "); + stream.print(p.path); + stream.print("\n") + } + case _ => + } + // Print classes + val printer = new ScalaSigPrinter(stream) + for (c <- syms) { + printer.printSymbol(c) + } + baos.toString + } + + + def decompileScala(bytes: Array[Byte]) = { + val byteCode = ByteCode(bytes) + val classFile = ClassFileParser.parse(byteCode) + classFile.attribute(SCALA_SIG).map(_.byteCode).map(ScalaSigAttributeParsers.parse) match { + case Some(scalaSig) => Console.println(parseScalaSignature(scalaSig)) + case None => //Do nothing + } + } + + + /**Executes scalap with the given arguments and classpath for the + * class denoted by <code>classname</code>. + * + * @param args... + * @param path... + * @param classname... + */ + def process(args: Arguments, path: ClassPath#Build)(classname: String): Unit = { + // find the classfile + val filename = Names.encode( + if (classname == "scala.AnyRef") "java.lang.Object" + else classname).replace('.', File.separatorChar) + val cfile = path.lookupPath(filename, /*isDir*/ false) + if (cfile != null) { + if (verbose) { + Console.println(Console.BOLD + "FILENAME" + Console.RESET + " = " + cfile.path) + } + val bytes = cfile.toByteArray + if (isScalaFile(bytes)) { + decompileScala(bytes) + } else { + // construct a reader for the classfile content + val reader = new ByteArrayReader(cfile.toByteArray) + // parse the classfile + val clazz = new Classfile(reader) + processJavaClassFile(clazz) + } + // if the class corresponds to the artificial class scala.All. + // (to be removed after update of the STARR libraries) + } else if (classname == "scala.All") { + Console.println("package scala") + Console.println("/* Deprecated. Use scala.Nothing instead. */") + Console.println("sealed abstract class All") + // if the class corresponds to the artificial class scala.AllRef. + // (to be removed after update of the STARR libraries) + } else if (classname == "scala.AllRef") { + Console.println("package scala") + Console.println("/* Deprecated. Use scala.Null instead. */") + Console.println("sealed abstract class AllRef") + // if the class corresponds to the artificial class scala.Any. + // (see member list in class scala.tool.nsc.symtab.Definitions) + } else if (classname == "scala.Any") { + Console.println("package scala") + Console.println("class Any {") + Console.println(" final def ==(scala.Any): scala.Boolean") + Console.println(" final def !=(scala.Any): Boolean") + Console.println(" def equals(scala.Any): scala.Boolean") + Console.println(" def hashCode(): scala.Int") + Console.println(" def toString(): java.lang.String") + Console.println(" final def isInstanceOf[a]: scala.Boolean") + Console.println(" final def asInstanceOf[a]: a") + Console.println("}") + // if the class corresponds to the artificial class scala.AnyRef. + } else if (classname == "scala.AnyRef") { + Console.println("package scala") + Console.println("class AnyRef extends Any {") + Console.println(" def equals(scala.Any): scala.Boolean") + Console.println(" def hashCode(): scala.Int") + Console.println(" def toString(): java.lang.String") + Console.println("}") + // if the class corresponds to the artificial class scala.AnyVal. + } else if (classname == "scala.AnyVal") { + Console.println("package scala") + Console.println("sealed class AnyVal extends Any") + // if the class corresponds to the artificial class scala.Boolean. + } else if (classname == "scala.Boolean") { + Console.println("package scala") + Console.println("sealed abstract class Boolean extends AnyVal {") + Console.println(" def &&(p: => scala.Boolean): scala.Boolean // boolean and") + Console.println(" def ||(p: => scala.Boolean): scala.Boolean // boolean or") + Console.println(" def & (x: scala.Boolean): scala.Boolean // boolean strict and") + Console.println(" def | (x: scala.Boolean): scala.Boolean // boolean stric or") + Console.println(" def ==(x: scala.Boolean): scala.Boolean // boolean equality") + Console.println(" def !=(x: scala.Boolean): scala.Boolean // boolean inequality") + Console.println(" def !: scala.Boolean // boolean negation") + Console.println("}") + // if the class corresponds to the artificial class scala.Int. + } else if (classname == "scala.Int") { + Console.println("package scala") + Console.println("sealed abstract class Int extends AnyVal {") + Console.println(" def ==(that: scala.Double): scala.Boolean") + Console.println(" def ==(that: scala.Float): scala.Boolean") + Console.println(" def ==(that: scala.Long): scala.Boolean") + Console.println(" def ==(that: scala.Int): scala.Boolean") + Console.println(" def ==(that: scala.Short): scala.Boolean") + Console.println(" def ==(that: scala.Byte): scala.Boolean") + Console.println(" def ==(that: scala.Char): scala.Boolean") + Console.println(" /* analogous for !=, <, >, <=, >= */") + Console.println + Console.println(" def + (that: scala.Double): scala.Double // double addition") + Console.println(" def + (that: scala.Float): scala.Float // float addition") + Console.println(" def + (that: scala.Long): scala.Long // long addition") + Console.println(" def + (that: scala.Int): scala.Int // int addition") + Console.println(" def + (that: scala.Short): scala.Int // int addition") + Console.println(" def + (that: scala.Byte): scala.Int // int addition") + Console.println(" def + (that: scala.Char): scala.Int // int addition") + Console.println(" /* analogous for -, *, /, % */") + Console.println + Console.println(" def & (that: scala.Long): scala.Long // long bitwise and") + Console.println(" def & (that: scala.Int): scala.Int // int bitwise and") + Console.println(" def & (that: scala.Short): scala.Int // int bitwise and") + Console.println(" def & (that: scala.Byte): scala.Int // int bitwise and") + Console.println(" def & (that: scala.Char): scala.Int // int bitwise and") + Console.println(" /* analogous for |, ^ */") + Console.println + Console.println(" def <<(cnt: scala.Int): scala.Int // int left shift") + Console.println(" def <<(cnt: scala.Long): scala.Int // long left shift") + Console.println(" /* analogous for >>, >>> */") + Console.println + Console.println(" def + : scala.Int // int identity") + Console.println(" def - : scala.Int // int negation") + Console.println(" def ~ : scala.Int // int bitwise negation") + Console.println + Console.println(" def toByte: scala.Byte // convert to Byte") + Console.println(" def toShort: scala.Short // convert to Short") + Console.println(" def toChar: scala.Char // convert to Char") + Console.println(" def toInt: scala.Int // convert to Int") + Console.println(" def toLong: scala.Long // convert to Long") + Console.println(" def toFloat: scala.Float // convert to Float") + Console.println(" def toDouble: scala.Double // convert to Double") + Console.println("}") + // if the class corresponds to the artificial class scala.Nothing. + } else if (classname == "scala.Nothing") { + Console.println("package scala") + Console.println("sealed abstract class Nothing") + // if the class corresponds to the artificial class scala.Null. + } else if (classname == "scala.Null") { + Console.println("package scala") + Console.println("sealed abstract class Null") + } else + Console.println("class/object " + classname + " not found.") + } + + /**The main method of this object. + */ + def main(args: Array[String]) { + // print usage information if there is no command-line argument + if (args.length == 0) + usage + // otherwise parse the arguments... + else { + val arguments = Arguments.Parser('-') + .withOption("-private") + .withOption("-verbose") + .withOption("-version") + .withOption("-help") + .withOptionalArg("-classpath") + .withOptionalArg("-cp") + .parse(args); + if (arguments contains "-version") + Console.println(versionMsg) + if (arguments contains "-help") + usage + verbose = arguments contains "-verbose" + // construct a custom class path + val classPath0 = new ClassPath(false) + val path = arguments.getArgument("-classpath") match { + case None => arguments.getArgument("-cp") match { + case None => new classPath0.Build() + case Some(path) => new classPath0.Build(path) + } + case Some(path) => new classPath0.Build(path) + } + // print the classpath if output is verbose + if (verbose) { + Console.println(Console.BOLD + "CLASSPATH" + Console.RESET + " = " + path) + } + // process all given classes + arguments.getOthers.foreach(process(arguments, path)) + } + } +} |