OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [tools/] [external/] [asm/] [org/] [objectweb/] [asm/] [ClassReader.java] - Blame information for rev 779

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 779 jeremybenn
/***
2
 * ASM: a very small and fast Java bytecode manipulation framework
3
 * Copyright (c) 2000-2005 INRIA, France Telecom
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 3. Neither the name of the copyright holders nor the names of its
15
 *    contributors may be used to endorse or promote products derived from
16
 *    this software without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28
 * THE POSSIBILITY OF SUCH DAMAGE.
29
 */
30
package org.objectweb.asm;
31
 
32
import java.io.InputStream;
33
import java.io.IOException;
34
 
35
/**
36
 * A Java class parser to make a {@link ClassVisitor} visit an existing class.
37
 * This class parses a byte array conforming to the Java class file format and
38
 * calls the appropriate visit methods of a given class visitor for each field,
39
 * method and bytecode instruction encountered.
40
 *
41
 * @author Eric Bruneton
42
 * @author Eugene Kuleshov
43
 */
44
public class ClassReader {
45
 
46
    /**
47
     * The class to be parsed. <i>The content of this array must not be
48
     * modified. This field is intended for {@link Attribute} sub classes, and
49
     * is normally not needed by class generators or adapters.</i>
50
     */
51
    public final byte[] b;
52
 
53
    /**
54
     * The start index of each constant pool item in {@link #b b}, plus one.
55
     * The one byte offset skips the constant pool item tag that indicates its
56
     * type.
57
     */
58
    private int[] items;
59
 
60
    /**
61
     * The String objects corresponding to the CONSTANT_Utf8 items. This cache
62
     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
63
     * which GREATLY improves performances (by a factor 2 to 3). This caching
64
     * strategy could be extended to all constant pool items, but its benefit
65
     * would not be so great for these items (because they are much less
66
     * expensive to parse than CONSTANT_Utf8 items).
67
     */
68
    private String[] strings;
69
 
70
    /**
71
     * Maximum length of the strings contained in the constant pool of the
72
     * class.
73
     */
74
    private int maxStringLength;
75
 
76
    /**
77
     * Start index of the class header information (access, name...) in
78
     * {@link #b b}.
79
     */
80
    public final int header;
81
 
82
    // ------------------------------------------------------------------------
83
    // Constructors
84
    // ------------------------------------------------------------------------
85
 
86
    /**
87
     * Constructs a new {@link ClassReader} object.
88
     *
89
     * @param b the bytecode of the class to be read.
90
     */
91
    public ClassReader(final byte[] b) {
92
        this(b, 0, b.length);
93
    }
94
 
95
    /**
96
     * Constructs a new {@link ClassReader} object.
97
     *
98
     * @param b the bytecode of the class to be read.
99
     * @param off the start offset of the class data.
100
     * @param len the length of the class data.
101
     */
102
    public ClassReader(final byte[] b, final int off, final int len) {
103
        this.b = b;
104
        // parses the constant pool
105
        items = new int[readUnsignedShort(off + 8)];
106
        int ll = items.length;
107
        strings = new String[ll];
108
        int max = 0;
109
        int index = off + 10;
110
        for (int i = 1; i < ll; ++i) {
111
            items[i] = index + 1;
112
            int tag = b[index];
113
            int size;
114
            switch (tag) {
115
                case ClassWriter.FIELD:
116
                case ClassWriter.METH:
117
                case ClassWriter.IMETH:
118
                case ClassWriter.INT:
119
                case ClassWriter.FLOAT:
120
                case ClassWriter.NAME_TYPE:
121
                    size = 5;
122
                    break;
123
                case ClassWriter.LONG:
124
                case ClassWriter.DOUBLE:
125
                    size = 9;
126
                    ++i;
127
                    break;
128
                case ClassWriter.UTF8:
129
                    size = 3 + readUnsignedShort(index + 1);
130
                    if (size > max) {
131
                        max = size;
132
                    }
133
                    break;
134
                // case ClassWriter.CLASS:
135
                // case ClassWriter.STR:
136
                default:
137
                    size = 3;
138
                    break;
139
            }
140
            index += size;
141
        }
142
        maxStringLength = max;
143
        // the class header information starts just after the constant pool
144
        header = index;
145
    }
146
 
147
    /**
148
     * Copies the constant pool data into the given {@link ClassWriter}. Should
149
     * be called before the {@link #accept(ClassVisitor,boolean)} method.
150
     *
151
     * @param classWriter the {@link ClassWriter} to copy constant pool into.
152
     */
153
    void copyPool(final ClassWriter classWriter) {
154
        char[] buf = new char[maxStringLength];
155
        int ll = items.length;
156
        Item[] items2 = new Item[ll];
157
        for (int i = 1; i < ll; i++) {
158
            int index = items[i];
159
            int tag = b[index - 1];
160
            Item item = new Item(i);
161
            int nameType;
162
            switch (tag) {
163
                case ClassWriter.FIELD:
164
                case ClassWriter.METH:
165
                case ClassWriter.IMETH:
166
                    nameType = items[readUnsignedShort(index + 2)];
167
                    item.set(tag,
168
                            readClass(index, buf),
169
                            readUTF8(nameType, buf),
170
                            readUTF8(nameType + 2, buf));
171
                    break;
172
 
173
                case ClassWriter.INT:
174
                    item.set(readInt(index));
175
                    break;
176
 
177
                case ClassWriter.FLOAT:
178
                    item.set(Float.intBitsToFloat(readInt(index)));
179
                    break;
180
 
181
                case ClassWriter.NAME_TYPE:
182
                    item.set(tag,
183
                            readUTF8(index, buf),
184
                            readUTF8(index + 2, buf),
185
                            null);
186
                    break;
187
 
188
                case ClassWriter.LONG:
189
                    item.set(readLong(index));
190
                    ++i;
191
                    break;
192
 
193
                case ClassWriter.DOUBLE:
194
                    item.set(Double.longBitsToDouble(readLong(index)));
195
                    ++i;
196
                    break;
197
 
198
                case ClassWriter.UTF8: {
199
                    String s = strings[i];
200
                    if (s == null) {
201
                        index = items[i];
202
                        s = strings[i] = readUTF(index + 2,
203
                                readUnsignedShort(index),
204
                                buf);
205
                    }
206
                    item.set(tag, s, null, null);
207
                }
208
                    break;
209
 
210
                // case ClassWriter.STR:
211
                // case ClassWriter.CLASS:
212
                default:
213
                    item.set(tag, readUTF8(index, buf), null, null);
214
                    break;
215
            }
216
 
217
            int index2 = item.hashCode % items2.length;
218
            item.next = items2[index2];
219
            items2[index2] = item;
220
        }
221
 
222
        int off = items[1] - 1;
223
        classWriter.pool.putByteArray(b, off, header - off);
224
        classWriter.items = items2;
225
        classWriter.threshold = (int) (0.75d * ll);
226
        classWriter.index = ll;
227
    }
228
 
229
    /**
230
     * Constructs a new {@link ClassReader} object.
231
     *
232
     * @param is an input stream from which to read the class.
233
     * @throws IOException if a problem occurs during reading.
234
     */
235
    public ClassReader(final InputStream is) throws IOException {
236
        this(readClass(is));
237
    }
238
 
239
    /**
240
     * Constructs a new {@link ClassReader} object.
241
     *
242
     * @param name the fully qualified name of the class to be read.
243
     * @throws IOException if an exception occurs during reading.
244
     */
245
    public ClassReader(final String name) throws IOException {
246
        this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
247
                + ".class"));
