4 // Lluis Sanchez Gual <lluis@novell.com>
6 // Copyright (c) 2008 Novell, Inc (http://www.novell.com)
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 using System
.Collections
.Generic
;
31 using System
.Diagnostics
;
32 using MD
= Mono
.Debugger
;
33 using SR
= System
.Reflection
;
34 using Mono
.Debugger
.Languages
;
35 using Mono
.Debugging
.Client
;
36 using Mono
.Debugging
.Backend
;
38 namespace DebuggerServer
40 public static class Util
42 public static ObjectValue
CreateObjectValue (EvaluationContext ctx
, IObjectValueSource source
, ObjectPath path
, TargetObject obj
, ObjectValueFlags flags
)
45 return CreateObjectValueImpl (ctx
, source
, path
, obj
, flags
);
46 } catch (Exception ex
) {
47 Console
.WriteLine (ex
);
48 return ObjectValue
.CreateError (path
.LastName
, ex
.Message
, flags
);
52 static ObjectValue
CreateObjectValueImpl (EvaluationContext ctx
, IObjectValueSource source
, ObjectPath path
, TargetObject obj
, ObjectValueFlags flags
)
54 obj
= ObjectUtil
.GetRealObject (ctx
, obj
);
57 return ObjectValue
.CreateObject (null, path
, "", null, flags
| ObjectValueFlags
.ReadOnly
, null);
59 if (obj
.HasAddress
&& obj
.GetAddress (ctx
.Thread
).IsNull
)
60 return ObjectValue
.CreateObject (null, path
, obj
.TypeName
, "(null)", flags
, null);
64 case TargetObjectKind
.Struct
:
65 case TargetObjectKind
.GenericInstance
:
66 case TargetObjectKind
.Class
:
67 TypeDisplayData tdata
= ObjectUtil
.GetTypeDisplayData (ctx
, obj
.Type
);
69 TargetStructObject co
= obj
as TargetStructObject
;
71 return ObjectValue
.CreateUnknown (path
.LastName
);
74 if (!string.IsNullOrEmpty (tdata
.ValueDisplayString
))
75 tvalue
= ObjectUtil
.EvaluateDisplayString (ctx
, co
, tdata
.ValueDisplayString
);
77 tvalue
= Server
.Instance
.Evaluator
.TargetObjectToExpression (ctx
, obj
);
80 if (!string.IsNullOrEmpty (tdata
.TypeDisplayString
))
81 tname
= ObjectUtil
.EvaluateDisplayString (ctx
, co
, tdata
.TypeDisplayString
);
85 ObjectValue val
= ObjectValue
.CreateObject (source
, path
, tname
, tvalue
, flags
, null);
86 if (!string.IsNullOrEmpty (tdata
.NameDisplayString
))
87 val
.Name
= ObjectUtil
.EvaluateDisplayString (ctx
, co
, tdata
.NameDisplayString
);
91 case TargetObjectKind
.Object
:
92 TargetObjectObject oob
= obj
as TargetObjectObject
;
94 return ObjectValue
.CreateUnknown (path
.LastName
);
96 return ObjectValue
.CreateObject (source
, path
, obj
.TypeName
, Server
.Instance
.Evaluator
.TargetObjectToExpression (ctx
, obj
), flags
, null);
98 case TargetObjectKind
.Array
:
99 return ObjectValue
.CreateObject (source
, path
, obj
.TypeName
, Server
.Instance
.Evaluator
.TargetObjectToExpression (ctx
, obj
), flags
, null);
101 case TargetObjectKind
.Fundamental
:
102 TargetFundamentalObject fob
= (TargetFundamentalObject
) obj
;
103 return ObjectValue
.CreatePrimitive (source
, path
, obj
.TypeName
, Server
.Instance
.Evaluator
.TargetObjectToExpression (ctx
, fob
), flags
);
105 case TargetObjectKind
.Enum
:
106 Console
.WriteLine ("pp ??? ENUM: " + obj
.GetType ());
107 TargetEnumObject enumobj
= (TargetEnumObject
) obj
;
108 return CreateObjectValue (ctx
, source
, path
, enumobj
.GetValue (ctx
.Thread
), flags
);
110 case TargetObjectKind
.Pointer
:
111 return ObjectValue
.CreateObject (source
, path
, obj
.TypeName
, Server
.Instance
.Evaluator
.TargetObjectToExpression (ctx
, obj
), flags
, null);
114 return ObjectValue
.CreateError (path
.LastName
, "Unknown value type: " + obj
.Kind
, flags
);
118 public static ObjectValue
[] GetObjectValueChildren (EvaluationContext ctx
, TargetObject obj
, int firstItemIndex
, int count
)
120 return GetObjectValueChildren (ctx
, obj
, firstItemIndex
, count
, true);
123 public static ObjectValue
[] GetObjectValueChildren (EvaluationContext ctx
, TargetObject obj
, int firstItemIndex
, int count
, bool dereferenceProxy
)
125 obj
= ObjectUtil
.GetRealObject (ctx
, obj
);
129 case MD
.Languages
.TargetObjectKind
.Array
: {
131 TargetArrayObject arr
= obj
as TargetArrayObject
;
133 return new ObjectValue
[0];
135 ArrayElementGroup agroup
= new ArrayElementGroup (ctx
, new ArrayAdaptor (ctx
, arr
));
136 return agroup
.GetChildren ();
138 case TargetObjectKind
.GenericInstance
:
139 case TargetObjectKind
.Struct
:
140 case TargetObjectKind
.Class
: {
141 // If there is a proxy, it has to show the members of the proxy
142 TargetObject proxy
= dereferenceProxy
? ObjectUtil
.GetProxyObject (ctx
, obj
) : obj
;
143 TargetStructObject co
= (TargetStructObject
) proxy
;
144 TypeDisplayData tdata
= ObjectUtil
.GetTypeDisplayData (ctx
, proxy
.Type
);
145 List
<ObjectValue
> values
= new List
<ObjectValue
> ();
146 ReqMemberAccess access
= tdata
.IsProxyType
? ReqMemberAccess
.Public
: ReqMemberAccess
.Auto
;
147 foreach (ValueReference val
in GetMembers (ctx
, co
.Type
, co
, access
)) {
149 DebuggerBrowsableState state
= tdata
.GetMemberBrowsableState (val
.Name
);
150 if (state
== DebuggerBrowsableState
.Never
)
153 if (state
== DebuggerBrowsableState
.RootHidden
) {
154 TargetObject ob
= val
.Value
;
156 values
.AddRange (Util
.GetObjectValueChildren (ctx
, ob
, -1, -1));
159 values
.Add (val
.CreateObjectValue (true));
162 } catch (Exception ex
) {
163 Server
.Instance
.WriteDebuggerError (ex
);
164 values
.Add (ObjectValue
.CreateError (null, new ObjectPath (val
.Name
), val
.Type
.Name
, ex
.Message
, val
.Flags
));
167 if (tdata
.IsProxyType
) {
168 values
.Add (RawViewSource
.CreateRawView (ctx
, obj
));
170 CollectionAdaptor col
= CollectionAdaptor
.CreateAdaptor (ctx
, co
);
172 ArrayElementGroup agroup
= new ArrayElementGroup (ctx
, col
);
173 ObjectValue val
= ObjectValue
.CreateObject (null, new ObjectPath ("Raw View"), "", "", ObjectValueFlags
.ReadOnly
, values
.ToArray ());
174 values
= new List
<ObjectValue
> ();
176 values
.AddRange (agroup
.GetChildren ());
179 return values
.ToArray ();
181 case TargetObjectKind
.Object
:
182 return new ObjectValue
[0];
184 case TargetObjectKind
.Pointer
:
185 TargetPointerObject pobj
= (TargetPointerObject
) obj
;
186 TargetObject defob
= pobj
.GetDereferencedObject (ctx
.Thread
);
187 LiteralValueReference pval
= new LiteralValueReference (ctx
, "*", defob
);
188 return new ObjectValue
[] {pval.CreateObjectValue () }
;
190 return new ObjectValue
[0];
195 public static object StringToObject (TargetType type
, string value)
197 TargetFundamentalType ftype
= type
as TargetFundamentalType
;
199 switch (ftype
.FundamentalKind
) {
200 case FundamentalKind
.Boolean
: return bool.Parse (value);
201 case FundamentalKind
.Byte
: return byte.Parse (value);
202 case FundamentalKind
.Char
: return char.Parse (value);
203 case FundamentalKind
.Double
: return double.Parse (value);
204 case FundamentalKind
.Int16
: return short.Parse (value);
205 case FundamentalKind
.Int32
: return int.Parse (value);
206 case FundamentalKind
.Int64
: return long.Parse (value);
207 case FundamentalKind
.IntPtr
: return new IntPtr (long.Parse (value));
208 case FundamentalKind
.SByte
: return sbyte.Parse (value);
209 case FundamentalKind
.Single
: return float.Parse (value);
210 case FundamentalKind
.String
: return value;
211 case FundamentalKind
.UInt16
: return ushort.Parse (value);
212 case FundamentalKind
.UInt32
: return uint.Parse (value);
213 case FundamentalKind
.UInt64
: return ulong.Parse (value);
214 case FundamentalKind
.UIntPtr
: return new UIntPtr (ulong.Parse (value));
217 throw new InvalidOperationException ("Value '" + value + "' can't be converted to type '" + type
.Name
+ "'");
220 public static IEnumerable
<ValueReference
> GetMembers (EvaluationContext ctx
, TargetType t
, TargetStructObject co
)
222 return GetMembers (ctx
, t
, co
, ReqMemberAccess
.Auto
);
225 public static IEnumerable
<ValueReference
> GetMembers (EvaluationContext ctx
, TargetType t
, TargetStructObject co
, ReqMemberAccess access
)
227 foreach (MemberReference mem
in ObjectUtil
.GetTypeMembers (ctx
, t
, co
==null, true, true, false, access
)) {
228 if (mem
.Member
is TargetFieldInfo
) {
229 TargetFieldInfo field
= (TargetFieldInfo
) mem
.Member
;
230 yield return new FieldReference (ctx
, co
, mem
.DeclaringType
, field
);
232 if (mem
.Member
is TargetPropertyInfo
) {
233 TargetPropertyInfo prop
= (TargetPropertyInfo
) mem
.Member
;
234 if (prop
.CanRead
&& (prop
.Getter
.ParameterTypes
== null || prop
.Getter
.ParameterTypes
.Length
== 0))
235 yield return new PropertyReference (ctx
, prop
, co
);
240 public static IEnumerable
<VariableReference
> GetLocalVariables (EvaluationContext ctx
)
242 foreach (TargetVariable
var in ctx
.Frame
.Method
.GetLocalVariables (ctx
.Thread
)) {
243 yield return new VariableReference (ctx
, var, ObjectValueFlags
.Variable
);
247 public static IEnumerable
<VariableReference
> GetParameters (EvaluationContext ctx
)
249 if (ctx
.Frame
.Method
!= null) {
250 foreach (TargetVariable
var in ctx
.Frame
.Method
.GetParameters (ctx
.Thread
))
251 yield return new VariableReference (ctx
, var, ObjectValueFlags
.Parameter
);
255 public static string UnscapeString (string text
)
257 StringBuilder sb
= new StringBuilder ();
258 for (int i
= 0; i
< text
.Length
; i
++) {
265 if (i
>= text
.Length
)
269 case '\\': c
= '\\'; break;
270 case 'a': c
= '\a'; break;
271 case 'b': c
= '\b'; break;
272 case 'f': c
= '\f'; break;
273 case 'v': c
= '\v'; break;
274 case 'n': c
= '\n'; break;
275 case 'r': c
= '\r'; break;
276 case 't': c
= '\t'; break;
277 default: return null;
281 return sb
.ToString ();
284 public static string EscapeString (string text
)
286 StringBuilder sb
= new StringBuilder ();
287 for (int i
= 0; i
< text
.Length
; i
++) {
291 case '\\': txt
= @"\\"; break;
292 case '\a': txt
= @"\a"; break;
293 case '\b': txt
= @"\b"; break;
294 case '\f': txt
= @"\f"; break;
295 case '\v': txt
= @"\v"; break;
296 case '\n': txt
= @"\n"; break;
297 case '\r': txt
= @"\r"; break;
298 case '\t': txt
= @"\t"; break;
305 return sb
.ToString ();
309 public enum ReqMemberAccess