001: // Copyright (c) 1997 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.bytecode;
005:
006: import java.io.PrintWriter;
007: import java.io.PrintStream;
008:
009: /** This class prints out in contents of a ClassType in human-readable form.
010: * The output format matches my earlier jcf-dump program (in gcc/java).
011: * @author Per Bothner <bothner@cygnus>
012: */
013:
014: public class ClassTypeWriter extends PrintWriter {
015: ClassType ctype;
016: int flags;
017: boolean printConstants = true;
018:
019: public ClassTypeWriter(ClassType ctype, PrintWriter stream,
020: int flags) {
021: super (stream);
022: this .ctype = ctype;
023: this .flags = flags;
024: }
025:
026: public ClassTypeWriter(ClassType ctype, PrintStream stream,
027: int flags) {
028: super (stream);
029: this .ctype = ctype;
030: this .flags = flags;
031: }
032:
033: public static void print(ClassType ctype, PrintWriter stream,
034: int flags) {
035: ClassTypeWriter writer = new ClassTypeWriter(ctype, stream,
036: flags);
037: writer.print();
038: writer.flush();
039: }
040:
041: public static void print(ClassType ctype, PrintStream stream,
042: int flags) {
043: ClassTypeWriter writer = new ClassTypeWriter(ctype, stream,
044: flags);
045: writer.print();
046: writer.flush();
047: }
048:
049: public void print() {
050: if (printConstants)
051: printConstantPool();
052: printClassInfo();
053: printFields();
054: printMethods();
055: }
056:
057: public void printAttributes(AttrContainer container) {
058: for (Attribute attr = container.getAttributes(); attr != null; attr = attr.next) {
059: attr.print(this );
060: }
061: }
062:
063: void printClassInfo() {
064: println();
065: print("Access flags:");
066: int modifiers = ctype.getModifiers();
067: print(Access.toString(modifiers));
068: println();
069: print("This class: ");
070: printOptionalIndex(ctype.this ClassIndex);
071: printConstantTersely(ctype.this ClassIndex, 7);
072: print(" super: ");
073: if (ctype.super ClassIndex == -1)
074: print("<unknown>");
075: else if (ctype.super ClassIndex == 0)
076: print("0");
077: else {
078: printOptionalIndex(ctype.super ClassIndex);
079: printConstantTersely(ctype.super ClassIndex,
080: ConstantPool.CLASS);
081: }
082: println();
083: print("Interfaces (count: ");
084: int[] interfaces = ctype.interfaceIndexes;
085: int n_interfaces = interfaces == null ? 0 : interfaces.length;
086: print(n_interfaces);
087: print("):");
088: println();
089: for (int i = 0; i < n_interfaces; i++) {
090: print("- Implements: ");
091: int index = interfaces[i];
092: printOptionalIndex(index);
093: printConstantTersely(index, 7);
094: println();
095: }
096: }
097:
098: public final void printFields() {
099: println();
100: print("Fields (count: ");
101: print(ctype.fields_count);
102: print("):");
103: println();
104: int ifield = 0;
105: Field field = ctype.fields;
106: for (; field != null; ifield++, field = field.next) {
107: print("Field name: ");
108: if (field.name_index != 0)
109: printOptionalIndex(field.name_index);
110: print(field.getName());
111: print(Access.toString(field.flags));
112: print(" Signature: ");
113: if (field.signature_index != 0)
114: printOptionalIndex(field.signature_index);
115: printSignature(field.type);
116: println();
117: printAttributes(field);
118: }
119: }
120:
121: void printMethods() {
122: println();
123: print("Methods (count: ");
124: print(ctype.methods_count);
125: print("):");
126: println();
127: Method method = ctype.methods;
128: for (; method != null; method = method.next) {
129: println();
130: print("Method name:");
131: if (method.name_index != 0)
132: printOptionalIndex(method.name_index);
133: print('\"');
134: print(method.getName());
135: print('\"');
136: print(Access.toString(method.access_flags));
137: print(" Signature: ");
138: if (method.signature_index != 0)
139: printOptionalIndex(method.signature_index);
140: print('(');
141: for (int i = 0; i < method.arg_types.length; i++) {
142: if (i > 0)
143: print(',');
144: printSignature(method.arg_types[i]);
145: }
146: print(')');
147: printSignature(method.return_type);
148: println();
149: printAttributes(method);
150: }
151: }
152:
153: final void printConstantTersely(int index, int expected_tag) {
154: CpoolEntry[] pool = ctype.constants.pool;
155: CpoolEntry entry;
156: if (pool == null || index < 0 || index >= pool.length
157: || (entry = pool[index]) == null)
158: print("<invalid constant index>");
159: else if (entry.getTag() != expected_tag) {
160: print("<unexpected constant type ");
161: entry.print(this , 1);
162: print('>');
163: } else
164: entry.print(this , 0);
165: }
166:
167: /** Print constant pool index for dis-assembler. */
168: final void printConstantOperand(int index) {
169: print(' ');
170: if (printConstants) {
171: print('#');
172: print(index);
173: print('=');
174: }
175: CpoolEntry[] pool = ctype.constants.pool;
176: CpoolEntry entry;
177: if (pool == null || index < 0 || index >= pool.length
178: || (entry = pool[index]) == null)
179: print("<invalid constant index>");
180: else {
181: print('<');
182: entry.print(this , 1);
183: print('>');
184: }
185: }
186:
187: public final void printQuotedString(String string) {
188: print('\"');
189: int len = string.length();
190: for (int i = 0; i < len; i++) {
191: char ch = string.charAt(i);
192: if (ch == '\"')
193: print("\\\"");
194: else if (ch >= ' ' && ch < 127)
195: print(ch);
196: else if (ch == '\n')
197: print("\\n");
198: else {
199: print("\\u");
200: for (int j = 4; --j >= 0;)
201: print(Character.forDigit((ch >> (j * 4)) & 15, 16));
202: }
203: }
204: print('\"');
205: }
206:
207: public final void printConstantPool() {
208: CpoolEntry[] pool = ctype.constants.pool;
209: int length = ctype.constants.count;
210: for (int i = 1; i <= length; i++) {
211: CpoolEntry entry = pool[i];
212: if (entry == null)
213: continue;
214: print('#');
215: print(entry.index);
216: print(": ");
217: entry.print(this , 2);
218: println();
219: }
220: }
221:
222: public final void printOptionalIndex(int index) {
223: if (printConstants) {
224: print(index);
225: print('=');
226: }
227: }
228:
229: public final void printOptionalIndex(CpoolEntry entry) {
230: printOptionalIndex(entry.index);
231: }
232:
233: void printName(String name) {
234: // in jcf-dump: jcf_print_utf8
235: print(name);
236: }
237:
238: /** Print in Java source form one type from a signature string.
239: * @param sig the signature string to print
240: * @param pos the index in sig to start with
241: * @return the index following the signature of one type. */
242: public final int printSignature(String sig, int pos) {
243: int len = sig.length();
244: if (pos >= len) {
245: print("<empty signature>");
246: return pos;
247: }
248: int sig_length = Type.signatureLength(sig, pos);
249: if (sig_length > 0) {
250: String name = Type.signatureToName(sig.substring(pos, pos
251: + sig_length));
252: if (name != null) {
253: print(name);
254: return pos + sig_length;
255: }
256: }
257: char c = sig.charAt(pos);
258: if (c != '(') {
259: print(c);
260: return pos + 1;
261: }
262: int nargs = 0;
263: pos++;
264: print(c);
265: for (;;) {
266: if (pos >= len) {
267: print("<truncated method signature>");
268: return pos;
269: }
270: c = sig.charAt(pos);
271: if (c == ')') {
272: pos++;
273: print(c);
274: break;
275: }
276: if (nargs++ > 0)
277: print(',');
278: pos = printSignature(sig, pos);
279: }
280: return printSignature(sig, pos);
281:
282: /*
283: char c = sig.charAt(pos);
284: Type type = Type.signatureToPrimitive(c);
285: if (type != null)
286: {
287: print(Type.getName());
288: return pos+1;
289: }
290: switch (c)
291: {
292: case 'L':
293: for (;;)
294: {
295: pos++;
296: if (pos >= len)
297: {
298: print("<truncated object signature>");
299: return pos;
300: }
301: c = sig.charAt(pos);
302: if (c == ';')
303: return pos+1;
304: print(c == '/' ? '.' : c);
305: }
306:
307: case '[':
308: pos = printSignature(sig, pos+1);
309: print("[]");
310: return pos;
311:
312: case '(':
313: int nargs = 0;
314: pos++;
315: print(c);
316: for (;;)
317: {
318: if (pos >= len)
319: {
320: print("<truncated method signature>");
321: return pos;
322: }
323: c = sig.charAt(pos);
324: if (c == ')')
325: {
326: pos++;
327: print(c);
328: break;
329: }
330: if (nargs > 0)
331: print(',');
332: pos = printSignature(sig, pos);
333: }
334: return printSignature(sig, pos);
335:
336: default: print(c); return pos+1;
337: }
338: */
339: }
340:
341: /** Print a signature string in Java source.
342: * @param sig the signature string to print */
343: public final void printSignature(String sig) {
344: int pos = printSignature(sig, 0);
345: int len = sig.length();
346: if (pos < len) {
347: print("<trailing junk:");
348: print(sig.substring(pos));
349: print('>');
350: }
351: }
352:
353: public final void printSignature(Type type) {
354: if (type == null)
355: print("<unknown type>");
356: else
357: printSignature(type.getSignature());
358: }
359: }
|