summaryrefslogtreecommitdiff
path: root/sources/scala/tools/scalap/Classfile.scala
blob: 26a53a8f53d210cb38829a3a6001216975c4f3e4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*     ___ ____ ___   __   ___   ___
**    / _// __// _ | / /  / _ | / _ \    Scala classfile decoder
**  __\ \/ /__/ __ |/ /__/ __ |/ ___/    (c) 2003, LAMP/EPFL
** /____/\___/_/ |_/____/_/ |_/_/
**
**  $Id$
*/

package scalap;


class Classfile(in: ByteArrayReader) {
    import Classfiles._;

    assert(in.nextInt == JAVA_MAGIC);
    val minorVersion = in.nextChar;
    val majorVersion = in.nextChar;
    val pool = readPool;
    val flags = in.nextChar;
    val classname = in.nextChar;
    val superclass = in.nextChar;
    val interfaces = readInterfaces;
    val fields = readMembers(true);
    val methods = readMembers(false);
    val attribs = readAttribs;

    def readAttribs = {
        val n = in.nextChar;
        var attribs: List[Attribute] = Nil;
        var i = 0;
        while (i < n) {
            attribs = Attribute(in.nextChar, in.nextBytes(in.nextInt)) :: attribs;
            i = i + 1;
        }
        attribs
    }

    def readMembers(field: Boolean) = {
        val n = in.nextChar;
        var members: List[Member] = Nil;
        var i = 0;
        while (i < n) {
            members = Member(field, in.nextChar, in.nextChar, in.nextChar, readAttribs) :: members;
            i = i + 1;
        }
        members
    }

    def readInterfaces = {
        val n = in.nextChar;
        var intfs: List[Int] = Nil;
        var i = 0;
        while (i < n) {
            intfs = in.nextChar :: intfs;
            i = i + 1;
        }
        intfs
    }

    def readPool = {
        val pool = new Array[PoolEntry](in.nextChar);
        var i = 1;
        while (i < pool.length) {
            val tag: Int = in.nextByte;
            tag match {
                case 1 => // CONSTANT_UTF8
                    pool(i) = UTF8(in.nextUTF8(in.nextChar));
                case 2 => // CONSTANT_UNICODE
                    in.skip(in.nextChar);
                    pool(i) = Empty();
                case 7 => // CONSTANT_CLASS
                    pool(i) = ClassRef(in.nextChar);
                case 8 => // CONSTANT_STRING
                    pool(i) = StringConst(in.nextChar);
                case 9 => // CONSTANT_FIELDREF
                    pool(i) = FieldRef(in.nextChar, in.nextChar);
                case 10 => // CONSTANT_METHODREF
                    pool(i) = MethodRef(in.nextChar, in.nextChar);
                case 11 => // CONSTANT_INTFMETHODREF
                    pool(i) = IntfMethodRef(in.nextChar, in.nextChar);
                case 12 => // CONSTANT_NAMEANDTYPE
                    pool(i) = NameAndType(in.nextChar, in.nextChar);
                case 3 => // CONSTANT_INTEGER
                    pool(i) = IntegerConst(in.nextInt);
                case 4 => // CONSTANT_FLOAT
                    pool(i) = FloatConst(in.nextFloat);
                case 5 => // CONSTANT_LONG
                    pool(i) = LongConst(in.nextLong);
                    i = i + 1;
                    pool(i) = Empty();
                case 6 => // CONSTANT_DOUBLE
                    pool(i) = DoubleConst(in.nextDouble);
                    i = i + 1;
                    pool(i) = Empty();
            }
            i = i + 1;
        }
        pool
    }

    class PoolEntry;
    case class UTF8(str: String) extends PoolEntry;
    case class ClassRef(classId: Int) extends PoolEntry;
    case class FieldRef(classId: Int, memberId: Int) extends PoolEntry;
    case class MethodRef(classId: Int, memberId: Int) extends PoolEntry;
    case class IntfMethodRef(classId: Int, memberId: Int) extends PoolEntry;
    case class StringConst(strId: Int) extends PoolEntry;
    case class IntegerConst(x: Int) extends PoolEntry;
    case class FloatConst(x: Float) extends PoolEntry;
    case class LongConst(x: Long) extends PoolEntry;
    case class DoubleConst(x: Double) extends PoolEntry;
    case class NameAndType(nameId: Int, typeId: Int) extends PoolEntry;
    case class Empty() extends PoolEntry;

    case class Member(field: Boolean, flags: Int, name: Int, tpe: Int, attribs: List[Attribute]);
    case class Attribute(name: Int, data: Array[Byte]) {

        override def toString(): String = pool(name) match {
            case UTF8(str: String) => str
        }

        def reader: ByteArrayReader = new ByteArrayReader(data);
    }

}