* Makefile.am:
[monodevelop.git] / extras / MonoDevelop.Debugger.Mdb / Mono.Debugging.Server.Mdb / Util.cs
blob155ac3dad5e4fda356638b2242a766dc260198a2
1 // Util.cs
2 //
3 // Author:
4 // Lluis Sanchez Gual <lluis@novell.com>
5 //
6 // Copyright (c) 2008 Novell, Inc (http://www.novell.com)
7 //
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
24 // THE SOFTWARE.
28 using System;
29 using System.Collections.Generic;
30 using System.Text;
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)
44 try {
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);
56 if (obj == null)
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);
62 switch (obj.Kind) {
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;
70 if (co == null)
71 return ObjectValue.CreateUnknown (path.LastName);
72 else {
73 string tvalue;
74 if (!string.IsNullOrEmpty (tdata.ValueDisplayString))
75 tvalue = ObjectUtil.EvaluateDisplayString (ctx, co, tdata.ValueDisplayString);
76 else
77 tvalue = Server.Instance.Evaluator.TargetObjectToExpression (ctx, obj);
79 string tname;
80 if (!string.IsNullOrEmpty (tdata.TypeDisplayString))
81 tname = ObjectUtil.EvaluateDisplayString (ctx, co, tdata.TypeDisplayString);
82 else
83 tname = obj.TypeName;
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);
88 return val;
91 case TargetObjectKind.Object:
92 TargetObjectObject oob = obj as TargetObjectObject;
93 if (oob == null)
94 return ObjectValue.CreateUnknown (path.LastName);
95 else
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);
113 default:
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);
127 switch (obj.Kind)
129 case MD.Languages.TargetObjectKind.Array: {
131 TargetArrayObject arr = obj as TargetArrayObject;
132 if (arr == null)
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)) {
148 try {
149 DebuggerBrowsableState state = tdata.GetMemberBrowsableState (val.Name);
150 if (state == DebuggerBrowsableState.Never)
151 continue;
153 if (state == DebuggerBrowsableState.RootHidden) {
154 TargetObject ob = val.Value;
155 if (ob != null)
156 values.AddRange (Util.GetObjectValueChildren (ctx, ob, -1, -1));
158 else {
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));
169 } else {
170 CollectionAdaptor col = CollectionAdaptor.CreateAdaptor (ctx, co);
171 if (col != null) {
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> ();
175 values.Add (val);
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 () };
189 default:
190 return new ObjectValue [0];
195 public static object StringToObject (TargetType type, string value)
197 TargetFundamentalType ftype = type as TargetFundamentalType;
198 if (ftype != null) {
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++) {
259 char c = text[i];
260 if (c != '\\') {
261 sb.Append (c);
262 continue;
264 i++;
265 if (i >= text.Length)
266 return null;
268 switch (text[i]) {
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;
279 sb.Append (c);
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++) {
288 char c = text[i];
289 string txt;
290 switch (c) {
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;
299 default:
300 sb.Append (c);
301 continue;
303 sb.Append (txt);
305 return sb.ToString ();
309 public enum ReqMemberAccess
311 All,
312 Auto,
313 Public