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