248
    }
249
 
250
    /**
251
     * Reads the bytecode of a class.
252
     *
253
     * @param is an input stream from which to read the class.
254
     * @return the bytecode read from the given input stream.
255
     * @throws IOException if a problem occurs during reading.
256
     */
257
    private static byte[] readClass(final InputStream is) throws IOException {
258
        if (is == null) {
259
            throw new IOException("Class not found");
260
        }
261
        byte[] b = new byte[is.available()];
262
        int len = 0;
263
        while (true) {
264
            int n = is.read(b, len, b.length - len);
265
            if (n == -1) {
266
                if (len < b.length) {
267
                    byte[] c = new byte[len];
268
                    System.arraycopy(b, 0, c, 0, len);
269
                    b = c;
270
                }
271
                return b;
272
            }
273
            len += n;
274
            if (len == b.length) {
275
                byte[] c = new byte[b.length + 1000];
276
                System.arraycopy(b, 0, c, 0, len);
277
                b = c;
278
            }
279
        }
280
    }
281
 
282
    // ------------------------------------------------------------------------
283
    // Public methods
284
    // ------------------------------------------------------------------------
285
 
286
    /**
287
     * Makes the given visitor visit the Java class of this {@link ClassReader}.
288
     * This class is the one specified in the constructor (see
289
     * {@link #ClassReader(byte[]) ClassReader}).
290
     *
291
     * @param classVisitor the visitor that must visit this class.
292
     * @param skipDebug <tt>true</tt> if the debug information of the class
293
     *        must not be visited. In this case the
294
     *        {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
295
     *        {@link MethodVisitor#visitLineNumber visitLineNumber} methods will
296
     *        not be called.
297
     */
298
    public void accept(final ClassVisitor classVisitor, final boolean skipDebug)
299
    {
300
        accept(classVisitor, new Attribute[0], skipDebug);
301
    }
302
 
303
    /**
304
     * Makes the given visitor visit the Java class of this {@link ClassReader}.
305
     * This class is the one specified in the constructor (see
306
     * {@link #ClassReader(byte[]) ClassReader}).
307
     *
308
     * @param classVisitor the visitor that must visit this class.
309
     * @param attrs prototypes of the attributes that must be parsed during the
310
     *        visit of the class. Any attribute whose type is not equal to the
311
     *        type of one the prototypes will be ignored.
312
     * @param skipDebug <tt>true</tt> if the debug information of the class
313
     *        must not be visited. In this case the
314
     *        {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
315
     *        {@link MethodVisitor#visitLineNumber visitLineNumber} methods will
316
     *        not be called.
317
     */
318
    public void accept(
319
        final ClassVisitor classVisitor,
320
        final Attribute[] attrs,
321
        final boolean skipDebug)
322
    {
323
        byte[] b = this.b; // the bytecode array
324
        char[] c = new char[maxStringLength]; // buffer used to read strings
325
        int i, j, k; // loop variables
326
        int u, v, w; // indexes in b
327
        Attribute attr;
328
 
329
        int access;
330
        String name;
331
        String desc;
332
        String attrName;
333
        String signature;
334
        int anns = 0;
335
        int ianns = 0;
336
        Attribute cattrs = null;
337
 
338
        // visits the header
339
        u = header;
340
        access = readUnsignedShort(u);
341
        name = readClass(u + 2, c);
342
        v = items[readUnsignedShort(u + 4)];
343
        String superClassName = v == 0 ? null : readUTF8(v, c);
344
        String[] implementedItfs = new String[readUnsignedShort(u + 6)];
345
        w = 0;
346
        u += 8;
347
        for (i = 0; i < implementedItfs.length; ++i) {
348
            implementedItfs[i] = readClass(u, c);
349
            u += 2;
350
        }
351
 
352
        // skips fields and methods
353
        v = u;
354
        i = readUnsignedShort(v);
355
        v += 2;
356
        for (; i > 0; --i) {
357
            j = readUnsignedShort(v + 6);
358
            v += 8;
359
            for (; j > 0; --j) {
360
                v += 6 + readInt(v + 2);
361
            }
362
        }
363
        i = readUnsignedShort(v);
364
        v += 2;
365
        for (; i > 0; --i) {
366
            j = readUnsignedShort(v + 6);
367
            v += 8;
368
            for (; j > 0; --j) {
369
                v += 6 + readInt(v + 2);
370
            }
371
        }
372
        // reads the class's attributes
373
        signature = null;
374
        String sourceFile = null;
375
        String sourceDebug = null;
376
        String enclosingOwner = null;
377
        String enclosingName = null;
378
        String enclosingDesc = null;
379
 
380
        i = readUnsignedShort(v);
381
        v += 2;
382
        for (; i > 0; --i) {
383
            attrName = readUTF8(v, c);
384
            if (attrName.equals("SourceFile")) {
385
                sourceFile = readUTF8(v + 6, c);
386
            } else if (attrName.equals("Deprecated")) {
387
                access |= Opcodes.ACC_DEPRECATED;
388
            } else if (attrName.equals("Synthetic")) {
389
                access |= Opcodes.ACC_SYNTHETIC;
390
            } else if (attrName.equals("Annotation")) {
391
                access |= Opcodes.ACC_ANNOTATION;
392
            } else if (attrName.equals("Enum")) {
393
                access |= Opcodes.ACC_ENUM;
394
            } else if (attrName.equals("InnerClasses")) {
395
                w = v + 6;
396
            } else if (attrName.equals("Signature")) {
397
                signature = readUTF8(v + 6, c);
398
            } else if (attrName.equals("SourceDebugExtension")) {
399
                int len = readInt(v + 2);
400
                sourceDebug = readUTF(v + 6, len, new char[len]);
401
            } else if (attrName.equals("EnclosingMethod")) {
402
                enclosingOwner = readClass(v + 6, c);
403
                int item = readUnsignedShort(v + 8);
404
                if (item != 0) {
405
                    enclosingName = readUTF8(items[item], c);
406
                    enclosingDesc = readUTF8(items[item] + 2, c);
407
                }
408
            } else if (attrName.equals("RuntimeVisibleAnnotations")) {
409
                anns = v + 6;
410
            } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
411
                ianns = v + 6;
412
            } else {
413
                attr = readAttribute(attrs,
414
                        attrName,
415
                        v + 6,
416
                        readInt(v + 2),
417
                        c,
418
                        -1,
419
                        null);
420
                if (attr != null) {
421
                    attr.next = cattrs;
422
                    cattrs = attr;
423
                }
424
            }
425
            v += 6 + readInt(v + 2);
426
        }
427
        // calls the visit method
428
        classVisitor.visit(readInt(4),
429
                access,
430
                name,
431
                signature,
432
                superClassName,
433
                implementedItfs);
434
 
435
        // calls the visitSource method
436
        if (sourceFile != null || sourceDebug != null) {
437
            classVisitor.visitSource(sourceFile, sourceDebug);
438
        }
439
 
440
        // calls the visitOuterClass method
441
        if (enclosingOwner != null) {
442
            classVisitor.visitOuterClass(enclosingOwner,
443
                    enclosingName,
444
                    enclosingDesc);
445
        }
446
 
447
        // visits the class annotations
448
        for (i = 1; i >= 0; --i) {
449
            v = i == 0 ? ianns : anns;
450
            if (v != 0) {
451
                j = readUnsignedShort(v);
452
                v += 2;
453
                for (; j > 0; --j) {
454
                    desc = readUTF8(v, c);
455
                    v += 2;
456
                    v = readAnnotationValues(v,
457
                            c,
458
                            classVisitor.visitAnnotation(desc, i != 0));
459
                }
460
            }
461
        }
462
 
463
        // visits the class attributes
464
        while (cattrs != null) {
465
            attr = cattrs.next;
466
            cattrs.next = null;
467
            classVisitor.visitAttribute(cattrs);
468
            cattrs = attr;
469
        }
470
 
471
        // class the visitInnerClass method
472
        if (w != 0) {
473
            i = readUnsignedShort(w);
474
            w += 2;
475
            for (; i > 0; --i) {
476
                classVisitor.visitInnerClass(readUnsignedShort(w) == 0
477
                        ? null
478
                        : readClass(w, c), readUnsignedShort(w + 2) == 0
479
                        ? null
480
                        : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
481
                        ? null
482
                        : readUTF8(w + 4, c), readUnsignedShort(w + 6));
483
                w += 8;
484
            }
485
        }
486
 
487
        // visits the fields
488
        i = readUnsignedShort(u);
489
        u += 2;
490
        for (; i > 0; --i) {
491
            access = readUnsignedShort(u);
492
            name = readUTF8(u + 2, c);
493
            desc = readUTF8(u + 4, c);
494
            // visits the field's attributes and looks for a ConstantValue
495
            // attribute
496
            int fieldValueItem = 0;
497
            signature = null;
498
            anns = 0;
499
            ianns = 0;
500
            cattrs = null;
501
 
502
            j = readUnsignedShort(u + 6);
503
            u += 8;
504
            for (; j > 0; --j) {
505
                attrName = readUTF8(u, c);
506
                if (attrName.equals("ConstantValue")) {
507
                    fieldValueItem = readUnsignedShort(u + 6);
508
                } else if (attrName.equals("Synthetic")) {
509
                    access |= Opcodes.ACC_SYNTHETIC;
510
                } else if (attrName.equals("Deprecated")) {
511
                    access |= Opcodes.ACC_DEPRECATED;
512
                } else if (attrName.equals("Enum")) {
513
                    access |= Opcodes.ACC_ENUM;
514
                } else if (attrName.equals("Signature")) {
515
                    signature = readUTF8(u + 6, c);
516
                } else if (attrName.equals("RuntimeVisibleAnnotations")) {
517
                    anns = u + 6;
518
                } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
519
                    ianns = u + 6;
520
                } else {
521
                    attr = readAttribute(attrs,
522
                            attrName,
523
                            u + 6,
524
                            readInt(u + 2),
525
                            c,
526
                            -1,
527
                            null);
528
                    if (attr != null) {
529
                        attr.next = cattrs;
530
                        cattrs = attr;
531
                    }
532
                }
533
                u += 6 + readInt(u + 2);
534
            }
535
            // reads the field's value, if any
536
            Object value = (fieldValueItem == 0
537
                    ? null
538
                    : readConst(fieldValueItem, c));
539
            // visits the field
540
            FieldVisitor fv = classVisitor.visitField(access,
541
                    name,
542
                    desc,
543
                    signature,
544
                    value);
545
            // visits the field annotations and attributes
546
            if (fv != null) {
547
                for (j = 1; j >= 0; --j) {
548
                    v = j == 0 ? ianns : anns;
549
                    if (v != 0) {
550
                        k = readUnsignedShort(v);
551
                        v += 2;
552
                        for (; k > 0; --k) {
553
                            desc = readUTF8(v, c);
554
                            v += 2;
555
                            v = readAnnotationValues(v,
556
                                    c,
557
                                    fv.visitAnnotation(desc, j != 0));
558
                        }
559
                    }
560
                }
561
                while (cattrs != null) {
562
                    attr = cattrs.next;
563
                    cattrs.next = null;
564
                    fv.visitAttribute(cattrs);
565
                    cattrs = attr;
566
                }
567
                fv.visitEnd();
568
            }
569
        }
570
 
571
        // visits the methods
572
        i = readUnsignedShort(u);
573
        u += 2;
574
        for (; i > 0; --i) {
575
            int u0 = u + 6;
576
            access = readUnsignedShort(u);
577
            name = readUTF8(u + 2, c);
578
            desc = readUTF8(u + 4, c);
579
            signature = null;
580
            anns = 0;
581
            ianns = 0;
582
            int dann = 0;
583
            int mpanns = 0;
584
            int impanns = 0;
585
            cattrs = null;
586
            v = 0;
587
            w = 0;
588
 
589
            // looks for Code and Exceptions attributes
590
            j = readUnsignedShort(u + 6);
591
            u += 8;
592
            for (; j > 0; --j) {
593
                attrName = readUTF8(u, c);
594
                u += 2;
595
                int attrSize = readInt(u);
596
                u += 4;
597
                if (attrName.equals("Code")) {
598
                    v = u;
599
                } else if (attrName.equals("Exceptions")) {
600
                    w = u;
601
                } else if (attrName.equals("Synthetic")) {
602
                    access |= Opcodes.ACC_SYNTHETIC;
603
                } else if (attrName.equals("Varargs")) {
604
                    access |= Opcodes.ACC_VARARGS;
605
                } else if (attrName.equals("Bridge")) {
606
                    access |= Opcodes.ACC_BRIDGE;
607
                } else if (attrName.equals("Deprecated")) {
608
                    access |= Opcodes.ACC_DEPRECATED;
609
                } else if (attrName.equals("Signature")) {
610
                    signature = readUTF8(u, c);
611
                } else if (attrName.equals("AnnotationDefault")) {
612
                    dann = u;
613
                } else if (attrName.equals("RuntimeVisibleAnnotations")) {
614
                    anns = u;
615
                } else if (attrName.equals("RuntimeInvisibleAnnotations")) {
616
                    ianns = u;
617
                } else if (attrName.equals("RuntimeVisibleParameterAnnotations"))
618
                {
619
                    mpanns = u;
620
                } else if (attrName.equals("RuntimeInvisibleParameterAnnotations"))
621
                {
622
                    impanns = u;
623
                } else {
624
                    attr = readAttribute(attrs,
625
                            attrName,
626
                            u,
627
                            attrSize,
628
                            c,
629
                            -1,
630
                            null);
631
                    if (attr != null) {
632
                        attr.next = cattrs;
633
                        cattrs = attr;
634
                    }
635
                }
636
                u += attrSize;
637
            }
638
            // reads declared exceptions
639
            String[] exceptions;
640
            if (w == 0) {
641
                exceptions = null;
642
            } else {
643
                exceptions = new String[readUnsignedShort(w)];
644
                w += 2;
645
                for (j = 0; j < exceptions.length; ++j) {
646
                    exceptions[j] = readClass(w, c);
647
                    w += 2;
648
                }
649
            }
650
 
651
            // visits the method's code, if any
652
            MethodVisitor mv = classVisitor.visitMethod(access,
653
                    name,
654
                    desc,
655
                    signature,
656
                    exceptions);
657
 
658
            if (mv != null) {
659
                /*
660
                 * if the returned MethodVisitor is in fact a MethodWriter, it
661
                 * means there is no method adapter between the reader and the
662
                 * writer. If, in addition, the writer's constant pool was
663
                 * copied from this reader (mw.cw.cr == this), and the signature
664
                 * and exceptions of the method have not been changed, then it
665
                 * is possible to skip all visit events and just copy the
666
                 * original code of the method to the writer (the access, name
667
                 * and descriptor can have been changed, this is not important
668
                 * since they are not copied as is from the reader).
669
                 */
670
                if (mv instanceof MethodWriter) {
671
                    MethodWriter mw = (MethodWriter) mv;
672
                    if (mw.cw.cr == this) {
673
                        if (signature == mw.signature) {
674
                            boolean sameExceptions = false;
675
                            if (exceptions == null) {
676
                                sameExceptions = mw.exceptionCount == 0;
677
                            } else {
678
                                if (exceptions.length == mw.exceptionCount) {
679
                                    sameExceptions = true;
680
                                    for (j = exceptions.length - 1; j >= 0; --j)
681
                                    {
682
                                        w -= 2;
683
                                        if (mw.exceptions[j] != readUnsignedShort(w))
684
                                        {
685
                                            sameExceptions = false;
686
                                            break;
687
                                        }
688
                                    }
689
                                }
690
                            }
691
                            if (sameExceptions) {
692
                                /*
693
                                 * we do not copy directly the code into
694
                                 * MethodWriter to save a byte array copy
695
                                 * operation. The real copy will be done in
696
                                 * ClassWriter.toByteArray().
697
                                 */
698
                                mw.classReaderOffset = u0;
699
                                mw.classReaderLength = u - u0;
700
                                continue;
701
                            }
702
                        }
703
                    }
704
                }
705
                if (dann != 0) {
706
                    AnnotationVisitor dv = mv.visitAnnotationDefault();
707
                    readAnnotationValue(dann, c, null, dv);
708
                    dv.visitEnd();
709
                }
710
                for (j = 1; j >= 0; --j) {
711
                    w = j == 0 ? ianns : anns;
712
                    if (w != 0) {
713
                        k = readUnsignedShort(w);
714
                        w += 2;
715
                        for (; k > 0; --k) {
716
                            desc = readUTF8(w, c);
717
                            w += 2;
718
                            w = readAnnotationValues(w,
719
                                    c,
720
                                    mv.visitAnnotation(desc, j != 0));
721
                        }
722
                    }
723
                }
724
                if (mpanns != 0) {
725
                    readParameterAnnotations(mpanns, c, true, mv);
726
                }
727
                if (impanns != 0) {
728
                    readParameterAnnotations(impanns, c, false, mv);
729
                }
730
                while (cattrs != null) {
731
                    attr = cattrs.next;
732
                    cattrs.next = null;
733
                    mv.visitAttribute(cattrs);
734
                    cattrs = attr;
735
                }
736
            }
737
 
738
            if (mv != null && v != 0) {
739
                int maxStack = readUnsignedShort(v);
740
                int maxLocals = readUnsignedShort(v + 2);
741
                int codeLength = readInt(v + 4);
742
                v += 8;
743
 
744
                int codeStart = v;
745
                int codeEnd = v + codeLength;
746
 
747
                mv.visitCode();
748
 
749
                // 1st phase: finds the labels
750
                int label;
751
                Label[] labels = new Label[codeLength + 1];
752
                while (v < codeEnd) {
753
                    int opcode = b[v] & 0xFF;
754
                    switch (ClassWriter.TYPE[opcode]) {
755
                        case ClassWriter.NOARG_INSN:
756
                        case ClassWriter.IMPLVAR_INSN:
757
                            v += 1;
758
                            break;
759
                        case ClassWriter.LABEL_INSN:
760
                            label = v - codeStart + readShort(v + 1);
761
                            if (labels[label] == null) {
762
                                labels[label] = new Label();
763
                            }
764
                            v += 3;
765
                            break;
766
                        case ClassWriter.LABELW_INSN:
767
                            label = v - codeStart + readInt(v + 1);
768
                            if (labels[label] == null) {
769
                                labels[label] = new Label();
770
                            }
771
                            v += 5;
772
                            break;
773
                        case ClassWriter.WIDE_INSN:
774
                            opcode = b[v + 1] & 0xFF;
775
                            if (opcode == Opcodes.IINC) {
776
                                v += 6;
777
                            } else {
778
                                v += 4;
779
                            }
780
                            break;
781
                        case ClassWriter.TABL_INSN:
782
                            // skips 0 to 3 padding bytes
783
                            w = v - codeStart;
784
                            v = v + 4 - (w & 3);
785
                            // reads instruction
786
                            label = w + readInt(v);
787
                            v += 4;
788
                            if (labels[label] == null) {
789
                                labels[label] = new Label();
790
                            }
791
                            j = readInt(v);
792
                            v += 4;
793
                            j = readInt(v) - j + 1;
794
                            v += 4;
795
                            for (; j > 0; --j) {
796
                                label = w + readInt(v);
797
                                v += 4;
798
                                if (labels[label] == null) {
799
                                    labels[label] = new Label();
800
                                }
801
                            }
802
                            break;
803
                        case ClassWriter.LOOK_INSN:
804
                            // skips 0 to 3 padding bytes
805
                            w = v - codeStart;
806
                            v = v + 4 - (w & 3);
807
                            // reads instruction
808
                            label = w + readInt(v);
809
                            v += 4;
810
                            if (labels[label] == null) {
811
                                labels[label] = new Label();
812
                            }
813
                            j = readInt(v);
814
                            v += 4;
815
                            for (; j > 0; --j) {
816
                                v += 4; // skips key
817
                                label = w + readInt(v);
818
                                v += 4;
819
                                if (labels[label] == null) {
820
                                    labels[label] = new Label();
821
                                }
822
                            }
823
                            break;
824
                        case ClassWriter.VAR_INSN:
825
                        case ClassWriter.SBYTE_INSN:
826
                        case ClassWriter.LDC_INSN:
827
                            v += 2;
828
                            break;
829
                        case ClassWriter.SHORT_INSN:
830
                        case ClassWriter.LDCW_INSN:
831
                        case ClassWriter.FIELDORMETH_INSN:
832
                        case ClassWriter.TYPE_INSN:
833
                        case ClassWriter.IINC_INSN:
834
                            v += 3;
835
                            break;
836
                        case ClassWriter.ITFMETH_INSN:
837
                            v += 5;
838
                            break;
839
                        // case MANA_INSN:
840
                        default:
841
                            v += 4;
842
                            break;
843
                    }
844
                }
845
                // parses the try catch entries
846
                j = readUnsignedShort(v);
847
                v += 2;
848
                for (; j > 0; --j) {
849
                    label = readUnsignedShort(v);
850
                    Label start = labels[label];
851
                    if (start == null) {
852
                        labels[label] = start = new Label();
853
                    }
854
                    label = readUnsignedShort(v + 2);
855
                    Label end = labels[label];
856
                    if (end == null) {
857
                        labels[label] = end = new Label();
858
                    }
859
                    label = readUnsignedShort(v + 4);
860
                    Label handler = labels[label];
861
                    if (handler == null) {
862
                        labels[label] = handler = new Label();
863
                    }
864
 
865
                    int type = readUnsignedShort(v + 6);
866
                    if (type == 0) {
867
                        mv.visitTryCatchBlock(start, end, handler, null);
868
                    } else {
869
                        mv.visitTryCatchBlock(start,
870
                                end,
871
                                handler,
872
                                readUTF8(items[type], c));
873
                    }
874
                    v += 8;
875
                }
876
                // parses the local variable, line number tables, and code
877
                // attributes
878
                int varTable = 0;
879
                int varTypeTable = 0;
880
                cattrs = null;
881
                j = readUnsignedShort(v);
882
                v += 2;
883
                for (; j > 0; --j) {
884
                    attrName = readUTF8(v, c);
885
                    if (attrName.equals("LocalVariableTable")) {
886
                        if (!skipDebug) {
887
                            varTable = v + 6;
888
                            k = readUnsignedShort(v + 6);
889
                            w = v + 8;
890
                            for (; k > 0; --k) {
891
                                label = readUnsignedShort(w);
892
                                if (labels[label] == null) {
893
                                    labels[label] = new Label();
894
                                }
895
                                label += readUnsignedShort(w + 2);
896
                                if (labels[label] == null) {
897
                                    labels[label] = new Label();
898
                                }
899
                                w += 10;
900
                            }
901
                        }
902
                    } else if (attrName.equals("LocalVariableTypeTable")) {
903
                        varTypeTable = v + 6;
904
                    } else if (attrName.equals("LineNumberTable")) {
905
                        if (!skipDebug) {
906
                            k = readUnsignedShort(v + 6);
907
                            w = v + 8;
908
                            for (; k > 0; --k) {
909
                                label = readUnsignedShort(w);
910
                                if (labels[label] == null) {
911
                                    labels[label] = new Label();
912
                                }
913
                                labels[label].line = readUnsignedShort(w + 2);
914
                                w += 4;
915
                            }
916
                        }
917
                    } else {
918
                        for (k = 0; k < attrs.length; ++k) {
919
                            if (attrs[k].type.equals(attrName)) {
920
                                attr = attrs[k].read(this,
921
                                        v + 6,
922
                                        readInt(v + 2),
923
                                        c,
924
                                        codeStart - 8,
925
                                        labels);
926
                                if (attr != null) {
927
                                    attr.next = cattrs;
928
                                    cattrs = attr;
929
                                }
930
                            }
931
                        }
932
                    }
933
                    v += 6 + readInt(v + 2);
934
                }
935
 
936
                // 2nd phase: visits each instruction
937
                v = codeStart;
938
                Label l;
939
                while (v < codeEnd) {
940
                    w = v - codeStart;
941
                    l = labels[w];
942
                    if (l != null) {
943
                        mv.visitLabel(l);
944
                        if (!skipDebug && l.line > 0) {
945
                            mv.visitLineNumber(l.line, l);
946
                        }
947
                    }
948
                    int opcode = b[v] & 0xFF;
949
                    switch (ClassWriter.TYPE[opcode]) {
950
                        case ClassWriter.NOARG_INSN:
951
                            mv.visitInsn(opcode);
952
                            v += 1;
953
                            break;
954
                        case ClassWriter.IMPLVAR_INSN:
955
                            if (opcode > Opcodes.ISTORE) {
956
                                opcode -= 59; // ISTORE_0
957
                                mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
958
                                        opcode & 0x3);
959
                            } else {
960
                                opcode -= 26; // ILOAD_0
961
                                mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),
962
                                        opcode & 0x3);
963
                            }
964
                            v += 1;
965
                            break;
966
                        case ClassWriter.LABEL_INSN:
967
                            mv.visitJumpInsn(opcode, labels[w
968
                                    + readShort(v + 1)]);
969
                            v += 3;
970
                            break;
971
                        case ClassWriter.LABELW_INSN:
972
                            mv.visitJumpInsn(opcode - 33, labels[w
973
                                    + readInt(v + 1)]);
974
                            v += 5;
975
                            break;
976
                        case ClassWriter.WIDE_INSN:
977
                            opcode = b[v + 1] & 0xFF;
978
                            if (opcode == Opcodes.IINC) {
979
                                mv.visitIincInsn(readUnsignedShort(v + 2),
980
                                        readShort(v + 4));
981
                                v += 6;
982
                            } else {
983
                                mv.visitVarInsn(opcode,
984
                                        readUnsignedShort(v + 2));
985
                                v += 4;
986
                            }
987
                            break;
988
                        case ClassWriter.TABL_INSN:
989
                            // skips 0 to 3 padding bytes
990
                            v = v + 4 - (w & 3);
991
                            // reads instruction
992
                            label = w + readInt(v);
993
                            v += 4;
994
                            int min = readInt(v);
995
                            v += 4;
996
                            int max = readInt(v);
997
                            v += 4;
998
                            Label[] table = new Label[max - min + 1];
999
                            for (j = 0; j < table.length; ++j) {
1000
                                table[j] = labels[w + readInt(v)];
1001
                                v += 4;
1002
                            }
1003
                            mv.visitTableSwitchInsn(min,
1004
                                    max,
1005
                                    labels[label],
1006
                                    table);
1007
                            break;
1008
                        case ClassWriter.LOOK_INSN:
1009
                            // skips 0 to 3 padding bytes
1010
                            v = v + 4 - (w & 3);
1011
                            // reads instruction
1012
                            label = w + readInt(v);
1013
                            v += 4;
1014
                            j = readInt(v);
1015
                            v += 4;
1016
                            int[] keys = new int[j];
1017
                            Label[] values = new Label[j];
1018
                            for (j = 0; j < keys.length; ++j) {
1019
                                keys[j] = readInt(v);
1020
                                v += 4;
1021
                                values[j] = labels[w + readInt(v)];
1022
                                v += 4;
1023
                            }
1024
                            mv.visitLookupSwitchInsn(labels[label],
1025
                                    keys,
1026
                                    values);
1027
                            break;
1028
                        case ClassWriter.VAR_INSN:
1029
                            mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
1030
                            v += 2;
1031
                            break;
1032
                        case ClassWriter.SBYTE_INSN:
1033
                            mv.visitIntInsn(opcode, b[v + 1]);
1034
                            v += 2;
1035
                            break;
1036
                        case ClassWriter.SHORT_INSN:
1037
                            mv.visitIntInsn(opcode, readShort(v + 1));
1038
                            v += 3;
1039
                            break;
1040
                        case ClassWriter.LDC_INSN:
1041
                            mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
1042
                            v += 2;
1043
                            break;
1044
                        case ClassWriter.LDCW_INSN:
1045
                            mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),
