001: /*
002: * Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.javap;
027:
028: import java.util.*;
029: import java.io.*;
030:
031: import static sun.tools.javap.RuntimeConstants.*;
032:
033: /**
034: * Program to print information about class files
035: *
036: * @author Sucheta Dambalkar
037: */
038: public class JavapPrinter {
039: JavapEnvironment env;
040: ClassData cls;
041: byte[] code;
042: String lP = "";
043: PrintWriter out;
044:
045: public JavapPrinter(InputStream cname, PrintWriter out,
046: JavapEnvironment env) {
047: this .out = out;
048: this .cls = new ClassData(cname);
049: this .env = env;
050: }
051:
052: /**
053: * Entry point to print class file information.
054: */
055: public void print() {
056: printclassHeader();
057: printfields();
058: printMethods();
059: printend();
060: }
061:
062: /**
063: * Print a description of the class (not members).
064: */
065: public void printclassHeader() {
066: String srcName = "";
067: if ((srcName = cls.getSourceName()) != "null") // requires debug info
068: out.println("Compiled from " + javaclassname(srcName));
069:
070: if (cls.isInterface()) {
071: // The only useful access modifier of an interface is
072: // public; interfaces are always marked as abstract and
073: // cannot be final.
074: out.print((cls.isPublic() ? "public " : "") + "interface "
075: + javaclassname(cls.getClassName()));
076: } else if (cls.isClass()) {
077: String[] accflags = cls.getAccess();
078: printAccess(accflags);
079: out.print("class " + javaclassname(cls.getClassName()));
080:
081: if (cls.getSuperClassName() != null) {
082: out.print(" extends "
083: + javaclassname(cls.getSuperClassName()));
084: }
085: }
086:
087: String[] interfacelist = cls.getSuperInterfaces();
088: if (interfacelist.length > 0) {
089: if (cls.isClass()) {
090: out.print(" implements ");
091: } else if (cls.isInterface()) {
092: out.print(" extends ");
093: }
094:
095: for (int j = 0; j < interfacelist.length; j++) {
096: out.print(javaclassname(interfacelist[j]));
097:
098: if ((j + 1) < interfacelist.length) {
099: out.print(",");
100: }
101: }
102: }
103:
104: // Print class attribute information.
105: if ((env.showallAttr) || (env.showVerbose)) {
106: printClassAttributes();
107: }
108: // Print verbose output.
109: if (env.showVerbose) {
110: printverbosecls();
111: }
112: out.println("{");
113: }
114:
115: /**
116: * Print verbose output.
117: */
118: public void printverbosecls() {
119: out.println(" minor version: " + cls.getMinor_version());
120: out.println(" major version: " + cls.getMajor_version());
121: out.println(" Constant pool:");
122: printcp();
123: env.showallAttr = true;
124: }
125:
126: /**
127: * Print class attribute information.
128: */
129: public void printClassAttributes() {
130: out.println();
131: AttrData[] clsattrs = cls.getAttributes();
132: for (int i = 0; i < clsattrs.length; i++) {
133: String clsattrname = clsattrs[i].getAttrName();
134: if (clsattrname.equals("SourceFile")) {
135: out.println(" SourceFile: " + cls.getSourceName());
136: } else if (clsattrname.equals("InnerClasses")) {
137: printInnerClasses();
138: } else {
139: printAttrData(clsattrs[i]);
140: }
141: }
142: }
143:
144: /**
145: * Print the fields
146: */
147: public void printfields() {
148: FieldData[] fields = cls.getFields();
149: for (int f = 0; f < fields.length; f++) {
150: String[] accflags = fields[f].getAccess();
151: if (checkAccess(accflags)) {
152: if (!(env.showLineAndLocal || env.showDisassembled
153: || env.showVerbose || env.showInternalSigs || env.showallAttr)) {
154: out.print(" ");
155: }
156: printAccess(accflags);
157: out.println(fields[f].getType() + " "
158: + fields[f].getName() + ";");
159: if (env.showInternalSigs) {
160: out.println(" Signature: "
161: + (fields[f].getInternalSig()));
162: }
163:
164: // print field attribute information.
165: if (env.showallAttr) {
166: printFieldAttributes(fields[f]);
167:
168: }
169: if ((env.showDisassembled) || (env.showLineAndLocal)) {
170: out.println();
171: }
172: }
173: }
174: }
175:
176: /* print field attribute information. */
177: public void printFieldAttributes(FieldData field) {
178: Vector fieldattrs = field.getAttributes();
179: for (int j = 0; j < fieldattrs.size(); j++) {
180: String fieldattrname = ((AttrData) fieldattrs.elementAt(j))
181: .getAttrName();
182: if (fieldattrname.equals("ConstantValue")) {
183: printConstantValue(field);
184: } else if (fieldattrname.equals("Deprecated")) {
185: out.println("Deprecated: " + field.isDeprecated());
186: } else if (fieldattrname.equals("Synthetic")) {
187: out.println(" Synthetic: " + field.isSynthetic());
188: } else {
189: printAttrData((AttrData) fieldattrs.elementAt(j));
190: }
191: }
192: out.println();
193: }
194:
195: /**
196: * Print the methods
197: */
198: public void printMethods() {
199: MethodData[] methods = cls.getMethods();
200: for (int m = 0; m < methods.length; m++) {
201: String[] accflags = methods[m].getAccess();
202: if (checkAccess(accflags)) {
203: if (!(env.showLineAndLocal || env.showDisassembled
204: || env.showVerbose || env.showInternalSigs || env.showallAttr)) {
205: out.print(" ");
206: }
207: printMethodSignature(methods[m], accflags);
208: printExceptions(methods[m]);
209: out.println(";");
210:
211: // Print internal signature of method.
212: if (env.showInternalSigs) {
213: out.println(" Signature: "
214: + (methods[m].getInternalSig()));
215: }
216:
217: //Print disassembled code.
218: if (env.showDisassembled && !env.showallAttr) {
219: printcodeSequence(methods[m]);
220: printExceptionTable(methods[m]);
221: out.println();
222: }
223:
224: // Print line and local variable attribute information.
225: if (env.showLineAndLocal) {
226: printLineNumTable(methods[m]);
227: printLocVarTable(methods[m]);
228: out.println();
229: }
230:
231: // Print method attribute information.
232: if (env.showallAttr) {
233: printMethodAttributes(methods[m]);
234: }
235: }
236: }
237: }
238:
239: /**
240: * Print method signature.
241: */
242: public void printMethodSignature(MethodData method,
243: String[] accflags) {
244: printAccess(accflags);
245:
246: if ((method.getName()).equals("<init>")) {
247: out.print(javaclassname(cls.getClassName()));
248: out.print(method.getParameters());
249: } else if ((method.getName()).equals("<clinit>")) {
250: out.print("{}");
251: } else {
252: out.print(method.getReturnType() + " ");
253: out.print(method.getName());
254: out.print(method.getParameters());
255: }
256: }
257:
258: /**
259: * print method attribute information.
260: */
261: public void printMethodAttributes(MethodData method) {
262: Vector methodattrs = method.getAttributes();
263: Vector codeattrs = method.getCodeAttributes();
264: for (int k = 0; k < methodattrs.size(); k++) {
265: String methodattrname = ((AttrData) methodattrs
266: .elementAt(k)).getAttrName();
267: if (methodattrname.equals("Code")) {
268: printcodeSequence(method);
269: printExceptionTable(method);
270: for (int c = 0; c < codeattrs.size(); c++) {
271: String codeattrname = ((AttrData) codeattrs
272: .elementAt(c)).getAttrName();
273: if (codeattrname.equals("LineNumberTable")) {
274: printLineNumTable(method);
275: } else if (codeattrname
276: .equals("LocalVariableTable")) {
277: printLocVarTable(method);
278: } else if (codeattrname.equals("StackMapTable")) {
279: // Java SE JSR 202 stack map tables
280: printStackMapTable(method);
281: } else if (codeattrname.equals("StackMap")) {
282: // Java ME CLDC stack maps
283: printStackMap(method);
284: } else {
285: printAttrData((AttrData) codeattrs.elementAt(c));
286: }
287: }
288: } else if (methodattrname.equals("Exceptions")) {
289: out.println(" Exceptions: ");
290: printExceptions(method);
291: } else if (methodattrname.equals("Deprecated")) {
292: out.println(" Deprecated: " + method.isDeprecated());
293: } else if (methodattrname.equals("Synthetic")) {
294: out.println(" Synthetic: " + method.isSynthetic());
295: } else {
296: printAttrData((AttrData) methodattrs.elementAt(k));
297: }
298: }
299: out.println();
300: }
301:
302: /**
303: * Print exceptions.
304: */
305: public void printExceptions(MethodData method) {
306: int[] exc_index_table = method.get_exc_index_table();
307: if (exc_index_table != null) {
308: if (!(env.showLineAndLocal || env.showDisassembled
309: || env.showVerbose || env.showInternalSigs || env.showallAttr)) {
310: out.print(" ");
311: }
312: out.print(" throws ");
313: int k;
314: int l = exc_index_table.length;
315:
316: for (k = 0; k < l; k++) {
317: out.print(javaclassname(cls
318: .getClassName(exc_index_table[k])));
319: if (k < l - 1)
320: out.print(", ");
321: }
322: }
323: }
324:
325: /**
326: * Print code sequence.
327: */
328: public void printcodeSequence(MethodData method) {
329: code = method.getCode();
330: if (code != null) {
331: out.println(" Code:");
332: if (env.showVerbose) {
333: printVerboseHeader(method);
334: }
335:
336: for (int pc = 0; pc < code.length;) {
337: out.print(" " + pc + ":\t");
338: pc = pc + printInstr(pc);
339: out.println();
340: }
341: }
342: }
343:
344: /**
345: * Print instructions.
346: */
347: public int printInstr(int pc) {
348: int opcode = getUbyte(pc);
349: int opcode2;
350: String mnem;
351: switch (opcode) {
352: case opc_nonpriv:
353: case opc_priv:
354: opcode2 = getUbyte(pc + 1);
355: mnem = Tables.opcName((opcode << 8) + opcode2);
356: if (mnem == null)
357: // assume all (even nonexistent) priv and nonpriv instructions
358: // are 2 bytes long
359: mnem = Tables.opcName(opcode) + " " + opcode2;
360: out.print(mnem);
361: return 2;
362: case opc_wide: {
363: opcode2 = getUbyte(pc + 1);
364: mnem = Tables.opcName((opcode << 8) + opcode2);
365: if (mnem == null) {
366: // nonexistent opcode - but we have to print something
367: out.print("bytecode " + opcode);
368: return 1;
369: }
370: out.print(mnem + " " + getUShort(pc + 2));
371: if (opcode2 == opc_iinc) {
372: out.print(", " + getShort(pc + 4));
373: return 6;
374: }
375: return 4;
376: }
377: }
378: mnem = Tables.opcName(opcode);
379: if (mnem == null) {
380: // nonexistent opcode - but we have to print something
381: out.print("bytecode " + opcode);
382: return 1;
383: }
384: if (opcode > opc_jsr_w) {
385: // pseudo opcodes should be printed as bytecodes
386: out.print("bytecode " + opcode);
387: return 1;
388: }
389: out.print(Tables.opcName(opcode));
390: switch (opcode) {
391: case opc_aload:
392: case opc_astore:
393: case opc_fload:
394: case opc_fstore:
395: case opc_iload:
396: case opc_istore:
397: case opc_lload:
398: case opc_lstore:
399: case opc_dload:
400: case opc_dstore:
401: case opc_ret:
402: out.print("\t" + getUbyte(pc + 1));
403: return 2;
404: case opc_iinc:
405: out.print("\t" + getUbyte(pc + 1) + ", " + getbyte(pc + 2));
406: return 3;
407: case opc_tableswitch: {
408: int tb = align(pc + 1);
409: int default_skip = getInt(tb); /* default skip pamount */
410: int low = getInt(tb + 4);
411: int high = getInt(tb + 8);
412: int count = high - low;
413: out.print("{ //" + low + " to " + high);
414: for (int i = 0; i <= count; i++)
415: out.print("\n\t\t" + (i + low) + ": " + lP
416: + (pc + getInt(tb + 12 + 4 * i)) + ";");
417: out.print("\n\t\tdefault: " + lP + (default_skip + pc)
418: + " }");
419: return tb - pc + 16 + count * 4;
420: }
421:
422: case opc_lookupswitch: {
423: int tb = align(pc + 1);
424: int default_skip = getInt(tb);
425: int npairs = getInt(tb + 4);
426: out.print("{ //" + npairs);
427: for (int i = 1; i <= npairs; i++)
428: out.print("\n\t\t" + getInt(tb + i * 8) + ": " + lP
429: + (pc + getInt(tb + 4 + i * 8)) + ";");
430: out.print("\n\t\tdefault: " + lP + (default_skip + pc)
431: + " }");
432: return tb - pc + (npairs + 1) * 8;
433: }
434: case opc_newarray:
435: int type = getUbyte(pc + 1);
436: switch (type) {
437: case T_BOOLEAN:
438: out.print(" boolean");
439: break;
440: case T_BYTE:
441: out.print(" byte");
442: break;
443: case T_CHAR:
444: out.print(" char");
445: break;
446: case T_SHORT:
447: out.print(" short");
448: break;
449: case T_INT:
450: out.print(" int");
451: break;
452: case T_LONG:
453: out.print(" long");
454: break;
455: case T_FLOAT:
456: out.print(" float");
457: break;
458: case T_DOUBLE:
459: out.print(" double");
460: break;
461: case T_CLASS:
462: out.print(" class");
463: break;
464: default:
465: out.print(" BOGUS TYPE:" + type);
466: }
467: return 2;
468:
469: case opc_anewarray: {
470: int index = getUShort(pc + 1);
471: out.print("\t#" + index + "; //");
472: PrintConstant(index);
473: return 3;
474: }
475:
476: case opc_sipush:
477: out.print("\t" + getShort(pc + 1));
478: return 3;
479:
480: case opc_bipush:
481: out.print("\t" + getbyte(pc + 1));
482: return 2;
483:
484: case opc_ldc: {
485: int index = getUbyte(pc + 1);
486: out.print("\t#" + index + "; //");
487: PrintConstant(index);
488: return 2;
489: }
490:
491: case opc_ldc_w:
492: case opc_ldc2_w:
493: case opc_instanceof :
494: case opc_checkcast:
495: case opc_new:
496: case opc_putstatic:
497: case opc_getstatic:
498: case opc_putfield:
499: case opc_getfield:
500: case opc_invokevirtual:
501: case opc_invokespecial:
502: case opc_invokestatic: {
503: int index = getUShort(pc + 1);
504: out.print("\t#" + index + "; //");
505: PrintConstant(index);
506: return 3;
507: }
508:
509: case opc_invokeinterface: {
510: int index = getUShort(pc + 1), nargs = getUbyte(pc + 3);
511: out.print("\t#" + index + ", " + nargs + "; //");
512: PrintConstant(index);
513: return 5;
514: }
515:
516: case opc_multianewarray: {
517: int index = getUShort(pc + 1), dimensions = getUbyte(pc + 3);
518: out.print("\t#" + index + ", " + dimensions + "; //");
519: PrintConstant(index);
520: return 4;
521: }
522: case opc_jsr:
523: case opc_goto:
524: case opc_ifeq:
525: case opc_ifge:
526: case opc_ifgt:
527: case opc_ifle:
528: case opc_iflt:
529: case opc_ifne:
530: case opc_if_icmpeq:
531: case opc_if_icmpne:
532: case opc_if_icmpge:
533: case opc_if_icmpgt:
534: case opc_if_icmple:
535: case opc_if_icmplt:
536: case opc_if_acmpeq:
537: case opc_if_acmpne:
538: case opc_ifnull:
539: case opc_ifnonnull:
540: out.print("\t" + lP + (pc + getShort(pc + 1)));
541: return 3;
542:
543: case opc_jsr_w:
544: case opc_goto_w:
545: out.print("\t" + lP + (pc + getInt(pc + 1)));
546: return 5;
547:
548: default:
549: return 1;
550: }
551: }
552:
553: /**
554: * Print code attribute details.
555: */
556: public void printVerboseHeader(MethodData method) {
557: int argCount = method.getArgumentlength();
558: if (!method.isStatic())
559: ++argCount; // for 'this'
560:
561: out.println(" Stack=" + method.getMaxStack() + ", Locals="
562: + method.getMaxLocals() + ", Args_size=" + argCount);
563:
564: }
565:
566: /**
567: * Print the exception table for this method code
568: */
569: void printExceptionTable(MethodData method) {//throws IOException
570: Vector exception_table = method.getexception_table();
571: if (exception_table.size() > 0) {
572: out.println(" Exception table:");
573: out.println(" from to target type");
574: for (int idx = 0; idx < exception_table.size(); ++idx) {
575: TrapData handler = (TrapData) exception_table
576: .elementAt(idx);
577: printFixedWidthInt(handler.start_pc, 6);
578: printFixedWidthInt(handler.end_pc, 6);
579: printFixedWidthInt(handler.handler_pc, 6);
580: out.print(" ");
581: int catch_cpx = handler.catch_cpx;
582: if (catch_cpx == 0) {
583: out.println("any");
584: } else {
585: out.print("Class ");
586: out.println(cls.getClassName(catch_cpx));
587: out.println("");
588: }
589: }
590: }
591: }
592:
593: /**
594: * Print LineNumberTable attribute information.
595: */
596: public void printLineNumTable(MethodData method) {
597: int numlines = method.getnumlines();
598: Vector lin_num_tb = method.getlin_num_tb();
599: if (lin_num_tb.size() > 0) {
600: out.println(" LineNumberTable: ");
601: for (int i = 0; i < numlines; i++) {
602: LineNumData linnumtb_entry = (LineNumData) lin_num_tb
603: .elementAt(i);
604: out.println(" line " + linnumtb_entry.line_number
605: + ": " + linnumtb_entry.start_pc);
606: }
607: }
608: out.println();
609: }
610:
611: /**
612: * Print LocalVariableTable attribute information.
613: */
614: public void printLocVarTable(MethodData method) {
615: int siz = method.getloc_var_tbsize();
616: if (siz > 0) {
617: out.println(" LocalVariableTable: ");
618: out.print(" ");
619: out.println("Start Length Slot Name Signature");
620: }
621: Vector loc_var_tb = method.getloc_var_tb();
622:
623: for (int i = 0; i < siz; i++) {
624: LocVarData entry = (LocVarData) loc_var_tb.elementAt(i);
625:
626: out.println(" " + entry.start_pc + " "
627: + entry.length + " " + entry.slot + " "
628: + cls.StringValue(entry.name_cpx) + " "
629: + cls.StringValue(entry.sig_cpx));
630: }
631: out.println();
632: }
633:
634: /**
635: * Print StackMap attribute information.
636: */
637: public void printStackMap(MethodData method) {
638: StackMapData[] stack_map_tb = method.getStackMap();
639: int number_of_entries = stack_map_tb.length;
640: if (number_of_entries > 0) {
641: out.println(" StackMap: number_of_entries = "
642: + number_of_entries);
643:
644: for (StackMapData frame : stack_map_tb) {
645: frame.print(this );
646: }
647: }
648: out.println();
649: }
650:
651: /**
652: * Print StackMapTable attribute information.
653: */
654: public void printStackMapTable(MethodData method) {
655: StackMapTableData[] stack_map_tb = method.getStackMapTable();
656: int number_of_entries = stack_map_tb.length;
657: if (number_of_entries > 0) {
658: out.println(" StackMapTable: number_of_entries = "
659: + number_of_entries);
660:
661: for (StackMapTableData frame : stack_map_tb) {
662: frame.print(this );
663: }
664: }
665: out.println();
666: }
667:
668: void printMap(String name, int[] map) {
669: out.print(name);
670: for (int i = 0; i < map.length; i++) {
671: int fulltype = map[i];
672: int type = fulltype & 0xFF;
673: int argument = fulltype >> 8;
674: switch (type) {
675: case ITEM_Object:
676: out.print(" ");
677: PrintConstant(argument);
678: break;
679: case ITEM_NewObject:
680: out.print(" " + Tables.mapTypeName(type));
681: out.print(" " + argument);
682: break;
683: default:
684: out.print(" " + Tables.mapTypeName(type));
685: }
686: out.print((i == (map.length - 1) ? ' ' : ','));
687: }
688: out.println("]");
689: }
690:
691: /**
692: * Print ConstantValue attribute information.
693: */
694: public void printConstantValue(FieldData field) {
695: out.print(" Constant value: ");
696: int cpx = (field.getConstantValueIndex());
697: byte tag = 0;
698: try {
699: tag = cls.getTag(cpx);
700:
701: } catch (IndexOutOfBoundsException e) {
702: out.print("Error:");
703: return;
704: }
705: switch (tag) {
706: case CONSTANT_METHOD:
707: case CONSTANT_INTERFACEMETHOD:
708: case CONSTANT_FIELD: {
709: CPX2 x = (CPX2) (cls.getCpoolEntry(cpx));
710: if (x.cpx1 == cls.getthis _cpx()) {
711: // don't print class part for local references
712: cpx = x.cpx2;
713: }
714: }
715: }
716: out.print(cls.TagString(tag) + " " + cls.StringValue(cpx));
717: }
718:
719: /**
720: * Print InnerClass attribute information.
721: */
722: public void printInnerClasses() {//throws ioexception
723:
724: InnerClassData[] innerClasses = cls.getInnerClasses();
725: if (innerClasses != null) {
726: if (innerClasses.length > 0) {
727: out.print(" ");
728: out.println("InnerClass: ");
729: for (int i = 0; i < innerClasses.length; i++) {
730: out.print(" ");
731: //access
732: String[] accflags = innerClasses[i].getAccess();
733: if (checkAccess(accflags)) {
734: printAccess(accflags);
735: if (innerClasses[i].inner_name_index != 0) {
736: out.print("#"
737: + innerClasses[i].inner_name_index
738: + "= ");
739: }
740: out
741: .print("#"
742: + innerClasses[i].inner_class_info_index);
743: if (innerClasses[i].outer_class_info_index != 0) {
744: out
745: .print(" of #"
746: + innerClasses[i].outer_class_info_index);
747: }
748: out.print("; //");
749: if (innerClasses[i].inner_name_index != 0) {
750: out
751: .print(cls
752: .getName(innerClasses[i].inner_name_index)
753: + "=");
754: }
755: PrintConstant(innerClasses[i].inner_class_info_index);
756: if (innerClasses[i].outer_class_info_index != 0) {
757: out.print(" of ");
758: PrintConstant(innerClasses[i].outer_class_info_index);
759: }
760: out.println();
761: }
762: }
763:
764: }
765: }
766: }
767:
768: /**
769: * Print constant pool information.
770: */
771: public void printcp() {
772: int cpx = 1;
773:
774: while (cpx < cls.getCpoolCount()) {
775: out.print("const #" + cpx + " = ");
776: cpx += PrintlnConstantEntry(cpx);
777: }
778: out.println();
779: }
780:
781: /**
782: * Print constant pool entry information.
783: */
784: public int PrintlnConstantEntry(int cpx) {
785: int size = 1;
786: byte tag = 0;
787: try {
788: tag = cls.getTag(cpx);
789: } catch (IndexOutOfBoundsException e) {
790: out.println(" <Incorrect CP index>");
791: return 1;
792: }
793: out.print(cls.StringTag(cpx) + "\t");
794: Object x = cls.getCpoolEntryobj(cpx);
795: if (x == null) {
796: switch (tag) {
797: case CONSTANT_LONG:
798: case CONSTANT_DOUBLE:
799: size = 2;
800: }
801: out.println("null;");
802: return size;
803: }
804: String str = cls.StringValue(cpx);
805:
806: switch (tag) {
807: case CONSTANT_CLASS:
808: case CONSTANT_STRING:
809: out.println("#" + (((CPX) x).cpx) + ";\t// " + str);
810: break;
811: case CONSTANT_FIELD:
812: case CONSTANT_METHOD:
813: case CONSTANT_INTERFACEMETHOD:
814: out.println("#" + ((CPX2) x).cpx1 + ".#" + ((CPX2) x).cpx2
815: + ";\t// " + str);
816: break;
817: case CONSTANT_NAMEANDTYPE:
818: out.println("#" + ((CPX2) x).cpx1 + ":#" + ((CPX2) x).cpx2
819: + ";// " + str);
820: break;
821: case CONSTANT_LONG:
822: case CONSTANT_DOUBLE:
823: size = 2;
824: default:
825: out.println(str + ";");
826: }
827: return size;
828: }
829:
830: /**
831: * Checks access of class, field or method.
832: */
833: public boolean checkAccess(String accflags[]) {
834:
835: boolean ispublic = false;
836: boolean isprotected = false;
837: boolean isprivate = false;
838: boolean ispackage = false;
839:
840: for (int i = 0; i < accflags.length; i++) {
841: if (accflags[i].equals("public"))
842: ispublic = true;
843: else if (accflags[i].equals("protected"))
844: isprotected = true;
845: else if (accflags[i].equals("private"))
846: isprivate = true;
847: }
848:
849: if (!(ispublic || isprotected || isprivate))
850: ispackage = true;
851:
852: if ((env.showAccess == env.PUBLIC)
853: && (isprotected || isprivate || ispackage))
854: return false;
855: else if ((env.showAccess == env.PROTECTED)
856: && (isprivate || ispackage))
857: return false;
858: else if ((env.showAccess == env.PACKAGE) && (isprivate))
859: return false;
860: else
861: return true;
862: }
863:
864: /**
865: * Prints access of class, field or method.
866: */
867: public void printAccess(String[] accflags) {
868: for (int j = 0; j < accflags.length; j++) {
869: out.print(accflags[j] + " ");
870: }
871: }
872:
873: /**
874: * Print an integer so that it takes 'length' characters in
875: * the output. Temporary until formatting code is stable.
876: */
877: public void printFixedWidthInt(long x, int length) {
878: CharArrayWriter baStream = new CharArrayWriter();
879: PrintWriter pStream = new PrintWriter(baStream);
880: pStream.print(x);
881: String str = baStream.toString();
882: for (int cnt = length - str.length(); cnt > 0; --cnt)
883: out.print(' ');
884: out.print(str);
885: }
886:
887: protected int getbyte(int pc) {
888: return code[pc];
889: }
890:
891: protected int getUbyte(int pc) {
892: return code[pc] & 0xFF;
893: }
894:
895: int getShort(int pc) {
896: return (code[pc] << 8) | (code[pc + 1] & 0xFF);
897: }
898:
899: int getUShort(int pc) {
900: return ((code[pc] << 8) | (code[pc + 1] & 0xFF)) & 0xFFFF;
901: }
902:
903: protected int getInt(int pc) {
904: return (getShort(pc) << 16) | (getShort(pc + 2) & 0xFFFF);
905: }
906:
907: /**
908: * Print constant value at that index.
909: */
910: void PrintConstant(int cpx) {
911: if (cpx == 0) {
912: out.print("#0");
913: return;
914: }
915: byte tag = 0;
916: try {
917: tag = cls.getTag(cpx);
918:
919: } catch (IndexOutOfBoundsException e) {
920: out.print("#" + cpx);
921: return;
922: }
923: switch (tag) {
924: case CONSTANT_METHOD:
925: case CONSTANT_INTERFACEMETHOD:
926: case CONSTANT_FIELD: {
927: // CPX2 x=(CPX2)(cpool[cpx]);
928: CPX2 x = (CPX2) (cls.getCpoolEntry(cpx));
929: if (x.cpx1 == cls.getthis _cpx()) {
930: // don't print class part for local references
931: cpx = x.cpx2;
932: }
933: }
934: }
935: out.print(cls.TagString(tag) + " " + cls.StringValue(cpx));
936: }
937:
938: protected static int align(int n) {
939: return (n + 3) & ~3;
940: }
941:
942: public void printend() {
943: out.println("}");
944: out.println();
945: }
946:
947: public String javaclassname(String name) {
948: return name.replace('/', '.');
949: }
950:
951: /**
952: * Print attribute data in hex.
953: */
954: public void printAttrData(AttrData attr) {
955: byte[] data = attr.getData();
956: int i = 0;
957: int j = 0;
958: out.print(" " + attr.getAttrName() + ": ");
959: out.println("length = " + cls.toHex(attr.datalen));
960:
961: out.print(" ");
962:
963: while (i < data.length) {
964: String databytestring = cls.toHex(data[i]);
965: if (databytestring.equals("0x"))
966: out.print("00");
967: else if (databytestring.substring(2).length() == 1) {
968: out.print("0" + databytestring.substring(2));
969: } else {
970: out.print(databytestring.substring(2));
971: }
972:
973: j++;
974: if (j == 16) {
975: out.println();
976: out.print(" ");
977: j = 0;
978: } else
979: out.print(" ");
980: i++;
981: }
982: out.println();
983: }
984: }
|