//
// System.Diagnostics.StackTrace.cs
//
// Author:
// Alexander Klyubin (klyubin@aqris.com)
// Dietmar Maurer (dietmar@ximian.com)
//
// (C) 2001
//
//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Reflection;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Collections;
namespace System.Diagnostics {
///
/// Stack trace.
/// TODO: more information.
///
[Serializable]
[MonoTODO ("Fix serialization compatibility with MS.NET")]
public class StackTrace {
///
/// Uses a constant to define the number of methods that are
/// to be omitted from the stack trace.
///
public const int METHODS_TO_SKIP = 0;
///
/// Frames. First frame is the last stack frame pushed.
///
private StackFrame[] frames;
///
/// Initializes a new instance of the StackTrace class.
///
[MonoTODO]
public StackTrace() {
init_frames (METHODS_TO_SKIP, false);
}
///
/// Initializes a new instance of the StackTrace class.
///
///
/// TODO:
///
public StackTrace(bool needFileInfo) {
init_frames (METHODS_TO_SKIP, needFileInfo);
}
///
/// Initializes a new instance of the StackTrace class
/// from the current location, in a caller's frame.
///
///
/// The number of frames up the stack to start the trace
/// from.
///
public StackTrace(int skipFrames) {
init_frames (skipFrames, false);
}
///
/// Initializes a new instance of the StackTrace class
/// from the current location, in a caller's frame.
///
///
/// The number of frames up the stack to start the trace
/// from.
///
///
/// TODO:
///
public StackTrace(int skipFrames, bool needFileInfo) {
init_frames (skipFrames, needFileInfo);
}
void init_frames (int skipFrames, bool needFileInfo)
{
StackFrame sf;
ArrayList al = new ArrayList ();
skipFrames += 2;
while ((sf = new StackFrame (skipFrames, needFileInfo)) != null &&
sf.GetMethod () != null) {
al.Add (sf);
skipFrames++;
};
frames = (StackFrame [])al.ToArray (typeof (StackFrame));
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static StackFrame [] get_trace (Exception e, int skipFrames, bool needFileInfo);
///
/// Initializes a new instance of the StackTrace class.
///
///
/// TODO:
///
public StackTrace(Exception e) {
frames = get_trace (e, METHODS_TO_SKIP, false);
}
///
/// Initializes a new instance of the StackTrace class,
/// using the provided exception object. The resulting stack
/// trace describes the stack at the time of the exception.
///
///
/// TODO:
///
///
/// TODO:
///
public StackTrace(Exception e, bool needFileInfo) {
frames = get_trace (e, METHODS_TO_SKIP, needFileInfo);
}
///
/// Initializes a new instance of the StackTrace class,
/// using the provided exception object. The resulting stack
/// trace describes the stack at the time of the exception.
///
///
/// Exception.
///
///
/// The number of frames up the stack to start the trace
/// from.
///
public StackTrace(Exception e, int skipFrames) {
frames = get_trace (e, skipFrames, false);
}
///
/// Initializes a new instance of the StackTrace class,
/// using the provided exception object. The resulting stack
/// trace describes the stack at the time of the exception.
///
///
/// Exception.
///
///
/// The number of frames up the stack to start the trace
/// from.
///
///
/// TODO:
///
public StackTrace(Exception e, int skipFrames, bool needFileInfo) {
frames = get_trace (e, skipFrames, needFileInfo);
}
///
/// Initializes a new instance of the StackTrace class
/// containing a single frame.
///
///
/// The frame that the StackTrace object should contain.
///
public StackTrace(StackFrame frame) {
this.frames = new StackFrame[1];
this.frames[0] = frame;
}
///
/// Initializes a new instance of the StackTrace class.
///
///
/// TODO:
///
///
/// TODO:
///
[MonoTODO]
public StackTrace(Thread targetThread, bool needFileInfo) {
throw new NotImplementedException();
}
///
/// Holds the number of frames in the stack trace.
///
public virtual int FrameCount {
get {
return (frames == null) ? 0 : frames.Length;
}
}
///
/// Gets the specified stack frame.
///
///
/// The index of the stack frame requested.
///
///
/// The specified stack frame. Returns null
if
/// frame with specified index does not exist in this stack
/// trace.
///
///
/// Stack frames are numbered starting at zero, which is the
/// last stack frame pushed.
///
public virtual StackFrame GetFrame(int index) {
if ((index < 0) || (index >= FrameCount)) {
return null;
}
return frames[index];
}
///
/// Builds a readable representation of the stack trace.
///
///
/// A readable representation of the stack trace.
///
public override string ToString() {
string result = "";
for (int i = 0; i < FrameCount; i++) {
StackFrame frame = GetFrame(i);
result += "\n\tat " + FrameToString(frame);
}
return result;
}
//
// These are not on the Framework
//
#if false
public override bool Equals(Object obj) {
if ((obj == null) || (!(obj is StackTrace))) {
return false;
}
StackTrace rhs = (StackTrace) obj;
if (FrameCount != rhs.FrameCount) {
return false;
}
for (int i = 0; i < FrameCount; i++) {
if (!GetFrame(i).Equals(rhs.GetFrame(i))) {
return false;
}
}
return true;
}
public override int GetHashCode() {
return FrameCount;
}
#endif
///
/// Converts single stack frame to string to be used in
/// ToString method.
///
///
/// Frame to convert.
///
///
/// A readable representation of stack frame for using
/// ToString.
///
private static String FrameToString(StackFrame frame) {
MethodBase method = frame.GetMethod();
if (method != null) {
// Method information available
return method.DeclaringType.FullName
+ "." + method.Name + "()";
} else {
// Method information not available
return "";
}
}
}
}