aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/lang/Throwable.java
blob: 9892dd2cae4f0117ea314400247cbe6b1b582ba3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Throwable.java - Superclass for all exceptions.

/* Copyright (C) 1998, 1999  Free Software Foundation

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

package java.lang;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.OutputStreamWriter;
import java.io.OutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;

/**
 * @author Tom Tromey <tromey@cygnus.com>
 * @date October 30, 1998 
 */

/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
 * "The Java Language Specification", ISBN 0-201-63451-1
 * Status: Sufficient for compiled code, but methods applicable to
 * bytecode not implemented.  JDK 1.1.
 */

/* A CPlusPlusDemangler sits on top of a PrintWriter.  All input is
 * passed through the "c++filt" program (part of GNU binutils) which
 * demangles internal symbols to their C++ source form.
 *
 * Closing a CPlusPlusDemangler doesn't close the underlying
 * PrintWriter; it does, however close underlying process and flush
 * all its buffers, so it's possible to guarantee that after a
 * CPlusPlusDemangler has been closed no more will ever be written to
 * the underlying PrintWriter.
 *
 * FIXME: This implictly converts data from the input stream, which is
 * a stream of characters, to a stream of bytes.  We need a way of
 * handling Unicode characters in demangled identifiers.  */

class CPlusPlusDemangler extends OutputStream
{
  java.io.OutputStream procOut;
  java.io.InputStream procIn;
  java.lang.Process proc;
  PrintWriter p;

  /* The number of bytes written to the underlying PrintWriter.  This
     provides a crude but fairly portable way to determine whether or
     not the attempt to exec c++filt worked. */  
  public int written = 0;

  CPlusPlusDemangler (PrintWriter writer) throws IOException
  {
    p = writer;
    proc = Runtime.getRuntime ().exec ("c++filt");
    procOut = proc.getOutputStream ();
    procIn = proc.getInputStream ();
  }

  public void write (int b) throws IOException
  {
    procOut.write (b);
    while (procIn.available () != 0)
      {
	int c = procIn.read ();
	if (c == -1)
	  break;
	else
	  {
	    p.write (c);
	    written++;
	  }
      }
  }
  
  public void close () throws IOException
  {
    procOut.close ();
    int c;
    while ((c = procIn.read ()) != -1)
      {
	p.write (c);
	written++;
      }
    p.flush ();
  }    
}

public class Throwable implements Serializable
{
  public native Throwable fillInStackTrace ();

  public String getLocalizedMessage ()
  {
    return getMessage ();
  }

  public String getMessage ()
  {
    return detailMessage;
  }

  public void printStackTrace ()
  {
    printStackTrace (System.err);
  }

  public void printStackTrace (PrintStream ps)
  {
    PrintWriter writer = new PrintWriter (ps);
    printStackTrace (writer);
  }

  public void printStackTrace (PrintWriter wr)
  {
    try
      {
	CPlusPlusDemangler cPlusPlusFilter = new CPlusPlusDemangler (wr);
	PrintWriter writer = new PrintWriter (cPlusPlusFilter);
	printRawStackTrace (writer);	
	writer.close ();
	if (cPlusPlusFilter.written == 0) // The demangler has failed...
	  printRawStackTrace (wr);
      }
    catch (Exception e1)
      {
	printRawStackTrace (wr);
      }
  }

  public Throwable ()
  {
    detailMessage = null;
    fillInStackTrace ();
  }

  public Throwable (String message)
  {
    detailMessage = message;
    fillInStackTrace ();
  }

  public String toString ()
  {
    return ((detailMessage == null)
	    ? getClass().getName()
	    : getClass().getName() + ": " + getMessage ());
  }

  private native final void printRawStackTrace (PrintWriter wr);
  
  // Name of this field comes from serialization spec.
  private String detailMessage;

  private byte stackTrace[];
}