001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.util; 014 015import org.jikesrvm.VM; 016import org.jikesrvm.classloader.Atom; 017import org.jikesrvm.classloader.RVMClass; 018import org.jikesrvm.classloader.RVMMember; 019 020/** 021 * This interface is implemented by org.jikesrvm.PrintContainer. The 022 * interfaces is used by our java.lang.Throwable to print stack traces. 023 */ 024@SuppressWarnings("unused") 025// Suppress the unused import warning as per comment above 026public abstract class PrintLN { 027 // PrintLN(PrintWriter out); 028 // PrintLN(PrintStream out); 029 public boolean isSysWrite() { 030 return false; 031 } 032 033 public boolean isSystemErr() { 034 return false; 035 } 036 037 public abstract void flush(); 038 039 public abstract void println(); 040 041 public void println(String s) { 042 print(s); 043 println(); 044 } 045 046 public abstract void print(String s); 047 048 /* Here, we are writing code to make sure that we do not rely upon any 049 * external memory accesses. */ 050 // largest power of 10 representable as a Java integer. 051 // (max int is 2147483647) 052 static final int max_int_pow10 = 1000000000; 053 054 public void print(int n) { 055 boolean suppress_leading_zero = true; 056 if (n == 0x80000000) { 057 print("-2147483648"); 058 return; 059 } else if (n == 0) { 060 print('0'); 061 return; 062 } else if (n < 0) { 063 print('-'); 064 n = -n; 065 } 066 /* We now have a positive # of the proper range. Will need to exit from 067the bottom of the loop. */ 068 for (int p = max_int_pow10; p >= 1; p /= 10) { 069 int digit = n / p; 070 n -= digit * p; 071 if (digit == 0 && suppress_leading_zero) { 072 continue; 073 } 074 suppress_leading_zero = false; 075 char c = (char) ('0' + digit); 076 print(c); 077 } 078 } 079 080 public void printHex(int n) { 081 print("0x"); 082 // print exactly 8 hexadec. digits. 083 for (int i = 32 - 4; i >= 0; i -= 4) { 084 int digit = (n >>> i) & 0x0000000F; // fill with 0 bits. 085 char c; 086 087 if (digit <= 9) { 088 c = (char) ('0' + digit); 089 } else { 090 c = (char) ('A' + (digit - 10)); 091 } 092 print(c); 093 } 094 } 095 096 public abstract void print(char c); 097 098// /** Print the name of the class to which the argument belongs. 099// * 100// * @param o Print the name of the class to which o belongs. */ 101// public void printClassName(Object o) { 102 103// } 104 105 /** Print the name of the class represented by the class descriptor. 106 * 107 * @param descriptor The class descriptor whose name we'll print. */ 108 public void printClassName(Atom descriptor) { 109 // toByteArray does not allocate; just returns an existing descriptor. 110 byte[] val = descriptor.toByteArray(); 111 112 if (VM.VerifyAssertions) { 113 VM._assert(val[0] == 'L' && val[val.length - 1] == ';'); 114 } 115 for (int i = 1; i < val.length - 1; ++i) { 116 char c = (char) val[i]; 117 if (c == '/') { 118 print('.'); 119 } else { 120 print(c); 121 } 122 } 123 // We could do this in an emergency. But we don't need to. 124 // print(descriptor); 125 } 126 127 /* Code related to Atom.classNameFromDescriptor() */ 128 public void print(RVMClass class_) { 129 // getDescriptor() does no allocation. 130 Atom descriptor = class_.getDescriptor(); 131 printClassName(descriptor); 132 } 133 134 // A kludgy alternative: 135// public void print(RVMClass c) { 136// Atom descriptor = c.getDescriptor(); 137// try { 138// print(descriptor.classNameFromDescriptor()); 139// } catch(OutOfMemoryError e) { 140// print(descriptor); 141// } 142// } 143 144 // No such method: 145 //public void print(RVMClass c) { 146 // VM.sysWrite(c); 147 // } 148 149 /* Here we need to imitate the work that would normally be done by 150* RVMMember.toString() (which RVMMethod.toString() inherits) */ 151 152 public void print(RVMMember m) { 153 print(m.getDeclaringClass()); // RVMClass 154 print('.'); 155 print(m.getName()); 156 print(' '); 157 print(m.getDescriptor()); 158 } 159 160 public void print(Atom a) { 161 byte[] val; 162 if (a != null) { 163 val = a.toByteArray(); 164 for (byte aVal : val) { 165 print((char) aVal); 166 } 167 } else { 168 print("(null)"); 169 } 170 } 171} 172