Ide/Debuggers/Gdb_MI2 : massive cleanup and some bugfixes

git-svn-id: svn://ultimatepp.org/upp/trunk@4875 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
micio 2012-04-29 08:02:35 +00:00
parent 3d4369aa3d
commit 408688d24a
3 changed files with 411 additions and 372 deletions

View file

@ -10,7 +10,7 @@ void Gdb_MI2::DebugBar(Bar& bar)
{
bar.Add("Stop debugging", THISBACK(Stop)).Key(K_SHIFT_F5);
bar.Separator();
bar.Add("Asynchronous break", THISBACK(AsyncBrk));
bar.Add(!stopped, "Asynchronous break", THISBACK(AsyncBrk));
bool b = !IdeIsDebugLock();
bar.Add(b, "Step into", DbgImg::StepInto(), THISBACK1(Step, disas.HasFocus() ? "exec-step-instruction" : "exec-step")).Key(K_F11);
bar.Add(b, "Step over", DbgImg::StepOver(), THISBACK1(Step, disas.HasFocus() ? "exec-next-instruction" : "exec-next")).Key(K_F10);
@ -515,7 +515,6 @@ MIValue Gdb_MI2::MICmd(const char *cmdLine)
// is there and gives problems to MI interface. We shall maybe
// parse and store it somewhere
ReadGdb(false);
dbg->Write(String("-") + cmdLine + "\n");
return ReadGdb();
@ -729,7 +728,12 @@ void Gdb_MI2::CheckStopReason(void)
}
else
{
LogFrame(Format("Stopped, reason '%s'", reason), stopReason["frame"]);
// weird stop reasons (i.e., signals, segfaults... may not have a frame
// data inside
if(stopReason.Find("frame") < 0)
PutConsole(Format("Stopped, reason '%s'", reason));
else
LogFrame(Format("Stopped, reason '%s'", reason), stopReason["frame"]);
SyncIde();
}
}
@ -893,31 +897,23 @@ void Gdb_MI2::UpdateVars(void)
MIValue &updated = iUpdated["changelist"];
for(int iUpd = 0; iUpd < updated.GetCount(); iUpd++)
{
if(!updated[iUpd].IsTuple() || iUpdated.Find("name") < 0 || iUpdated.Find("value") < 0)
if(!updated[iUpd].IsTuple() || updated[iUpd].Find("name") < 0 || updated[iUpd].Find("value") < 0)
return;
String varName = updated[iUpd]["name"];
String value = updated[iUpd]["value"];
int iVar;
// local variables
if( (iVar = localVarNames.Find(varName)) >= 0)
{
if( updated[iUpd].Find("value") >= 0)
localVarValues[iVar] = updated[iUpd]["value"];
}
localVarValues[iVar] = value;
// watches
if( (iVar = watchesNames.Find(varName)) >= 0)
{
if( updated[iUpd].Find("value") >= 0)
watchesValues[iVar] = updated[iUpd]["value"];
}
watchesValues[iVar] = value;
// autos
if( (iVar = autosNames.Find(varName)) >= 0)
{
if( updated[iUpd].Find("value") >= 0)
autosValues[iVar] = updated[iUpd]["value"];
}
autosValues[iVar] = value;
}
}
@ -966,6 +962,7 @@ void Gdb_MI2::UpdateLocalVars(void)
// still not active; we just skip them
if(var.IsError() || var.IsEmpty())
continue;
localVarNames.Add(var["name"]);
localVarExpressions.Add(locIdx[iLoc]);
localVarTypes.Add(var["type"]);

View file

