mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Ide/Debuggers/Gdb_MI2 : completed type evaluators for string, vector and corresponding maps
git-svn-id: svn://ultimatepp.org/upp/trunk@6913 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
0fb78efebf
commit
2b09abdfa7
10 changed files with 636 additions and 232 deletions
|
|
@ -11,7 +11,9 @@ file
|
|||
Gdb.lay,
|
||||
MIValue.h,
|
||||
MIValue.cpp,
|
||||
TypeSimplify.h,
|
||||
TypeSimplify.cpp,
|
||||
UppSimplifiers.icpp,
|
||||
VarItem.cpp,
|
||||
Terminal.cpp,
|
||||
Disas.cpp,
|
||||
|
|
@ -19,6 +21,7 @@ file
|
|||
Gdb.cpp,
|
||||
Gdb_MI2.lay,
|
||||
Gdb_MI2.h,
|
||||
Gdb_MI2Eval.cpp,
|
||||
Gdb_MI2.cpp,
|
||||
PrettyPrinters.brc,
|
||||
PrettyPrinters.py,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ static VectorMap<String, String> DataMap2(const ArrayCtrl& data)
|
|||
{
|
||||
VectorMap<String, String> m;
|
||||
for(int i = 0; i < data.GetCount(); i++)
|
||||
m.Add(data.Get(i, 0), data.Get(i, 2));
|
||||
m.Add(data.Get(i, 0), data.Get(i, 1));
|
||||
return m;
|
||||
}
|
||||
|
||||
|
|
@ -20,10 +20,10 @@ static void MarkChanged2(const VectorMap<String, String>& m, ArrayCtrl& data)
|
|||
for(int i = 0; i < data.GetCount(); i++)
|
||||
{
|
||||
int q = m.Find(data.Get(i, 0));
|
||||
if(q >= 0 && m[q] != data.Get(i, 2))
|
||||
data.SetDisplay(i, 2, Single<RedDisplay>());
|
||||
if(q >= 0 && m[q] != data.Get(i, 1))
|
||||
data.SetDisplay(i, 1, Single<RedDisplay>());
|
||||
else
|
||||
data.SetDisplay(i, 2, StdDisplay());
|
||||
data.SetDisplay(i, 1, StdDisplay());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1108,145 +1108,11 @@ void Gdb_MI2::UpdateLocalVars(void)
|
|||
}
|
||||
}
|
||||
|
||||
// deeply explore a value
|
||||
// taking its members and skipping types
|
||||
// WARNING, it APPENDS results to given arrays
|
||||
void Gdb_MI2::ExploreValueDeep(String baseName, MIValue const &val, Vector<String> &fullNames, Vector<String> &values) const
|
||||
{
|
||||
// if value is a string, just append baseName and value to result
|
||||
if(val.IsString())
|
||||
{
|
||||
fullNames.Add(baseName);
|
||||
values.Add(val.ToString());
|
||||
}
|
||||
// otherwise, if value is a tuple, recursively add all subvalues
|
||||
else if(val.IsTuple())
|
||||
{
|
||||
for(int iVal = 0; iVal < val.GetCount(); iVal++)
|
||||
{
|
||||
String name = val.GetKey(iVal);
|
||||
if(!name.StartsWith("<"))
|
||||
name = baseName + '.' + name;
|
||||
else
|
||||
name = baseName;
|
||||
ExploreValueDeep(name, val.Get(iVal), fullNames, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update 'this' inspector data
|
||||
void Gdb_MI2::UpdateThis(void)
|
||||
{
|
||||
/*
|
||||
thisNames.Clear();
|
||||
thisExpressions.Clear();
|
||||
thisValues.Clear();
|
||||
|
||||
VarItem v = EvalGdb("*this");
|
||||
v.shortExpression = ".";
|
||||
|
||||
thisNames.Add(v.shortExpression);
|
||||
thisExpressions.Add(v.evaluableExpression);
|
||||
thisValues.Add(v.value);
|
||||
|
||||
Vector<VarItem> vv;
|
||||
if(v.kind == VarItem::SIMPLE)
|
||||
vv = GetChildren(v);
|
||||
else
|
||||
vv = GetChildren(v, 0, 10);
|
||||
|
||||
for(int iChild = 0; iChild < vv.GetCount(); iChild++)
|
||||
{
|
||||
VarItem &v = vv[iChild];
|
||||
thisNames.Add(v.shortExpression);
|
||||
thisExpressions.Add(v.evaluableExpression);
|
||||
thisValues.Add(v.value);
|
||||
}
|
||||
*/
|
||||
|
||||
thisNames.Clear();
|
||||
thisExpressions.Clear();
|
||||
thisValues.Clear();
|
||||
|
||||
Vector<String>names, values;
|
||||
|
||||
MIValue thisVal = MICmd("data-evaluate-expression *this");
|
||||
|
||||
if(!thisVal.IsTuple())
|
||||
return;
|
||||
if(thisVal.Find("value") >= 0)
|
||||
{
|
||||
// weird but the value is quoted, so must be parsed again...
|
||||
MIValue const &tup = thisVal.Get("value");
|
||||
if(!tup.IsString())
|
||||
return;
|
||||
MIValue s(tup.ToString());
|
||||
s.PackNames();
|
||||
//RLOG(s.Dump());
|
||||
TypeSimplify(s);
|
||||
ExploreValueDeep("", s, names, values);
|
||||
}
|
||||
else if(thisVal.Find("variables") >= 0)
|
||||
{
|
||||
MIValue &arr = thisVal.Get("variables");
|
||||
|
||||
if(!arr.IsArray())
|
||||
return;
|
||||
for(int iVal = 0; iVal < arr.GetCount(); iVal++)
|
||||
{
|
||||
MIValue &val = arr[iVal];
|
||||
if(!val.IsTuple() || val.Find("name") < 0 || val.Find("value") < 0)
|
||||
continue;
|
||||
MIValue &s = val.Get("value");
|
||||
s.PackNames();
|
||||
TypeSimplify(s);
|
||||
val.PackNames();
|
||||
ExploreValueDeep("." + val.Get("name").ToString(), s, thisExpressions, thisValues);
|
||||
}
|
||||
}
|
||||
|
||||
// build short names from full names
|
||||
for(int iName = 0; iName < thisExpressions.GetCount(); iName++)
|
||||
{
|
||||
String const &nam = thisExpressions[iName];
|
||||
String shortName;
|
||||
int pos = nam.ReverseFind('.');
|
||||
if(pos < 0)
|
||||
shortName = nam;
|
||||
else
|
||||
shortName = nam.Mid(pos + 1);
|
||||
thisNames.Add(shortName);
|
||||
}
|
||||
|
||||
// here the 'this' object is dumped inside the 2 vectors 'names' and 'values'
|
||||
// we need to do some cleanup, removing empty values, class names and so on
|
||||
// we shall also construct the 'thisNames' vector containing just the last name path
|
||||
// used for tooltip
|
||||
for(int iName = 0; iName < names.GetCount(); iName++)
|
||||
{
|
||||
String const &name = names[iName];
|
||||
if(name.IsEmpty())
|
||||
continue;
|
||||
if(name == "<No data fields>")
|
||||
continue;
|
||||
if(name.StartsWith("_vptr."))
|
||||
continue;
|
||||
|
||||
String const &val = values[iName];
|
||||
if(val.IsEmpty())
|
||||
continue;
|
||||
|
||||
String shortName;
|
||||
int dotPos = name.ReverseFind('.');
|
||||
if(dotPos < 0)
|
||||
shortName = name;
|
||||
else
|
||||
shortName = name.Mid(dotPos + 1);
|
||||
|
||||
thisNames.Add(shortName);
|
||||
thisExpressions.Add(name);
|
||||
thisValues.Add(val);
|
||||
}
|
||||
MIValue val = Evaluate("*this");
|
||||
CollectVariables(val, thisExpressions, thisValues, thisHints);
|
||||
}
|
||||
|
||||
// sync auto vars treectrl
|
||||
|
|
@ -1299,8 +1165,8 @@ void Gdb_MI2::SyncMembers(void)
|
|||
VectorMap<String, String> prev = DataMap2(members);
|
||||
members.Clear();
|
||||
|
||||
for(int iMem = 0; iMem < thisNames.GetCount(); iMem++)
|
||||
members.Add(thisExpressions[iMem], thisValues[iMem]);
|
||||
for(int iMem = 0; iMem < thisExpressions.GetCount(); iMem++)
|
||||
members.Add(thisExpressions[iMem].Mid(7), thisValues[iMem]);
|
||||
MarkChanged2(prev, members);
|
||||
}
|
||||
|
||||
|
|
@ -1639,6 +1505,12 @@ void Gdb_MI2::onExploreExpr(ArrayCtrl *what)
|
|||
// we use the expression editbox
|
||||
expr = ~explorerExprEdit;
|
||||
}
|
||||
else if(what == &members)
|
||||
{
|
||||
int line = what->GetCursor();
|
||||
if(line >= 0)
|
||||
expr = thisExpressions[line];
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, we use the expression from sending ArrayCtrl
|
||||
|
|
|
|||
|
|
@ -170,9 +170,9 @@ class Gdb_MI2 : public Debugger, public ParentCtrl
|
|||
Vector<String>watchesValues;
|
||||
|
||||
// 'this' variable inspection data
|
||||
Index<String>thisNames;
|
||||
Vector<String>thisExpressions;
|
||||
Vector<String>thisValues;
|
||||
Vector<int>thisHints;
|
||||
|
||||
// stored autos expressions, values and types
|
||||
String autoLine;
|
||||
|
|
@ -180,18 +180,7 @@ class Gdb_MI2 : public Debugger, public ParentCtrl
|
|||
// update local variables on demand
|
||||
void UpdateLocalVars(void);
|
||||
|
||||
// deeply explore a value
|
||||
// taking its members and skipping types
|
||||
// WARNING, it APPENDS results to given arrays
|
||||
void ExploreValueDeep(String baseName, MIValue const &val, Vector<String> &fullNames, Vector<String> &values) const;
|
||||
|
||||
// known types simplifier
|
||||
// takes a MIValue from '-data-evaluate-expression' command and try
|
||||
// do simplify diplay of known types
|
||||
void TypeSimplify(MIValue &val);
|
||||
|
||||
// update 'this' inspector data
|
||||
void UpdateThisDeep(VarItem &v);
|
||||
void UpdateThis(void);
|
||||
|
||||
// logs frame data on console
|
||||
|
|
@ -285,6 +274,16 @@ class Gdb_MI2 : public Debugger, public ParentCtrl
|
|||
String GetHostPath(const String& path) { return host->GetHostPath(path); }
|
||||
String GetLocalPath(const String& path) { return host->GetLocalPath(path); }
|
||||
|
||||
// known types simplifier
|
||||
// takes a MIValue from '-data-evaluate-expression' command and try
|
||||
// do simplify diplay of known types
|
||||
void TypeSimplify(MIValue &val);
|
||||
|
||||
// collects evaluated variables got with Evaluate
|
||||
// hints are used to choose the visualizer when deep-inspecting members
|
||||
// 0 for simple values, 1 for arrays, 2 for map
|
||||
void CollectVariables(MIValue &val, Vector<String> &exprs, Vector<String> &vals, Vector<int> &hints);
|
||||
|
||||
protected:
|
||||
|
||||
public :
|
||||
|
|
@ -306,6 +305,13 @@ class Gdb_MI2 : public Debugger, public ParentCtrl
|
|||
|
||||
Gdb_MI2();
|
||||
virtual ~Gdb_MI2();
|
||||
|
||||
|
||||
// variable inspection support
|
||||
// returns a MIValue with inspected data and some info fields added
|
||||
// and known types simplified and cathegorized
|
||||
// unknown and simple types are left as they are
|
||||
MIValue Evaluate(String expr);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
182
uppsrc/ide/Debuggers/Gdb_MI2Eval.cpp
Normal file
182
uppsrc/ide/Debuggers/Gdb_MI2Eval.cpp
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
#include "Debuggers.h"
|
||||
#include <ide/ide.h>
|
||||
|
||||
#include "TypeSimplify.h"
|
||||
|
||||
// now we scan the result and add some info
|
||||
// so, for example, if we find tuple like this one:
|
||||
// data = simplevalue
|
||||
// this will be modified as
|
||||
// data = { value = simplevalue, expr = evaluable_expression }
|
||||
// and for a complex value
|
||||
// data = { some=complex, not_simple=val }
|
||||
// woll be modified as
|
||||
// data = { <!value> = { some=complex, not_simple=val }, <!expr> = evaluable_expression }
|
||||
// More attributes will be added by type simplifier phase
|
||||
static void AddAttribs(String const &expr, MIValue &valExpr)
|
||||
{
|
||||
if(valExpr.IsTuple())
|
||||
{
|
||||
for(int i = 0; i < valExpr.GetCount(); i++)
|
||||
{
|
||||
String nam = valExpr.GetKey(i);
|
||||
String nExpr;
|
||||
if(!nam.StartsWith("<"))
|
||||
nExpr = expr + "." + nam;
|
||||
else
|
||||
nExpr = expr;
|
||||
MIValue v = valExpr[i];
|
||||
valExpr[i].Clear();
|
||||
valExpr[i].Add(SIMPLIFY_VALUE, v);
|
||||
valExpr[i].Add(SIMPLIFY_EXPR, nExpr);
|
||||
AddAttribs(nExpr, valExpr[i][SIMPLIFY_VALUE]);
|
||||
}
|
||||
}
|
||||
else if(valExpr.IsArray())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void Gdb_MI2::TypeSimplify(MIValue &val)
|
||||
{
|
||||
if(val.IsTuple())
|
||||
{
|
||||
for(int i = 0; i < val.GetCount(); i++)
|
||||
{
|
||||
// root of variable -- contains VALUE, EXPRESSION and will add HINTS
|
||||
MIValue &vRoot = val[i];
|
||||
|
||||
// value part of variable
|
||||
MIValue &v = vRoot[SIMPLIFY_VALUE];
|
||||
|
||||
if(v.IsTuple() && v.GetCount())
|
||||
{
|
||||
String key = v.GetKey(0);
|
||||
if(key.StartsWith("<!"))
|
||||
continue;
|
||||
if(key.StartsWith("<"))
|
||||
{
|
||||
TYPE_SIMPLIFIER_HANDLER handler = GetSimplifier(v.GetKey(0));
|
||||
if(handler)
|
||||
handler(*this, vRoot);
|
||||
else
|
||||
TypeSimplify(v);
|
||||
}
|
||||
else
|
||||
TypeSimplify(v);
|
||||
}
|
||||
else
|
||||
TypeSimplify(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// variable inspection support
|
||||
// returns a MIValue with inspected data and some info fields added
|
||||
// and known types simplified and cathegorized
|
||||
// unknown and simple types are left as they are
|
||||
MIValue Gdb_MI2::Evaluate(String expr)
|
||||
{
|
||||
// add parhentesis around expression... gdb is dumb
|
||||
expr = "(" + expr + ")";
|
||||
|
||||
// ask gdb to evaluate expression
|
||||
// and gather result in a tuple
|
||||
MIValue valExpr = MICmd("data-evaluate-expression " + expr);
|
||||
|
||||
// return empty value on error
|
||||
if(!valExpr.IsTuple())
|
||||
return MIValue();
|
||||
|
||||
if(valExpr.Find("value") >= 0)
|
||||
{
|
||||
// weird but the value is quoted, so must be parsed again...
|
||||
MIValue const &tup = valExpr.Get("value");
|
||||
if(!tup.IsString())
|
||||
return MIValue();
|
||||
String s = tup.ToString();
|
||||
MIValue parsed(s);
|
||||
|
||||
// enclose it in a dummy container
|
||||
MIValue enclosed;
|
||||
enclosed.Add("<DUMMY>", parsed);
|
||||
|
||||
// remove spaces from names
|
||||
enclosed.PackNames();
|
||||
|
||||
// Add attributes to expression data
|
||||
AddAttribs(expr, enclosed);
|
||||
|
||||
// now we go through the type simplifier, which try to give simple representation
|
||||
// for known types
|
||||
TypeSimplify(enclosed);
|
||||
|
||||
//RLOG(enclosed.Dump());
|
||||
|
||||
// now we can de-enclose it...
|
||||
parsed = enclosed["<DUMMY>"][SIMPLIFY_VALUE];
|
||||
|
||||
//RLOG(parsed.Dump());
|
||||
|
||||
// and finally return the cleaned evaluated data
|
||||
return parsed;
|
||||
}
|
||||
|
||||
else if(valExpr.Find("variables") >= 0)
|
||||
{
|
||||
RLOG("ARRAY SIDE UNHANDLED....");
|
||||
return MIValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
RLOG("WEIRD STUFF HERE....");
|
||||
return MIValue();
|
||||
}
|
||||
}
|
||||
|
||||
// collects evaluated variables got with Evaluate
|
||||
// hints are used to choose the visualizer when deep-inspecting members
|
||||
// 0 for simple values, 1 for arrays, 2 for map
|
||||
static void Collect0(MIValue &val, Vector<String> &exprs, Vector<String> &vals, Vector<int> &hints)
|
||||
{
|
||||
if(!val.IsTuple())
|
||||
return;
|
||||
|
||||
for(int i = 0; i < val.GetCount(); i++)
|
||||
{
|
||||
MIValue &v = val[i];
|
||||
MIValue &data = v[SIMPLIFY_VALUE];
|
||||
if(data.IsError())
|
||||
continue;
|
||||
if(data.IsString())
|
||||
{
|
||||
String d = data.ToString();
|
||||
if(!d.StartsWith("<"))
|
||||
{
|
||||
vals.Add(data.ToString()),
|
||||
exprs.Add(v[SIMPLIFY_EXPR]);
|
||||
String hint = v.Get(SIMPLIFY_HINT, SIMPLIFY_SIMPLE);
|
||||
if(hint == SIMPLIFY_SIMPLE)
|
||||
hints << 0;
|
||||
else if(hint == SIMPLIFY_ARRAY)
|
||||
hints << 1;
|
||||
else if(hint == SIMPLIFY_MAP)
|
||||
hints << 2;
|
||||
else
|
||||
hints << 0;
|
||||
}
|
||||
}
|
||||
else if(data.IsTuple())
|
||||
Collect0(data, exprs, vals, hints);
|
||||
}
|
||||
}
|
||||
|
||||
void Gdb_MI2::CollectVariables(MIValue &val, Vector<String> &exprs, Vector<String> &vals, Vector<int> &hints)
|
||||
{
|
||||
exprs.Clear();
|
||||
vals.Clear();
|
||||
hints.Clear();
|
||||
|
||||
Collect0(val, exprs, vals, hints);
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ int MIValue::ParseAngle(String const &s, int i)
|
|||
}
|
||||
i++;
|
||||
}
|
||||
if(!expect("ParseAngle", '"', i-1, s))
|
||||
if(!expect("ParseAngle", '>', i-1, s))
|
||||
return s.GetCount();
|
||||
string.Cat('>');
|
||||
|
||||
|
|
@ -638,3 +638,64 @@ void MIValue::PackNames(void)
|
|||
array[i].PackNames();
|
||||
}
|
||||
}
|
||||
|
||||
// add an item to a tuple
|
||||
MIValue &MIValue::Add(String const &key, MIValue pick_ &v)
|
||||
{
|
||||
if(IsEmpty())
|
||||
{
|
||||
Clear();
|
||||
type = MITuple;
|
||||
}
|
||||
if(type != MITuple)
|
||||
return ErrorMIValue("Not a Tuple value type");
|
||||
tuple.AddPick(key, v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MIValue &MIValue::Add(String const &key, String const &data)
|
||||
{
|
||||
MIValue v;
|
||||
v.Set(data);
|
||||
return Add(key, v);
|
||||
}
|
||||
|
||||
MIValue &MIValue::FindAdd(String const &key, String const &data)
|
||||
{
|
||||
if(IsEmpty())
|
||||
{
|
||||
Clear();
|
||||
type = MITuple;
|
||||
}
|
||||
if(type != MITuple)
|
||||
return ErrorMIValue("Not a Tuple value type");
|
||||
int idx = tuple.Find(key);
|
||||
MIValue v;
|
||||
v.Set(data);
|
||||
if(idx >= 0)
|
||||
tuple[idx] = v;
|
||||
else
|
||||
tuple.AddPick(key, v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// add an item to an array
|
||||
MIValue &MIValue::Add(MIValue pick_ &v)
|
||||
{
|
||||
if(IsEmpty())
|
||||
{
|
||||
Clear();
|
||||
type = MIArray;
|
||||
}
|
||||
if(type != MIArray)
|
||||
return ErrorMIValue("Not a Array value type");
|
||||
array.AddPick(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MIValue &MIValue::Add(String const &data)
|
||||
{
|
||||
MIValue v;
|
||||
v.Set(data);
|
||||
return Add(v);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,17 @@ class MIValue : public Moveable<MIValue>
|
|||
|
||||
// packs names inside tuples -- to make type recognition easy
|
||||
void PackNames(void);
|
||||
|
||||
// add some data to a value
|
||||
|
||||
// add an item to a tuple
|
||||
MIValue &Add(String const &key, MIValue pick_ &v);
|
||||
MIValue &Add(String const &key, String const &data);
|
||||
MIValue &FindAdd(String const &key, String const &data);
|
||||
|
||||
// add an item to an array
|
||||
MIValue &Add(MIValue pick_ &v);
|
||||
MIValue &Add(String const &data);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,86 +1,23 @@
|
|||
#include "Debuggers.h"
|
||||
#include <ide/ide.h>
|
||||
#include "TypeSimplify.h"
|
||||
|
||||
typedef bool (*TYPE_SIMPLIFIER_HANDLER)(MIValue &val);
|
||||
|
||||
static bool UppStringSimplify(MIValue &val)
|
||||
static VectorMap<String, TYPE_SIMPLIFIER_HANDLER> &GetSimplifierMap(void)
|
||||
{
|
||||
// strings are "easy", in debug mode 's' and 'len' members are provided
|
||||
// so we shall just look at them in tuple
|
||||
// see Upp::String code for how it works....
|
||||
try
|
||||
{
|
||||
MIValue &v = val[0][0][0];
|
||||
MIValue &unn = v[1];
|
||||
if(!v.IsTuple() || !unn.IsTuple())
|
||||
return false;
|
||||
|
||||
if(unn.Find("chr") < 0)
|
||||
return false;
|
||||
String chr = unn["chr"];
|
||||
bool isSmall = (chr[14] == 0);
|
||||
String s;
|
||||
if(isSmall)
|
||||
s = chr;
|
||||
else
|
||||
{
|
||||
if(unn.Find("ptr") < 0)
|
||||
return false;
|
||||
s = unn["ptr"];
|
||||
|
||||
// strip address...
|
||||
int i = s.Find('"');
|
||||
if(i >= 0)
|
||||
{
|
||||
s = s.Mid(i+1);
|
||||
s = s.Left(s.GetCount()-1);
|
||||
}
|
||||
}
|
||||
val.Set(s);
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static VectorMap<String, TYPE_SIMPLIFIER_HANDLER> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
struct TYPE_SIMPLIFIER
|
||||
void RegisterSimplifier(const char *pattern, TYPE_SIMPLIFIER_HANDLER handler)
|
||||
{
|
||||
const char *type;
|
||||
TYPE_SIMPLIFIER_HANDLER handler;
|
||||
GetSimplifierMap().Add(pattern, handler);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TYPE_SIMPLIFIER TYPE_SIMPLIFIERS[] =
|
||||
TYPE_SIMPLIFIER_HANDLER GetSimplifier(String const &pattern)
|
||||
{
|
||||
{ "<Upp::Moveable<Upp::String,Upp::AString<Upp::String0>>>", UppStringSimplify }
|
||||
};
|
||||
|
||||
#define SIMPLIFIERS_COUNT ((int)(sizeof(TYPE_SIMPLIFIERS) / sizeof(TYPE_SIMPLIFIER)))
|
||||
|
||||
void Gdb_MI2::TypeSimplify(MIValue &val)
|
||||
{
|
||||
static VectorMap<String, TYPE_SIMPLIFIER_HANDLER> handlers;
|
||||
if(!handlers.GetCount())
|
||||
for(int i = 0; i < SIMPLIFIERS_COUNT; i++)
|
||||
handlers.Add(TYPE_SIMPLIFIERS[i].type, TYPE_SIMPLIFIERS[i].handler);
|
||||
|
||||
if(val.IsTuple())
|
||||
VectorMap<String, TYPE_SIMPLIFIER_HANDLER> &map = GetSimplifierMap();
|
||||
for(int i = 0; i < map.GetCount(); i++)
|
||||
{
|
||||
for(int i = 0; i < val.GetCount(); i++)
|
||||
{
|
||||
MIValue &v = val[i];
|
||||
if(v.IsTuple() && v.GetCount())
|
||||
{
|
||||
int idx = handlers.Find(v.GetKey(0));
|
||||
if(idx >= 0)
|
||||
handlers[idx](v);
|
||||
else
|
||||
TypeSimplify(v);
|
||||
}
|
||||
else
|
||||
TypeSimplify(v);
|
||||
}
|
||||
if(pattern.StartsWith(map.GetKey(i)))
|
||||
return map[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
32
uppsrc/ide/Debuggers/TypeSimplify.h
Normal file
32
uppsrc/ide/Debuggers/TypeSimplify.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef _ide_Debuggers_TypeSimplify_h_
|
||||
#define _ide_Debuggers_TypeSimplify_h_
|
||||
|
||||
#include "Debuggers.h"
|
||||
#include <ide/ide.h>
|
||||
|
||||
#define SIMPLIFY_EXPR "<!EXPR>"
|
||||
#define SIMPLIFY_VALUE "<!VALUE>"
|
||||
#define SIMPLIFY_HINT "<!HINT>"
|
||||
#define SIMPLIFY_START "<!START>"
|
||||
#define SIMPLIFY_COUNT "<!COUNT>"
|
||||
|
||||
#define SIMPLIFY_SIMPLE "<!SIMPLE>"
|
||||
#define SIMPLIFY_ARRAY "<!ARRAY>"
|
||||
#define SIMPLIFY_MAP "<!MAP>"
|
||||
|
||||
// Simplifier handler
|
||||
// parameters:
|
||||
// gdb handler to debugger object -- used mostly to inspect deeper
|
||||
// expRoot gdb evaluable expression of 'val' expression root. The one used to get the 'val'.
|
||||
typedef bool (*TYPE_SIMPLIFIER_HANDLER)(Gdb_MI2 &gdb, MIValue &val);
|
||||
|
||||
void RegisterSimplifier(const char *pattern, TYPE_SIMPLIFIER_HANDLER handler);
|
||||
|
||||
TYPE_SIMPLIFIER_HANDLER GetSimplifier(String const &pattern);
|
||||
|
||||
#define REGISTERSIMPLIFIER(pattern, handler) \
|
||||
INITBLOCK { \
|
||||
RegisterSimplifier(pattern, handler); \
|
||||
}
|
||||
|
||||
#endif
|
||||
297
uppsrc/ide/Debuggers/UppSimplifiers.icpp
Normal file
297
uppsrc/ide/Debuggers/UppSimplifiers.icpp
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
#include "TypeSimplify.h"
|
||||
|
||||
static bool UppStringSimplify(Gdb_MI2 &gdb, MIValue &val)
|
||||
{
|
||||
|
||||
// strings are "easy", in debug mode 's' and 'len' members are provided
|
||||
// so we shall just look at them in tuple
|
||||
// see Upp::String code for how it works....
|
||||
try
|
||||
{
|
||||
MIValue &v = val[SIMPLIFY_VALUE][0][0][0][0][0][SIMPLIFY_VALUE];
|
||||
MIValue &unn = v[1][SIMPLIFY_VALUE];
|
||||
|
||||
if(!v.IsTuple() || !unn.IsTuple())
|
||||
return false;
|
||||
|
||||
if(unn.Find("chr") < 0)
|
||||
return false;
|
||||
String chr = unn["chr"][SIMPLIFY_VALUE];
|
||||
bool isSmall = (chr[14] == 0);
|
||||
String s;
|
||||
if(isSmall)
|
||||
s = chr;
|
||||
else
|
||||
{
|
||||
if(unn.Find("ptr") < 0)
|
||||
return false;
|
||||
s = unn["ptr"][SIMPLIFY_VALUE];
|
||||
|
||||
// strip address...
|
||||
int i = s.Find('"');
|
||||
if(i >= 0)
|
||||
{
|
||||
s = s.Mid(i+1);
|
||||
s = s.Left(s.GetCount()-1);
|
||||
}
|
||||
}
|
||||
val[SIMPLIFY_VALUE].Set("\"" + s + "\"");
|
||||
val.FindAdd(SIMPLIFY_HINT, SIMPLIFY_SIMPLE);
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool UppVectorSimplify(Gdb_MI2 &gdb, MIValue &val)
|
||||
{
|
||||
//RLOG(val.Dump());
|
||||
try
|
||||
{
|
||||
MIValue &v = val[SIMPLIFY_VALUE];
|
||||
String vectorExpr = v["vector"][SIMPLIFY_EXPR];
|
||||
int items = atoi(v["items"][SIMPLIFY_VALUE].ToString());
|
||||
|
||||
val.FindAdd(SIMPLIFY_HINT, SIMPLIFY_ARRAY);
|
||||
val.FindAdd(SIMPLIFY_START, "0");
|
||||
val.FindAdd(SIMPLIFY_COUNT, FormatInt(items));
|
||||
|
||||
// display max 5 elements of array, starting from 0 and ONLY if elements evaluate to a simple type
|
||||
// otherwise display {...} string
|
||||
// to do this, we shall ask gdb to evaluate the undelying vector
|
||||
int count = min(5, items);
|
||||
String vals = "";
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
MIValue vi = gdb.Evaluate(vectorExpr + Format("[%d]", i));
|
||||
if(vi.IsError())
|
||||
{
|
||||
vals = "can't evaluate";
|
||||
break;
|
||||
}
|
||||
if(!vi.IsString())
|
||||
{
|
||||
vals = "{...}";
|
||||
break;
|
||||
}
|
||||
vals = vals + ", " + vi.ToString();
|
||||
}
|
||||
if(vals.StartsWith(", "))
|
||||
vals = vals.Mid(2);
|
||||
vals = Format("Upp::Vector with %d elements : %s", items, vals);
|
||||
//RLOG("VALS = " << vals);
|
||||
val[SIMPLIFY_VALUE].Set(vals);
|
||||
|
||||
//RLOG(v.Dump());
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool UppVectorMapSimplify(Gdb_MI2 &gdb, MIValue &val)
|
||||
{
|
||||
//RLOG(val.Dump());
|
||||
try
|
||||
{
|
||||
MIValue &v = val[SIMPLIFY_VALUE];
|
||||
|
||||
MIValue &keyPtr = v[1][0]["key"][0][1][0][0][0];
|
||||
String keyExpr = keyPtr["vector"][SIMPLIFY_EXPR].ToString();
|
||||
int items = atoi(keyPtr["items"][SIMPLIFY_VALUE].ToString());
|
||||
|
||||
MIValue &valPtr = v[1][0]["value"][SIMPLIFY_VALUE];;
|
||||
String valExpr = valPtr["vector"][SIMPLIFY_EXPR].ToString();
|
||||
|
||||
val.FindAdd(SIMPLIFY_HINT, SIMPLIFY_MAP);
|
||||
val.FindAdd(SIMPLIFY_START, "0");
|
||||
val.FindAdd(SIMPLIFY_COUNT, FormatInt(items));
|
||||
|
||||
|
||||
// display max 3 elements of map, starting from 0 and ONLY if elements evaluate to a simple type
|
||||
// otherwise display {...} string
|
||||
// to do this, we shall ask gdb to evaluate the undelying vector
|
||||
int count = min(3, items);
|
||||
String vals = "";
|
||||
bool err = false;
|
||||
bool complex = false;
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
MIValue vk = gdb.Evaluate(keyExpr + Format("[%d]", i));
|
||||
if(vk.IsError())
|
||||
{
|
||||
err = true;
|
||||
break;
|
||||
}
|
||||
if(!vk.IsString())
|
||||
{
|
||||
complex = true;
|
||||
break;
|
||||
}
|
||||
MIValue vv = gdb.Evaluate(valExpr + Format("[%d]", i));
|
||||
if(vv.IsError())
|
||||
{
|
||||
err = true;
|
||||
break;
|
||||
}
|
||||
if(!vv.IsString())
|
||||
{
|
||||
complex = true;
|
||||
break;
|
||||
}
|
||||
vals = vals + ", (" + vk.ToString() + "," + vv.ToString() + ")";
|
||||
}
|
||||
|
||||
if(complex)
|
||||
vals = "{...}";
|
||||
else if(err)
|
||||
vals = "can't evaluate";
|
||||
if(vals.StartsWith(", "))
|
||||
vals = vals.Mid(2);
|
||||
vals = Format("Upp::VectorMap with %d elements : %s", items, vals);
|
||||
//RLOG("VALS = " << vals);
|
||||
val[SIMPLIFY_VALUE].Set(vals);
|
||||
return true;
|
||||
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool UppArraySimplify(Gdb_MI2 &gdb, MIValue &val)
|
||||
{
|
||||
//RLOG(val.Dump());
|
||||
try
|
||||
{
|
||||
MIValue &v = val[SIMPLIFY_VALUE]["vector"][SIMPLIFY_VALUE];
|
||||
|
||||
String vectorExpr = v["vector"][SIMPLIFY_EXPR];
|
||||
int items = atoi(v["items"][SIMPLIFY_VALUE].ToString());
|
||||
|
||||
val.FindAdd(SIMPLIFY_HINT, SIMPLIFY_ARRAY);
|
||||
val.FindAdd(SIMPLIFY_START, "0");
|
||||
val.FindAdd(SIMPLIFY_COUNT, FormatInt(items));
|
||||
|
||||
// display max 5 elements of array, starting from 0 and ONLY if elements evaluate to a simple type
|
||||
// otherwise display {...} string
|
||||
// to do this, we shall ask gdb to evaluate the undelying vector
|
||||
int count = min(5, items);
|
||||
String vals = "";
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
MIValue vi = gdb.Evaluate(vectorExpr + Format("[%d][0]", i));
|
||||
if(vi.IsError())
|
||||
{
|
||||
vals = "can't evaluate";
|
||||
break;
|
||||
}
|
||||
if(!vi.IsString())
|
||||
{
|
||||
vals = "{...}";
|
||||
break;
|
||||
}
|
||||
vals = vals + ", " + vi.ToString();
|
||||
}
|
||||
if(vals.StartsWith(", "))
|
||||
vals = vals.Mid(2);
|
||||
vals = Format("Upp::Array with %d elements : %s", items, vals);
|
||||
//RLOG("VALS = " << vals);
|
||||
val[SIMPLIFY_VALUE].Set(vals);
|
||||
|
||||
//RLOG(v.Dump());
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool UppArrayMapSimplify(Gdb_MI2 &gdb, MIValue &val)
|
||||
{
|
||||
//RLOG(val.Dump());
|
||||
try
|
||||
{
|
||||
MIValue &v = val[SIMPLIFY_VALUE];
|
||||
|
||||
MIValue &keyPtr = v[1][0]["key"][0][1][0][0][0];
|
||||
String keyExpr = keyPtr["vector"][SIMPLIFY_EXPR].ToString();
|
||||
int items = atoi(keyPtr["items"][SIMPLIFY_VALUE].ToString());
|
||||
|
||||
MIValue &valPtr = v[1][0]["value"][SIMPLIFY_VALUE];;
|
||||
String valExpr = valPtr["vector"][SIMPLIFY_VALUE]["vector"][SIMPLIFY_EXPR].ToString();
|
||||
|
||||
val.FindAdd(SIMPLIFY_HINT, SIMPLIFY_MAP);
|
||||
val.FindAdd(SIMPLIFY_START, "0");
|
||||
val.FindAdd(SIMPLIFY_COUNT, FormatInt(items));
|
||||
|
||||
|
||||
// display max 3 elements of map, starting from 0 and ONLY if elements evaluate to a simple type
|
||||
// otherwise display {...} string
|
||||
// to do this, we shall ask gdb to evaluate the undelying vector
|
||||
int count = min(3, items);
|
||||
String vals = "";
|
||||
bool err = false;
|
||||
bool complex = false;
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
MIValue vk = gdb.Evaluate(keyExpr + Format("[%d]", i));
|
||||
if(vk.IsError())
|
||||
{
|
||||
err = true;
|
||||
break;
|
||||
}
|
||||
if(!vk.IsString())
|
||||
{
|
||||
complex = true;
|
||||
break;
|
||||
}
|
||||
MIValue vv = gdb.Evaluate(valExpr + Format("[%d][0]", i));
|
||||
if(vv.IsError())
|
||||
{
|
||||
err = true;
|
||||
break;
|
||||
}
|
||||
if(!vv.IsString())
|
||||
{
|
||||
complex = true;
|
||||
break;
|
||||
}
|
||||
vals = vals + ", (" + vk.ToString() + "," + vv.ToString() + ")";
|
||||
}
|
||||
|
||||
if(complex)
|
||||
vals = "{...}";
|
||||
else if(err)
|
||||
vals = "can't evaluate";
|
||||
if(vals.StartsWith(", "))
|
||||
vals = vals.Mid(2);
|
||||
vals = Format("Upp::ArrayMap with %d elements : %s", items, vals);
|
||||
//RLOG("VALS = " << vals);
|
||||
val[SIMPLIFY_VALUE].Set(vals);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Register the simplifiers
|
||||
REGISTERSIMPLIFIER("<Upp::Moveable<Upp::String,Upp::AString<Upp::String0>>>" , UppStringSimplify);
|
||||
REGISTERSIMPLIFIER("<Upp::MoveableAndDeepCopyOption<Upp::Vector<" , UppVectorSimplify);
|
||||
REGISTERSIMPLIFIER("<Upp::MoveableAndDeepCopyOption<Upp::VectorMap<" , UppVectorMapSimplify);
|
||||
REGISTERSIMPLIFIER("<Upp::MoveableAndDeepCopyOption<Upp::Array<" , UppArraySimplify);
|
||||
REGISTERSIMPLIFIER("<Upp::MoveableAndDeepCopyOption<Upp::ArrayMap<" , UppArrayMapSimplify);
|
||||
|
||||
|
||||
|
|
@ -3,4 +3,7 @@
|
|||
#include "ide\Common/init"
|
||||
#include "plugin\ndisasm/init"
|
||||
#include "HexView/init"
|
||||
#define BLITZ_INDEX__ Fa2117e771964dad617cdd6a1792596ea
|
||||
#include "UppSimplifiers.icpp"
|
||||
#undef BLITZ_INDEX__
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue