[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[dotgnu-pnet-commits] pnetlib ChangeLog runtime/System/Private/Debugg...
From: |
Radek Polak |
Subject: |
[dotgnu-pnet-commits] pnetlib ChangeLog runtime/System/Private/Debugg... |
Date: |
Fri, 09 Mar 2007 17:10:18 +0000 |
CVSROOT: /sources/dotgnu-pnet
Module name: pnetlib
Changes by: Radek Polak <radekp> 07/03/09 17:10:13
Modified files:
. : ChangeLog
Added files:
runtime/System/Private: DebuggerHelper.cs
Log message:
added private class DebuggerHelper that will be used by the debugger
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/pnetlib/ChangeLog?cvsroot=dotgnu-pnet&r1=1.2484&r2=1.2485
http://cvs.savannah.gnu.org/viewcvs/pnetlib/runtime/System/Private/DebuggerHelper.cs?cvsroot=dotgnu-pnet&rev=1.1
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/pnetlib/ChangeLog,v
retrieving revision 1.2484
retrieving revision 1.2485
diff -u -b -r1.2484 -r1.2485
--- ChangeLog 8 Mar 2007 19:04:44 -0000 1.2484
+++ ChangeLog 9 Mar 2007 17:10:13 -0000 1.2485
@@ -1,3 +1,8 @@
+2007-03-09 Radek Polak <address@hidden>
+
+ * runtime/System/Private/DebuggerHelper.cs: Managed helper class for
+ handling tasks, that are difficult to do in C.
+
2007-03-08 Klaus Treichel <address@hidden>
* tools/mkrelease: Fix the calls to libtoolize so that the libtool files
Index: runtime/System/Private/DebuggerHelper.cs
===================================================================
RCS file: runtime/System/Private/DebuggerHelper.cs
diff -N runtime/System/Private/DebuggerHelper.cs
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ runtime/System/Private/DebuggerHelper.cs 9 Mar 2007 17:10:13 -0000
1.1
@@ -0,0 +1,562 @@
+/*
+ * DebuggerHelper.cs - Managed support for debugger.
+ *
+ * Copyright (C) 2007 Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+namespace System.Private
+{
+using System.Text;
+using System.Collections;
+using System.Reflection;
+
+// This class is used internally by debugger.
+internal sealed class DebuggerHelper
+{
+ static LocalWatch locals;
+ static int maxItemsDumpCount = 16;
+ static Object error;
+
+ private DebuggerHelper()
+ {
+ }
+
+ // Return string representation of given object.
+ public static string ObjectToString(Object o)
+ {
+ if(o == null)
+ {
+ return "null";
+ }
+ try
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(o.ToString());
+ if(o is IEnumerable)
+ {
+
sb.Append(EnumerableToString((IEnumerable)(o)));
+ }
+ return sb.ToString();
+ }
+ catch(Exception ex)
+ {
+ return Error(ex.Message);
+ }
+ }
+
+ // Return value of given expression.
+ public static String ExpressionToString(String expression)
+ {
+ Object value = ExpressionNotFoundError();
+ try
+ {
+ if(expression == null)
+ {
+ return Error("null expression");
+ }
+
+ ExpressionParser parser = new
ExpressionParser(expression);
+ String name;
+ String[] args;
+
+ // Parse start of the expression.
+ if(!parser.Read(out name, out args))
+ {
+ return value.ToString();
+ }
+
+ // Check for constant
+ if(Char.IsDigit(name, 0))
+ {
+ return name;
+ }
+
+ // Find matching local
variable/function parameter
+ value = GetLocal(name);
+
+ // Call indexer if local variable found
+ // and arguments were specified
+ if(value != error)
+ {
+ if(args != null)
+ {
+ value =
GetNonStaticMemberValue(value,
+
"get_Item", args);
+ }
+ }
+ else
+ {
+ // Check for static member
+ Type matchingType =
FindType(name);
+
+ // Find matching static
field/method/property
+ if(matchingType != null)
+ {
+ parser.Read(out name,
out args);
+ value =
GetStaticMemberValue(matchingType,
+
name, args);
+ }
+ }
+
+ // Expression was not found
+ if(value == error)
+ {
+ return value.ToString();
+ }
+
+ // Iterate until the leftmost member
reference
+ while(parser.Read(out name, out args)
&& value != error)
+ {
+ value =
GetNonStaticMemberValue(value, name, args);
+ }
+
+ return ObjectToString(value);
+ }
+ catch(Exception ex)
+ {
+ return Error(ex.Message);
+ }
+ }
+
+ // Clear list of locals.
+ public static void ClearLocals()
+ {
+ locals = null;
+ }
+
+ // Add local variable or parameter to the list of locals.
+ public static void AddLocal(String name, Type type, Object value)
+ {
+ // Assign name if it is null
+ if(name == null)
+ {
+ int index =
LocalWatch.CountWatches(locals);
+ name = String.Format("var{0}", index);
+ }
+
+ // Create new watch and append it to the end of
the watch list.
+ LocalWatch watch = new LocalWatch(name, type,
value);
+ if(locals == null)
+ {
+ locals = watch;
+ }
+ else
+ {
+ locals.Append(watch);
+ }
+ }
+
+ // Helper function for show_locals command.
+ // If no error ocurred then result is xml string (first char is '<')
+ // otherwise the error message is returned.
+ public static String ShowLocals()
+ {
+ try
+ {
+ StringBuilder sb = new
StringBuilder("<LocalVariables>\n");
+ LocalWatch watch = locals;
+ while(watch != null)
+ {
+ sb.AppendFormat(
+@" <LocalVariable Name=""{0}"" Value=""{1}"">
+ <Type Name=""{2}"" />
+ </LocalVariable>
+",
+ watch.Name,
+
ObjectToString(watch.Value),
+ watch.Type.Name);
+
+ watch = watch.Next;
+ }
+ sb.Append("</LocalVariables>");
+ return sb.ToString();
+ }
+ catch(Exception ex)
+ {
+ return Error("unable to show locals, "
+ ex.Message);
+ }
+ }
+
+ // Return value of local variable with given name.
+ private static Object GetLocal(String name)
+ {
+ LocalWatch current = locals;
+ while(current != null)
+ {
+ if(current.Name == name)
+ {
+ return current.Value;
+ }
+ else
+ {
+ current = current.Next;
+ }
+ }
+ return ExpressionNotFoundError();
+ }
+
+ // Set current error and return it.
+ private static String Error(String message)
+ {
+ error = String.Format("error: {0}", message);
+ return (String) error;
+ }
+
+ // Set and returns "expression not found" error.
+ private static String ExpressionNotFoundError()
+ {
+ return Error("expression not found");
+ }
+
+ // Return info about enumerable object.
+ private static String EnumerableToString(IEnumerable o)
+ {
+ IEnumerator e = o.GetEnumerator();
+ int count = 0;
+ StringBuilder sb = new StringBuilder();
+
+ // Dump first elements
+ while(e.MoveNext())
+ {
+ if(count != 0)
+ {
+ sb.Append(", ");
+ }
+ count++;
+ sb.Append(e.Current);
+
+ // Display first 16 items at max.
+ if(count >= maxItemsDumpCount)
+ {
+ count = Int32.MaxValue;
+ break;
+ }
+ }
+
+ // Try to determine correct count
+ if(count == Int32.MaxValue && o is ICollection)
+ {
+ count = ((ICollection)(o)).Count;
+ }
+
+ // Dump information about count
+ if(count != Int32.MaxValue)
+ {
+ sb.Insert(0, "count=" + count + " | ");
+ }
+ sb.Insert(0, " | elements: ");
+
+ return sb.ToString();
+ }
+
+ // Create arguments from string values.
+ // Return null if something fails.
+ private static Object[] CreateArguments(ParameterInfo[] parameters,
+
String[] values)
+ {
+ if(values.Length != parameters.Length)
+ {
+ return null;
+ }
+ try
+ {
+ Object[] result = new
Object[parameters.Length];
+ for(int i = 0; i < result.Length; i++)
+ {
+ String arg =
ExpressionToString(values[i]);
+ result[i] =
Convert.ChangeType(arg,
+
parameters[i].ParameterType);
+ }
+ return result;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ // Find member with given name that can be called with given args.
+ // Output args can be used to make actual method or property call.
+ private static MemberInfo FindMember(Type type, Object obj,
+
String memberName, String[] args,
+
BindingFlags extraFlags,
+
out Object[] outArgs)
+ {
+ outArgs = null;
+ string suffix = "." + memberName;
+
+ foreach(MemberInfo mi in type.GetMembers(
+ extraFlags |
+ BindingFlags.Public |
+ BindingFlags.NonPublic))
+ {
+ if(mi.Name == memberName ||
mi.Name.EndsWith(suffix))
+ {
+ switch(mi.MemberType)
+ {
+ case MemberTypes.Field:
+ {
+ return mi;
+ }
+ case MemberTypes.Method:
+ case
MemberTypes.Property:
+ {
+ if(args != null)
+ {
+
ParameterInfo[] paramInfo;
+ if(mi
is PropertyInfo)
+ {
+
paramInfo = ((PropertyInfo)(mi)).GetIndexParameters();
+ }
+ else
+ {
+
paramInfo = ((MethodInfo)(mi)).GetParameters();
+ }
+ outArgs
= CreateArguments(paramInfo, args);
+ }
+ return mi;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ // Return member value as string.
+ // Call with obj=null and extraFlags=BindingFlags.Static for static
members
+ // Call with BindingFlags.Instance for instance members
+ private static Object GetMemberValue(Type type, Object obj,
+
String memberName, String[] args,
+
BindingFlags extraFlags)
+ {
+ Object[] outArgs;
+ MemberInfo mi = FindMember(type, obj,
memberName, args,
+
extraFlags, out outArgs);
+
+ if(mi is FieldInfo)
+ {
+ return ((FieldInfo)(mi)).GetValue(obj);
+ }
+ else if(mi is PropertyInfo)
+ {
+ return
((PropertyInfo)(mi)).GetValue(obj, outArgs);
+ }
+ else if(mi is MethodInfo)
+ {
+ return ((MethodInfo)(mi)).Invoke(obj,
outArgs);
+ }
+ else
+ {
+ return ExpressionNotFoundError();
+ }
+ }
+
+ // Return value of static member (field, property or method).
+ private static Object GetStaticMemberValue(Type type, String memberName,
+
String[] args)
+ {
+ return GetMemberValue(type, null, memberName,
args,
+
BindingFlags.Static);
+ }
+
+ // Return value of non static member (field, property or method).
+ private static Object GetNonStaticMemberValue(Object obj,
+
String memberName,
+
String[] args)
+ {
+ return GetMemberValue(obj.GetType(), obj,
memberName, args,
+
BindingFlags.Instance);
+ }
+
+ // Search assemblies in current app domain for type of given name.
+ private static Type FindType(String typeName)
+ {
+ foreach(Assembly assembly in
AppDomain.CurrentDomain.GetAssemblies())
+ {
+ foreach(Type type in
assembly.GetTypes())
+ {
+ if(type.Name == typeName)
+ {
+ return type;
+ }
+ }
+ }
+ return null;
+ }
+
+ // Simple parser for watched expressions.
+ private class ExpressionParser
+ {
+ private String expression;
+ private int index;
+
+ public ExpressionParser(String expression)
+ {
+ this.expression = expression;
+ this.index = 0;
+ }
+
+ // Read member name and arguments (if any)
+ // Returns false when end of expression is reached.
+ public bool Read(out String name, out String[] args)
+ {
+ name = null;
+ args = null;
+
+ // Bail out if whole expression is
processed
+ if(index >= expression.Length)
+ {
+ return false;
+ }
+
+ // Read name
+ StringBuilder sb = new StringBuilder();
+ for(; index < expression.Length;
index++)
+ {
+
if(Char.IsLetterOrDigit(expression, index))
+ {
+
sb.Append(expression[index]);
+ }
+ else
+ {
+ break;
+ }
+ }
+ name = sb.ToString();
+
+ // Move to next token
+ while(true)
+ {
+ if(index >= expression.Length)
+ {
+ return true;
+ }
+ if(expression[index] == '.')
+ {
+ index++;
+ return true;
+ }
+ if(expression[index] == '[' ||
+ expression[index] ==
'(')
+ {
+ index++;
+ break;
+ }
+ index++;
+ }
+
+ // Read arguments
+ ArrayList list = new ArrayList();
+ sb.Length = 0;
+ for(; index < expression.Length; index++)
+ {
+ char ch = expression[index];
+ if(ch == ')' || ch == ']')
+ {
+ list.Add(sb.ToString());
+ index++;
+ break;
+ }
+ if(ch == ',')
+ {
+ list.Add(sb.ToString());
+ sb.Length = 0;
+ }
+ sb.Append(ch);
+ }
+ args = (String[]) list.ToArray(typeof(String));
+ return true;
+ }
+ }
+
+ // Information about function parameter or local variable.
+ private class LocalWatch
+ {
+ private String name;
+ private Type type;
+ private Object value;
+ private LocalWatch next;
+
+ public LocalWatch(String name, Type type, Object value)
+ {
+ this.name = name;
+ this.type = type;
+ this.value = value;
+ }
+
+ public String Name
+ {
+ get
+ {
+ return name;
+ }
+ }
+
+ public Type Type
+ {
+ get
+ {
+ return type;
+ }
+ }
+
+ public Object Value
+ {
+ get
+ {
+ return value;
+ }
+ }
+
+ // Return next watch in this list or null.
+ public LocalWatch Next
+ {
+ get
+ {
+ return next;
+ }
+ }
+
+ // Append watch to the end of the list.
+ public void Append(LocalWatch watch)
+ {
+ LocalWatch tail = this;
+ while(tail.Next != null)
+ {
+ tail = tail.Next;
+ }
+ tail.next = watch;
+ }
+
+ // Return watch count in the watch list.
+ public static int CountWatches(LocalWatch watch)
+ {
+ int count = 0;
+ while(watch != null)
+ {
+ watch = watch.Next;
+ count++;
+ }
+ return count;
+ }
+
+ } // class LocalWatch
+
+}; // class DebuggerHelper
+
+}; // namespace System.Private
+
- [dotgnu-pnet-commits] pnetlib ChangeLog runtime/System/Private/Debugg...,
Radek Polak <=