// (C) 2002 Jonathan Pryor
//
+//
+// 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.IO;
+using System.Collections;
using System.Diagnostics;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System.Diagnostics {
[ComVisible(false)]
public class DefaultTraceListener : TraceListener {
+ private static readonly bool OnWin32;
+
+ private const string ConsoleOutTrace = "Console.Out";
+ private const string ConsoleErrorTrace = "Console.Error";
+
+ private static readonly string MonoTracePrefix;
+ private static readonly string MonoTraceFile;
+
+ static DefaultTraceListener ()
+ {
+ // Determine what platform we're on. This impacts how where we send
+ // messages. On Win32 platforms (OnWin32 = true), we use the
+ // `OutputDebugString' api.
+ //
+ // On Linux platforms, we use MONO_TRACE_LISTENER to figure things out. See the
+ // API documentation for more information on MONO_TRACE_LISTENER.
+ OnWin32 = (Path.DirectorySeparatorChar == '\\');
+
+ if (!OnWin32) {
+#if TARGET_JVM
+ string trace = java.lang.System.getProperty("MONO_TRACE");
+#else
+ // If we're running on Unix, we don't have OutputDebugString.
+ // Instead, send output to...wherever the MONO_TRACE_LISTENER environment
+ // variables says to.
+ String trace = Environment.GetEnvironmentVariable("MONO_TRACE_LISTENER");
+#endif
+
+ if (trace != null) {
+ string file = null;
+ string prefix = null;
+
+ if (trace.StartsWith (ConsoleOutTrace)) {
+ file = ConsoleOutTrace;
+ prefix = GetPrefix (trace, ConsoleOutTrace);
+ }
+ else if (trace.StartsWith (ConsoleErrorTrace)) {
+ file = ConsoleErrorTrace;
+ prefix = GetPrefix (trace, ConsoleErrorTrace);
+ }
+ else {
+ file = trace;
+
+ // We can't firgure out what the prefix would be, as ':' is a
+ // valid filename character. Thus, arbitrary files don't support
+ // prefixes.
+ //
+ // I don't consider this to be a major issue. Prefixes are useful
+ // with Console.Out and Console.Error to help separate trace
+ // output from the actual program output. Writing to an arbitrary
+ // file doesn't introduce issues with disambiguation.
+ prefix = "";
+ }
+
+ MonoTraceFile = file;
+ MonoTracePrefix = prefix;
+ }
+ }
+ }
+
+ /**
+ * Get the prefix for the specified variable.
+ *
+ * "Prefixes" are used in the MONO_TRACE_LISTENER variable, and specify text that
+ * should precede each message printed to the console. The prefix is
+ * appended to the console location with a colon (':') separating them.
+ * For example, if MONO_TRACE_LISTENER is "Console.Out:** my prefix", the prefix is
+ * "** my prefix".
+ *
+ * Everything after the colon, if the colon is present, is used as the
+ * prefix.
+ *
+ * @param var The current MONO_TRACE_LISTENER variable
+ * @param target The name of the output location, e.g. "Console.Out"
+ */
+ private static string GetPrefix (string var, string target)
+ {
+ // actually, we permit any character to separate `target' and the prefix;
+ // we just skip over target the ':' would be. This means that a space or
+ // anything else would suffice, as long as it was only a single
+ // character.
+ if (var.Length > target.Length)
+ return var.Substring (target.Length + 1);
+ return "";
+ }
+
private string logFileName = null;
+ private bool assertUiEnabled = false;
+
public DefaultTraceListener () : base ("Default")
{
}
+ // It's hard to do anything with a UI when we don't have Windows.Forms...
[MonoTODO]
public bool AssertUiEnabled {
- get {return false;}
+ get {return assertUiEnabled;}
set {/* ignore */}
}
set {logFileName = value;}
}
- public override void Fail (string message)
- {
- base.Fail (message);
- WriteLine (new StackTrace().ToString());
- }
-
- public override void Fail(string message, string detailMessage)
- {
- base.Fail (message, detailMessage);
- WriteLine (new StackTrace().ToString());
- }
+ public override void Fail (string message)
+ {
+ base.Fail (message);
+ WriteLine (new StackTrace().ToString());
+ }
- #if USE_NATIVE_WIN32_OUTPUT_DEBUG_STRING
+ public override void Fail (string message, string detailMessage)
+ {
+ base.Fail (message, detailMessage);
+ WriteLine (new StackTrace().ToString());
+ }
- [DllImport ("kernel32.dll")]
- private extern static void OutputDebugString (string message);
+#if TARGET_JVM
+ private void WriteDebugString (string message)
+ {
+#else
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void WriteWindowsDebugString (string message);
- #else
+ private void WriteDebugString (string message)
+ {
+ if (OnWin32)
+ WriteWindowsDebugString (message);
+ else
+#endif
+ WriteMonoTrace (message);
+ }
- private static void OutputDebugString (string message)
- {
- Console.Write ("**ods** " + message);
- }
+ private void WriteMonoTrace (string message)
+ {
+ switch (MonoTraceFile) {
+ case ConsoleOutTrace:
+ Console.Out.Write (message);
+ break;
+ case ConsoleErrorTrace:
+ Console.Error.Write (message);
+ break;
+ default:
+ WriteLogFile (message, MonoTraceFile);
+ break;
+ }
+ }
- #endif
+ private void WritePrefix ()
+ {
+ if (!OnWin32) {
+ WriteMonoTrace (MonoTracePrefix);
+ }
+ }
private void WriteImpl (string message)
{
- if (NeedIndent)
+ if (NeedIndent) {
WriteIndent ();
+ WritePrefix ();
+ }
- OutputDebugString (message);
+ WriteDebugString (message);
if (Debugger.IsLogging())
Debugger.Log (0, null, message);
- WriteLogFile (message);
+ WriteLogFile (message, LogFileName);
}
- private void WriteLogFile (string message)
+ private void WriteLogFile (string message, string logFile)
{
- string fname = LogFileName;
+ string fname = logFile;
if (fname != null && fname.Length != 0) {
FileInfo info = new FileInfo (fname);
StreamWriter sw = null;
using (sw) {
sw.Write (message);
+ sw.Flush ();
}
}
}
{
string msg = message + Environment.NewLine;
WriteImpl (msg);
+
NeedIndent = true;
}
}