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