1046
                                    c));
1047
                            v += 3;
1048
                            break;
1049
                        case ClassWriter.FIELDORMETH_INSN:
1050
                        case ClassWriter.ITFMETH_INSN:
1051
                            int cpIndex = items[readUnsignedShort(v + 1)];
1052
                            String iowner = readClass(cpIndex, c);
1053
                            cpIndex = items[readUnsignedShort(cpIndex + 2)];
1054
                            String iname = readUTF8(cpIndex, c);
1055
                            String idesc = readUTF8(cpIndex + 2, c);
1056
                            if (opcode < Opcodes.INVOKEVIRTUAL) {
1057
                                mv.visitFieldInsn(opcode, iowner, iname, idesc);
1058
                            } else {
1059
                                mv.visitMethodInsn(opcode, iowner, iname, idesc);
1060
                            }
1061
                            if (opcode == Opcodes.INVOKEINTERFACE) {
1062
                                v += 5;
1063
                            } else {
1064
                                v += 3;
1065
                            }
1066
                            break;
1067
                        case ClassWriter.TYPE_INSN:
1068
                            mv.visitTypeInsn(opcode, readClass(v + 1, c));
1069
                            v += 3;
1070
                            break;
1071
                        case ClassWriter.IINC_INSN:
1072
                            mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
1073
                            v += 3;
1074
                            break;
1075
                        // case MANA_INSN:
1076
                        default:
1077
                            mv.visitMultiANewArrayInsn(readClass(v + 1, c),
1078
                                    b[v + 3] & 0xFF);
1079
                            v += 4;
1080
                            break;
1081
                    }
1082
                }
1083
                l = labels[codeEnd - codeStart];
1084
                if (l != null) {
1085
                    mv.visitLabel(l);
1086
                }
1087
 
1088
                // visits the local variable tables
1089
                if (!skipDebug && varTable != 0) {
1090
                    int[] typeTable = null;
1091
                    if (varTypeTable != 0) {
1092
                        w = varTypeTable;
1093
                        k = readUnsignedShort(w) * 3;
1094
                        w += 2;
1095
                        typeTable = new int[k];
1096
                        while (k > 0) {
1097
                            typeTable[--k] = w + 6; // signature
1098
                            typeTable[--k] = readUnsignedShort(w + 8); // index
1099
                            typeTable[--k] = readUnsignedShort(w); // start
1100
                            w += 10;
1101
                        }
1102
                    }
1103
                    w = varTable;
1104
                    k = readUnsignedShort(w);
1105
                    w += 2;
1106
                    for (; k > 0; --k) {
1107
                        int start = readUnsignedShort(w);
1108
                        int length = readUnsignedShort(w + 2);
1109
                        int index = readUnsignedShort(w + 8);
1110
                        String vsignature = null;
1111
                        if (typeTable != null) {
1112
                            for (int a = 0; a < typeTable.length; a += 3) {
1113
                                if (typeTable[a] == start
1114
                                        && typeTable[a + 1] == index)
1115
                                {
1116
                                    vsignature = readUTF8(typeTable[a + 2], c);
1117
                                    break;
1118
                                }
1119
                            }
1120
                        }
1121
                        mv.visitLocalVariable(readUTF8(w + 4, c),
1122
                                readUTF8(w + 6, c),
1123
                                vsignature,
1124
                                labels[start],
1125
                                labels[start + length],
1126
                                index);
1127
                        w += 10;
1128
                    }
1129
                }
1130
                // visits the other attributes
1131
                while (cattrs != null) {
1132
                    attr = cattrs.next;
1133
                    cattrs.next = null;
1134
                    mv.visitAttribute(cattrs);
1135
                    cattrs = attr;
1136
                }
1137
                // visits the max stack and max locals values
1138
                mv.visitMaxs(maxStack, maxLocals);
1139
            }
1140
 
1141
            if (mv != null) {
1142
                mv.visitEnd();
1143
            }
1144
        }
1145
 
1146
        // visits the end of the class
1147
        classVisitor.visitEnd();
1148
    }
1149
 
1150
    /**
1151
     * Reads parameter annotations and makes the given visitor visit them.
1152
     *
1153
     * @param v start offset in {@link #b b} of the annotations to be read.
1154
     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1155
     *        {@link #readClass(int,char[]) readClass} or
1156
     *        {@link #readConst readConst}.
1157
     * @param visible <tt>true</tt> if the annotations to be read are visible
1158
     *        at runtime.
1159
     * @param mv the visitor that must visit the annotations.
1160
     */
1161
    private void readParameterAnnotations(
1162
        int v,
1163
        final char[] buf,
1164
        final boolean visible,
1165
        final MethodVisitor mv)
1166
    {
1167
        int n = b[v++] & 0xFF;
1168
        for (int i = 0; i < n; ++i) {
1169
            int j = readUnsignedShort(v);
1170
            v += 2;
1171
            for (; j > 0; --j) {
1172
                String desc = readUTF8(v, buf);
1173
                v += 2;
1174
                AnnotationVisitor av = mv.visitParameterAnnotation(i,
1175
                        desc,
1176
                        visible);
1177
                v = readAnnotationValues(v, buf, av);
1178
            }
1179
        }
1180
    }
1181
 
1182
    /**
1183
     * Reads the values of an annotation and makes the given visitor visit them.
1184
     *
1185
     * @param v the start offset in {@link #b b} of the values to be read
1186
     *        (including the unsigned short that gives the number of values).
1187
     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1188
     *        {@link #readClass(int,char[]) readClass} or
1189
     *        {@link #readConst readConst}.
1190
     * @param av the visitor that must visit the values.
1191
     * @return the end offset of the annotations values.
1192
     */
1193
    private int readAnnotationValues(
1194
        int v,
1195
        final char[] buf,
1196
        final AnnotationVisitor av)
1197
    {
1198
        int i = readUnsignedShort(v);
1199
        v += 2;
1200
        for (; i > 0; --i) {
1201
            String name = readUTF8(v, buf);
1202
            v += 2;
1203
            v = readAnnotationValue(v, buf, name, av);
1204
        }
1205
        av.visitEnd();
1206
        return v;
1207
    }
1208
 
1209
    /**
1210
     * Reads a value of an annotation and makes the given visitor visit it.
1211
     *
1212
     * @param v the start offset in {@link #b b} of the value to be read (<i>not
1213
     *        including the value name constant pool index</i>).
1214
     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1215
     *        {@link #readClass(int,char[]) readClass} or
1216
     *        {@link #readConst readConst}.
1217
     * @param name the name of the value to be read.
1218
     * @param av the visitor that must visit the value.
1219
     * @return the end offset of the annotation value.
1220
     */
1221
    private int readAnnotationValue(
1222
        int v,
1223
        final char[] buf,
1224
        final String name,
1225
        final AnnotationVisitor av)
