/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.util;
import org.jikesrvm.VM;
import org.jikesrvm.classloader.Atom;
import org.jikesrvm.classloader.RVMClass;
import org.jikesrvm.classloader.RVMMember;
/**
* This interface is implemented by org.jikesrvm.PrintContainer. The
* interfaces is used by our java.lang.Throwable to print stack traces.
*/
@SuppressWarnings("unused")
// Suppress the unused import warning as per comment above
public abstract class PrintLN {
// PrintLN(PrintWriter out);
// PrintLN(PrintStream out);
public boolean isSysWrite() {
return false;
}
public boolean isSystemErr() {
return false;
}
public abstract void flush();
public abstract void println();
public void println(String s) {
print(s);
println();
}
public abstract void print(String s);
/* Here, we are writing code to make sure that we do not rely upon any
* external memory accesses. */
// largest power of 10 representable as a Java integer.
// (max int is 2147483647)
static final int max_int_pow10 = 1000000000;
public void print(int n) {
boolean suppress_leading_zero = true;
if (n == 0x80000000) {
print("-2147483648");
return;
} else if (n == 0) {
print('0');
return;
} else if (n < 0) {
print('-');
n = -n;
}
/* We now have a positive # of the proper range. Will need to exit from
the bottom of the loop. */
for (int p = max_int_pow10; p >= 1; p /= 10) {
int digit = n / p;
n -= digit * p;
if (digit == 0 && suppress_leading_zero) {
continue;
}
suppress_leading_zero = false;
char c = (char) ('0' + digit);
print(c);
}
}
public void printHex(int n) {
print("0x");
// print exactly 8 hexadec. digits.
for (int i = 32 - 4; i >= 0; i -= 4) {
int digit = (n >>> i) & 0x0000000F; // fill with 0 bits.
char c;
if (digit <= 9) {
c = (char) ('0' + digit);
} else {
c = (char) ('A' + (digit - 10));
}
print(c);
}
}
public abstract void print(char c);
// /** Print the name of the class to which the argument belongs.
// *
// * @param o Print the name of the class to which o belongs. */
// public void printClassName(Object o) {
// }
/** Print the name of the class represented by the class descriptor.
*
* @param descriptor The class descriptor whose name we'll print. */
public void printClassName(Atom descriptor) {
// toByteArray does not allocate; just returns an existing descriptor.
byte[] val = descriptor.toByteArray();
if (VM.VerifyAssertions) {
VM._assert(val[0] == 'L' && val[val.length - 1] == ';');
}
for (int i = 1; i < val.length - 1; ++i) {
char c = (char) val[i];
if (c == '/') {
print('.');
} else {
print(c);
}
}
// We could do this in an emergency. But we don't need to.
// print(descriptor);
}
/* Code related to Atom.classNameFromDescriptor() */
public void print(RVMClass class_) {
// getDescriptor() does no allocation.
Atom descriptor = class_.getDescriptor();
printClassName(descriptor);
}
// A kludgy alternative:
// public void print(RVMClass c) {
// Atom descriptor = c.getDescriptor();
// try {
// print(descriptor.classNameFromDescriptor());
// } catch(OutOfMemoryError e) {
// print(descriptor);
// }
// }
// No such method:
//public void print(RVMClass c) {
// VM.sysWrite(c);
// }
/* Here we need to imitate the work that would normally be done by
* RVMMember.toString() (which RVMMethod.toString() inherits) */
public void print(RVMMember m) {
print(m.getDeclaringClass()); // RVMClass
print('.');
print(m.getName());
print(' ');
print(m.getDescriptor());
}
public void print(Atom a) {
byte[] val;
if (a != null) {
val = a.toByteArray();
for (byte aVal : val) {
print((char) aVal);
}
} else {
print("(null)");
}
}
}