summaryrefslogtreecommitdiff
path: root/src/scalap/scala/tools/scalap/Main.scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2009-02-09 16:06:06 +0000
committerLukas Rytz <lukas.rytz@epfl.ch>2009-02-09 16:06:06 +0000
commit76009173e08545c346d4a66eb847a75120649ad2 (patch)
treead271feec9a4411bd9e4d67a7d93ee35b32d0bca /src/scalap/scala/tools/scalap/Main.scala
parent9191eb8dd882e04bee79907bda69d5018ee5ed99 (diff)
downloadscala-76009173e08545c346d4a66eb847a75120649ad2.tar.gz
scala-76009173e08545c346d4a66eb847a75120649ad2.tar.bz2
scala-76009173e08545c346d4a66eb847a75120649ad2.zip
added build scripts for scalap
Diffstat (limited to 'src/scalap/scala/tools/scalap/Main.scala')
-rw-r--r--src/scalap/scala/tools/scalap/Main.scala266
1 files changed, 266 insertions, 0 deletions
diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala
new file mode 100644
index 0000000000..6e91e00234
--- /dev/null
+++ b/src/scalap/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))
+ }
+ }
+}