1226
    {
1227
        int i;
1228
        switch (readByte(v++)) {
1229
            case 'I': // pointer to CONSTANT_Integer
1230
            case 'J': // pointer to CONSTANT_Long
1231
            case 'F': // pointer to CONSTANT_Float
1232
            case 'D': // pointer to CONSTANT_Double
1233
                av.visit(name, readConst(readUnsignedShort(v), buf));
1234
                v += 2;
1235
                break;
1236
            case 'B': // pointer to CONSTANT_Byte
1237
                av.visit(name,
1238
                        new Byte((byte) readInt(items[readUnsignedShort(v)])));
1239
                v += 2;
1240
                break;
1241
            case 'Z': // pointer to CONSTANT_Boolean
1242
                boolean b = readInt(items[readUnsignedShort(v)]) == 0;
1243
                av.visit(name, b ? Boolean.FALSE : Boolean.TRUE);
1244
                v += 2;
1245
                break;
1246
            case 'S': // pointer to CONSTANT_Short
1247
                av.visit(name,
1248
                        new Short((short) readInt(items[readUnsignedShort(v)])));
1249
                v += 2;
1250
                break;
1251
            case 'C': // pointer to CONSTANT_Char
1252
                av.visit(name,
1253
                        new Character((char) readInt(items[readUnsignedShort(v)])));
1254
                v += 2;
1255
                break;
1256
            case 's': // pointer to CONSTANT_Utf8
1257
                av.visit(name, readUTF8(v, buf));
1258
                v += 2;
1259
                break;
1260
            case 'e': // enum_const_value
1261
                av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
1262
                v += 4;
1263
                break;
1264
            case 'c': // class_info
1265
                av.visit(name, Type.getType(readUTF8(v, buf)));
1266
                v += 2;
1267
                break;
1268
            case '@': // annotation_value
1269
                String desc = readUTF8(v, buf);
1270
                v += 2;
1271
                v = readAnnotationValues(v, buf, av.visitAnnotation(name, desc));
1272
                break;
1273
            case '[': // array_value
1274
                int size = readUnsignedShort(v);
1275
                v += 2;
1276
                if (size == 0) {
1277
                    av.visitArray(name).visitEnd();
1278
                    return v;
1279
                }
1280
                switch (readByte(v++)) {
1281
                    case 'B':
1282
                        byte[] bv = new byte[size];
1283
                        for (i = 0; i < size; i++) {
1284
                            bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
1285
                            v += 3;
1286
                        }
1287
                        av.visit(name, bv);
1288
                        --v;
1289
                        break;
1290
                    case 'Z':
1291
                        boolean[] zv = new boolean[size];
1292
                        for (i = 0; i < size; i++) {
1293
                            zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
1294
                            v += 3;
1295
                        }
1296
                        av.visit(name, zv);
1297
                        --v;
1298
                        break;
1299
                    case 'S':
1300
                        short[] sv = new short[size];
1301
                        for (i = 0; i < size; i++) {
1302
                            sv[i] = (short) readInt(items[readUnsignedShort(v)]);
1303
                            v += 3;
1304
                        }
1305
                        av.visit(name, sv);
1306
                        --v;
1307
                        break;
1308
                    case 'C':
1309
                        char[] cv = new char[size];
1310
                        for (i = 0; i < size; i++) {
1311
                            cv[i] = (char) readInt(items[readUnsignedShort(v)]);
1312
                            v += 3;
1313
                        }
1314
                        av.visit(name, cv);
1315
                        --v;
1316
                        break;
1317
                    case 'I':
1318
                        int[] iv = new int[size];
1319
                        for (i = 0; i < size; i++) {
1320
                            iv[i] = readInt(items[readUnsignedShort(v)]);
1321
                            v += 3;
1322
                        }
1323
                        av.visit(name, iv);
1324
                        --v;
1325
                        break;
1326
                    case 'J':
1327
                        long[] lv = new long[size];
1328
                        for (i = 0; i < size; i++) {
1329
                            lv[i] = readLong(items[readUnsignedShort(v)]);
1330
                            v += 3;
1331
                        }
1332
                        av.visit(name, lv);
1333
                        --v;
1334
                        break;
1335
                    case 'F':
1336
                        float[] fv = new float[size];
1337
                        for (i = 0; i < size; i++) {
1338
                            fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
1339
                            v += 3;
1340
                        }
1341
                        av.visit(name, fv);
1342
                        --v;
1343
                        break;
1344
                    case 'D':
1345
                        double[] dv = new double[size];
1346
                        for (i = 0; i < size; i++) {
1347
                            dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
1348
                            v += 3;
1349
                        }
1350
                        av.visit(name, dv);
1351
                        --v;
1352
                        break;
1353
                    default:
1354
                        v--;
1355
                        AnnotationVisitor aav = av.visitArray(name);
1356
                        for (i = size; i > 0; --i) {
1357
                            v = readAnnotationValue(v, buf, null, aav);
1358
                        }
1359
                        aav.visitEnd();
1360
                }
1361
        }
1362
        return v;
1363
    }
1364
 
1365
    /**
1366
     * Reads an attribute in {@link #b b}.
1367
     *
1368
     * @param attrs prototypes of the attributes that must be parsed during the
1369
     *        visit of the class. Any attribute whose type is not equal to the
1370
     *        type of one the prototypes is ignored (i.e. an empty
1371
     *        {@link Attribute} instance is returned).
1372
     * @param type the type of the attribute.
1373
     * @param off index of the first byte of the attribute's content in
1374
     *        {@link #b b}. The 6 attribute header bytes, containing the type
1375
     *        and the length of the attribute, are not taken into account here
1376
     *        (they have already been read).
1377
     * @param len the length of the attribute's content.
1378
     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1379
     *        {@link #readClass(int,char[]) readClass} or
1380
     *        {@link #readConst readConst}.
1381
     * @param codeOff index of the first byte of code's attribute content in
1382
     *        {@link #b b}, or -1 if the attribute to be read is not a code
1383
     *        attribute. The 6 attribute header bytes, containing the type and
1384
     *        the length of the attribute, are not taken into account here.
1385
     * @param labels the labels of the method's code, or <tt>null</tt> if the
1386
     *        attribute to be read is not a code attribute.
1387
     * @return the attribute that has been read, or <tt>null</tt> to skip this
1388
     *         attribute.
1389
     */
1390
    private Attribute readAttribute(
1391
        final Attribute[] attrs,
1392
        final String type,
1393
        final int off,
1394
        final int len,
1395
        final char[] buf,
1396
        final int codeOff,
1397
        final Label[] labels)
1398
    {
1399
        for (int i = 0; i < attrs.length; ++i) {
1400
            if (attrs[i].type.equals(type)) {
1401
                return attrs[i].read(this, off, len, buf, codeOff, labels);
1402
            }
1403
        }
1404
        return new Attribute(type).read(this, off, len, null, -1, null);
1405
    }
1406
 
1407
    // ------------------------------------------------------------------------
1408
    // Utility methods: low level parsing
1409
    // ------------------------------------------------------------------------
1410
 
1411
    /**
1412
     * Returns the start index of the constant pool item in {@link #b b}, plus
1413
     * one. <i>This method is intended for {@link Attribute} sub classes, and is
1414
     * normally not needed by class generators or adapters.</i>
1415
     *
1416
     * @param item the index a constant pool item.
1417
     * @return the start index of the constant pool item in {@link #b b}, plus
1418
     *         one.
1419
     */
1420
    public int getItem(final int item) {
1421
        return items[item];
1422
    }
1423
 