@ -1,355 +1,397 @@
#include "MIValue.h"
MIValue NullMIValue;
int MIValue::ParsePair(String &name, MIValue &val, String const &s, int i)
{
name.Clear();
val.Clear();
while(s[i] && (s[i] != '=') && s[i] != ']' && s[i] != '}')
name.Cat(s[i++]);
if(s[i] != '=')
return i;
i++;
switch(s[i])
{
case '"':
{
i = val.ParseString(s, i);
break;
}
break;
case '[':
i = val.ParseArray(s, i);
break;
case '{':
i = val.ParseTuple(s, i);
break;
default:
NEVER();
}
return i;
}
int MIValue::ParseTuple(String const &s, int i)
{
Clear();
type = MITuple;
// drop opening delimiter
ASSERT(s[i] == '{');
i++;
while(s[i] && s[i] != '}')
{
String name;
MIValue val;
i = ParsePair(name, val, s, i);
tuple.Add(name, val);
if(s[i] == '}')
break;
ASSERT(s[i] == ',');
i++;
}
return i + 1;
}
int MIValue::ParseArray(String const &s, int i)
{
Clear();
type = MIArray;
// drop opening delimiter
ASSERT(s[i] == '[');
i++;
while(s[i] && s[i] != ']')
{
String name;
MIValue val;
if(s[i] == '[')
i = val.ParseArray(s, i);
else if(s[i] == '{')
i = val.ParseTuple(s, i);
else if(s[i] == '"')
i = val.ParseString(s, i);
else
i = ParsePair(name, val, s, i);
array.Add(val);
if(s[i] == ']')
break;
ASSERT(s[i] == ',');
i++;
}
return i + 1;
}
int MIValue::ParseString(String const &s, int i)
{
Clear();
type = MIString;
char c;
ASSERT(s[i] == '"');
i++;
while( (c = s[i++]) != 0)
{
// verbatim if escaped
if(c == '\\')
string.Cat(s[i++]);
else if(c == '"')
break;
else
string.Cat(c);
}
ASSERT(c == '"');
return i;
}
int MIValue::Parse(String const &s, int i)
{
// if starts with '"', it's a string
// if starts with '[', it's an array
// if starts with '{', it's a tuple
// otherwise, it can be a sequence of pair name="value" which is stored like a tuple
// latter case is an example o bad design of MI interface....
Clear();
if(s[i] == '"')
return ParseString(s, i);
else if(s[i] == '[')
return ParseArray(s, i);
else if(s[i] == '{')
return ParseTuple(s, i);
else
{
String name;
MIValue val;
type = MITuple;
while(s[i])
{
i = ParsePair(name, val, s, i);
tuple.Add(name, val);
if(s[i] != ',')
break;
i++;
}
return i;
}
}
MIValue &MIValue::operator=(pick_ MIValue &v)
{
Clear();
type = v.type;
switch(type)
{
case MIString:
string = v.string;
break;
case MIArray:
array = v.array;
break;
case MITuple:
tuple = v.tuple;
break;
default:
NEVER();
}
return *this;
}
MIValue::MIValue()
{
Clear();
}
MIValue::MIValue(MIValue pick_ &v)
{
Clear();
type = v.type;
switch(type)
{
case MIString:
string = v.string;
break;
case MIArray:
array = v.array;
break;
case MITuple:
tuple = v.tuple;
break;
default:
NEVER();
}
}
MIValue::MIValue(String const &s)
{
Parse(s);
}
MIValue &MIValue::operator=(String const &s)
{
Parse(s);
return *this;
}
void MIValue::Clear()
{
type = MIString;
string = "";
array.Clear();
tuple.Clear();
}
// sets value to an error condition
MIValue &MIValue::SetError(String const &msg)
{
type = MIString;
string = "error:" + msg;
return *this;
}
// check if value contains an error
bool MIValue::IsError(void)
{
return type == MIString && string.StartsWith("error:");
}
// check for emptyness
bool MIValue::IsEmpty(void)
{
return type == MIString && string == "";
}
// simple accessors
int MIValue::GetCount(void) const
{
if(type == MIArray)
return array.GetCount();
else if(type == MITuple)
return tuple.GetCount();
else
NEVER();
return -1;
}
int MIValue::Find(const char *key) const
{
ASSERT(type == MITuple);
return tuple.Find(key);
}
MIValue &MIValue::Get(int i)
{
ASSERT(type == MIArray);
return array[i];
}
MIValue &MIValue::Get(const char *key)
{
ASSERT(type == MITuple);
return tuple.Get(key);
}
String &MIValue::Get(void)
{
ASSERT(type == MIString);
return string;
}
String const &MIValue::Get(void) const
{
ASSERT(type == MIString);
return string;
}
// tuple string member accessor with default value if not found
String MIValue::Get(const char *key, const char *def) const
{
ASSERT(type == MITuple);
int i = tuple.Find(key);
if(i >= 0)
{
ASSERT(tuple[i].type == MIString);
return tuple[i].Get();
}
else
return def;
}
// data dump
String MIValue::Dump(int level)
{
String spacer(' ', level);
switch(type)
{
case MIString:
return spacer + string;
case MITuple:
{
String s = spacer + "{\n";
level += 4;
spacer = String(' ', level);
for(int i = 0; i < tuple.GetCount(); i++)
{
String s1 = spacer + tuple.GetKey(i) + "=";
s += s1;
MIValue &val = tuple[i];
if(val.type == MIString)
s += val.Dump();
else
{
s += '\n' + val.Dump(level + 4);
s = s.Left(s.GetCount()-1);
}
if(i < tuple.GetCount() - 1)
s += ',';
s += '\n';
}
level -= 4;
spacer = String(' ', level);
s += spacer + "}\n";
return s;
}
case MIArray:
{
String s = spacer + "[ \n";
level += 4;
for(int i = 0; i < array.GetCount(); i++)
{
MIValue &val = array[i];
s += val.Dump(level);
if(val.type != MIString)
s = s.Left(s.GetCount()-1);
if(i < array.GetCount() - 1)
s += ',';
s += '\n';
}
s += spacer + "]\n";
return s;
}
default:
NEVER();
return "";
}
}
// finds breakpoint data given file and line
MIValue &MIValue::FindBreakpoint(String const &file, int line)
{
MIValue &body = Get("body");
body.AssertArray();
for(int i = 0; i < body.GetCount(); i++)
{
MIValue &bp = body[i];
bp.AssertTuple();
if(bp["file"] == file && atoi(bp["line"].Get()) == line)
return bp;
}
return NullMIValue;
}
#include "MIValue.h"
static MIValue &NullMIValue(void)
{
static MIValue v;
return v;
}
static MIValue &ErrorMIValue(String const &msg)
{
static MIValue v;
v.SetError(msg);
return v;
}
int MIValue::ParsePair(String &name, MIValue &val, String const &s, int i)
{
name.Clear();
val.Clear();
while(s[i] && (s[i] != '=') && s[i] != ']' && s[i] != '}')
name.Cat(s[i++]);
if(s[i] != '=')
return i;
i++;
switch(s[i])
{
case '"':
{
i = val.ParseString(s, i);
break;
}
break;
case '[':
i = val.ParseArray(s, i);
break;
case '{':
i = val.ParseTuple(s, i);
break;
default:
NEVER();
}
return i;
}
int MIValue::ParseTuple(String const &s, int i)
{
Clear();
type = MITuple;
// drop opening delimiter
if(s[i] != '{')
{
SetError(Format("Expected '{' at pos %d in '%s'", i, s));
return s.GetCount();
}
i++;
while(s[i] && s[i] != '}')
{
String name;
MIValue val;
i = ParsePair(name, val, s, i);
tuple.Add(name, val);
if(s[i] == '}')
break;
if(s[i] != ',')
{
SetError(Format("Expected ',' at pos %d in '%s'", i, s));
return s.GetCount();
}
i++;
}
return i + 1;
}
int MIValue::ParseArray(String const &s, int i)
{
Clear();
type = MIArray;
// drop opening delimiter
if(s[i] != '[')
{
SetError(Format("Expected '[' at pos %d in '%s'", i, s));
return s.GetCount();
}
i++;
while(s[i] && s[i] != ']')
{
String name;
MIValue val;
if(s[i] == '[')
i = val.ParseArray(s, i);
else if(s[i] == '{')
i = val.ParseTuple(s, i);
else if(s[i] == '"')
i = val.ParseString(s, i);
else
i = ParsePair(name, val, s, i);
array.Add(val);
if(s[i] == ']')
break;
if(s[i] != ',')
{
SetError(Format("Expected ',' at pos %d in '%s'", i, s));
return s.GetCount();
}
i++;
}
return i + 1;
}
int MIValue::ParseString(String const &s, int i)
{
Clear();
type = MIString;
char c;
if(s[i] != '"')
{
SetError(Format("Expected '\"' at pos %d in '%s'", i, s));
return s.GetCount();
}
i++;
while( (c = s[i++]) != 0)
{
// verbatim if escaped
if(c == '\\')
string.Cat(s[i++]);
else if(c == '"')
break;
else
string.Cat(c);
}
if(c != '"')
{
SetError(Format("Expected '\"' at pos %d in '%s'", i, s));
return s.GetCount();
}
return i;
}
int MIValue::Parse(String const &s, int i)
{
// if starts with '"', it's a string
// if starts with '[', it's an array
// if starts with '{', it's a tuple
// otherwise, it can be a sequence of pair name="value" which is stored like a tuple
// latter case is an example o bad design of MI interface....
Clear();
if(s[i] == '"')
return ParseString(s, i);
else if(s[i] == '[')
return ParseArray(s, i);
else if(s[i] == '{')
return ParseTuple(s, i);
else
{
String name;
MIValue val;
type = MITuple;
while(s[i])
{
i = ParsePair(name, val, s, i);
tuple.Add(name, val);
if(s[i] != ',')
break;
i++;
}
return i;
}
}
MIValue &MIValue::operator=(pick_ MIValue &v)
{
Clear();
type = v.type;
switch(type)
{
case MIString:
string = v.string;
break;
case MIArray:
array = v.array;
break;
case MITuple:
tuple = v.tuple;
break;
default:
SetError("Unknown MIValue type");
}
return *this;
}
MIValue::MIValue()
{
Clear();
}
MIValue::MIValue(MIValue pick_ &v)
{
Clear();
type = v.type;
switch(type)
{
case MIString:
string = v.string;
break;
case MIArray:
array = v.array;
break;
case MITuple:
tuple = v.tuple;
break;
default:
SetError("Unknown MIValue type");
}
}
MIValue::MIValue(String const &s)
{
Parse(s);
}
MIValue &MIValue::operator=(String const &s)
{
Parse(s);
return *this;
}
void MIValue::Clear()
{
type = MIString;
string = "";
array.Clear();
tuple.Clear();
}
// sets value to an error condition
MIValue &MIValue::SetError(String const &msg)
{
type = MIString;
string = "error:" + msg;
return *this;
}
// check if value contains an error
bool MIValue::IsError(void)
{
return type == MIString && string.StartsWith("error:");
}
// check for emptyness
bool MIValue::IsEmpty(void)
{
return type == MIString && string == "";
}
// simple accessors
int MIValue::GetCount(void) const
{
if(type == MIArray)
return array.GetCount();
else if(type == MITuple)
return tuple.GetCount();
else
return string.GetCount();
}
int MIValue::Find(const char *key) const
{
if(type != MITuple)
return -1;
return tuple.Find(key);
}
MIValue &MIValue::Get(int i)
{
if(type != MIArray)
return ErrorMIValue("Not an Array value type");
return array[i];
}
MIValue &MIValue::Get(const char *key)
{
if(type != MITuple)
return ErrorMIValue("Not a Tuple value type");
return tuple.Get(key);
}
String &MIValue::Get(void)
{
if(type != MIString)
return ErrorMIValue("Not a String value type");
return string;
}
String const &MIValue::Get(void) const
{
if(type != MIString)
return ErrorMIValue("Not a String value type");
return string;
}
// tuple string member accessor with default value if not found
String MIValue::Get(const char *key, const char *def) const
{
if(type != MITuple)
return def;
int i = tuple.Find(key);
if(i >= 0)
{
if(tuple[i].type != MIString)
return def;
return tuple[i].Get();
}
else
return def;
}
// data dump
String MIValue::Dump(int level)
{
String spacer(' ', level);
switch(type)
{
case MIString:
return spacer + string;
case MITuple:
{
String s = spacer + "{\n";
level += 4;
spacer = String(' ', level);
for(int i = 0; i < tuple.GetCount(); i++)
{
String s1 = spacer + tuple.GetKey(i) + "=";
s += s1;
MIValue &val = tuple[i];
if(val.type == MIString)
s += val.Dump();
else
{
s += '\n' + val.Dump(level + 4);
s = s.Left(s.GetCount()-1);
}
if(i < tuple.GetCount() - 1)
s += ',';
s += '\n';
}
level -= 4;
spacer = String(' ', level);
s += spacer + "}\n";
return s;
}
case MIArray:
{
String s = spacer + "[ \n";
level += 4;
for(int i = 0; i < array.GetCount(); i++)
{
MIValue &val = array[i];
s += val.Dump(level);
if(val.type != MIString)
s = s.Left(s.GetCount()-1);
if(i < array.GetCount() - 1)
s += ',';
s += '\n';
}
s += spacer + "]\n";
return s;
}
default:
return spacer + "*UNKNOWN MIVALUE TYPE*";
}
}
// finds breakpoint data given file and line
MIValue &MIValue::FindBreakpoint(String const &file, int line)
{
MIValue &body = Get("body");
if(body.IsError() || !body.IsArray())
return NullMIValue();
for(int i = 0; i < body.GetCount(); i++)
{
MIValue &bp = body[i];
if(bp.IsError() || !bp.IsTuple())
return NullMIValue();
if(bp["file"] == file && atoi(bp["line"].Get()) == line)
return bp;
}
return NullMIValue();
}

View file

@ -31,7 +31,7 @@ class UppStringPrinter(object):
if(IsSmall):
ptr = CHR
else:
ptr = self.val[ptr]
ptr = self.val['ptr']
return '"' + ptr.string() + '"'
def display_hint(self):