1424
    /**
1425
     * Reads a byte value in {@link #b b}. <i>This method is intended for
1426
     * {@link Attribute} sub classes, and is normally not needed by class
1427
     * generators or adapters.</i>
1428
     *
1429
     * @param index the start index of the value to be read in {@link #b b}.
1430
     * @return the read value.
1431
     */
1432
    public int readByte(final int index) {
1433
        return b[index] & 0xFF;
1434
    }
1435
 
1436
    /**
1437
     * Reads an unsigned short value in {@link #b b}. <i>This method is
1438
     * intended for {@link Attribute} sub classes, and is normally not needed by
1439
     * class generators or adapters.</i>
1440
     *
1441
     * @param index the start index of the value to be read in {@link #b b}.
1442
     * @return the read value.
1443
     */
1444
    public int readUnsignedShort(final int index) {
1445
        byte[] b = this.b;
1446
        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
1447
    }
1448
 
1449
    /**
1450
     * Reads a signed short value in {@link #b b}. <i>This method is intended
1451
     * for {@link Attribute} sub classes, and is normally not needed by class
1452
     * generators or adapters.</i>
1453
     *
1454
     * @param index the start index of the value to be read in {@link #b b}.
1455
     * @return the read value.
1456
     */
1457
    public short readShort(final int index) {
1458
        byte[] b = this.b;
1459
        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
1460
    }
1461
 
1462
    /**
1463
     * Reads a signed int value in {@link #b b}. <i>This method is intended for
1464
     * {@link Attribute} sub classes, and is normally not needed by class
1465
     * generators or adapters.</i>
1466
     *
1467
     * @param index the start index of the value to be read in {@link #b b}.
1468
     * @return the read value.
1469
     */
1470
    public int readInt(final int index) {
1471
        byte[] b = this.b;
1472
        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
1473
                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
1474
    }
1475
 
1476
    /**
1477
     * Reads a signed long value in {@link #b b}. <i>This method is intended
1478
     * for {@link Attribute} sub classes, and is normally not needed by class
1479
     * generators or adapters.</i>
1480
     *
1481
     * @param index the start index of the value to be read in {@link #b b}.
1482
     * @return the read value.
1483
     */
1484
    public long readLong(final int index) {
1485
        long l1 = readInt(index);
1486
        long l0 = readInt(index + 4) & 0xFFFFFFFFL;
1487
        return (l1 << 32) | l0;
1488
    }
1489
 
1490
    /**
1491
     * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
1492
     * is intended for {@link Attribute} sub classes, and is normally not needed
1493
     * by class generators or adapters.</i>
1494
     *
1495
     * @param index the start index of an unsigned short value in {@link #b b},
1496
     *        whose value is the index of an UTF8 constant pool item.
1497
     * @param buf buffer to be used to read the item. This buffer must be
1498
     *        sufficiently large. It is not automatically resized.
1499
     * @return the String corresponding to the specified UTF8 item.
1500
     */
1501
    public String readUTF8(int index, final char[] buf) {
1502
        int item = readUnsignedShort(index);
1503
        String s = strings[item];
1504
        if (s != null) {
1505
            return s;
1506
        }
1507
        index = items[item];
1508
        return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
1509
    }
1510
 
1511
    /**
1512
     * Reads UTF8 string in {@link #b b}.
1513
     *
1514
     * @param index start offset of the UTF8 string to be read.
1515
     * @param utfLen length of the UTF8 string to be read.
1516
     * @param buf buffer to be used to read the string. This buffer must be
1517
     *        sufficiently large. It is not automatically resized.
1518
     * @return the String corresponding to the specified UTF8 string.
1519
     */
1520
    private String readUTF(int index, int utfLen, char[] buf) {
1521
        int endIndex = index + utfLen;
1522
        byte[] b = this.b;
1523
        int strLen = 0;
1524
        int c, d, e;
1525
        while (index < endIndex) {
1526
            c = b[index++] & 0xFF;
1527
            switch (c >> 4) {
1528
                case 0:
1529
                case 1:
1530
                case 2:
1531
                case 3:
1532
                case 4:
1533
                case 5:
1534
                case 6:
1535
                case 7:
1536
                    // 0xxxxxxx
1537
                    buf[strLen++] = (char) c;
1538
                    break;
1539
                case 12:
1540
                case 13:
1541
                    // 110x xxxx 10xx xxxx
1542
                    d = b[index++];
1543
                    buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));
1544
                    break;
1545
                default:
1546
                    // 1110 xxxx 10xx xxxx 10xx xxxx
1547
                    d = b[index++];
1548
                    e = b[index++];
1549
                    buf[strLen++] = (char) (((c & 0x0F) << 12)
1550
                            | ((d & 0x3F) << 6) | (e & 0x3F));
1551
                    break;
1552
            }
1553
        }
1554
        return new String(buf, 0, strLen);
1555
    }
1556
 
1557
    /**
1558
     * Reads a class constant pool item in {@link #b b}. <i>This method is
1559
     * intended for {@link Attribute} sub classes, and is normally not needed by
1560
     * class generators or adapters.</i>
1561
     *
1562
     * @param index the start index of an unsigned short value in {@link #b b},
1563
     *        whose value is the index of a class constant pool item.
1564
     * @param buf buffer to be used to read the item. This buffer must be
1565
     *        sufficiently large. It is not automatically resized.
1566
     * @return the String corresponding to the specified class item.
1567
     */
1568
    public String readClass(final int index, final char[] buf) {
1569
        // computes the start index of the CONSTANT_Class item in b
1570
        // and reads the CONSTANT_Utf8 item designated by
1571
        // the first two bytes of this CONSTANT_Class item
1572
        return readUTF8(items[readUnsignedShort(index)], buf);
1573
    }
1574
 
1575
    /**
1576
     * Reads a numeric or string constant pool item in {@link #b b}. <i>This
1577
     * method is intended for {@link Attribute} sub classes, and is normally not
1578
     * needed by class generators or adapters.</i>
1579
     *
1580
     * @param item the index of a constant pool item.
1581
     * @param buf buffer to be used to read the item. This buffer must be
1582
     *        sufficiently large. It is not automatically resized.
1583
     * @return the {@link Integer}, {@link Float}, {@link Long},
1584
     *         {@link Double}, {@link String} or {@link Type} corresponding to
1585
     *         the given constant pool item.
1586
     */
1587
    public Object readConst(final int item, final char[] buf) {
1588
        int index = items[item];
1589
        switch (b[index - 1]) {
1590
            case ClassWriter.INT:
1591
                return new Integer(readInt(index));
1592
            case ClassWriter.FLOAT:
1593
                return new Float(Float.intBitsToFloat(readInt(index)));
1594
            case ClassWriter.LONG:
1595
                return new Long(readLong(index));
1596
            case ClassWriter.DOUBLE:
1597
                return new Double(Double.longBitsToDouble(readLong(index)));
1598
            case ClassWriter.CLASS:
1599
                String s = readUTF8(index, buf);
1600
                return Type.getType(s.charAt(0) == '[' ? s : "L" + s + ";");
1601
            // case ClassWriter.STR:
1602
            default:
1603
                return readUTF8(index, buf);
1604
        }
1605
    }
1606
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.