From 408688d24aff662b3901dd367308f9c19fe682be Mon Sep 17 00:00:00 2001 From: micio Date: Sun, 29 Apr 2012 08:02:35 +0000 Subject: [PATCH] Ide/Debuggers/Gdb_MI2 : massive cleanup and some bugfixes git-svn-id: svn://ultimatepp.org/upp/trunk@4875 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/ide/Debuggers/Gdb_MI2.cpp | 29 +- uppsrc/ide/Debuggers/MIValue.cpp | 752 +++++++++++++------------ uppsrc/ide/Debuggers/PrettyPrinters.py | 2 +- 3 files changed, 411 insertions(+), 372 deletions(-) diff --git a/uppsrc/ide/Debuggers/Gdb_MI2.cpp b/uppsrc/ide/Debuggers/Gdb_MI2.cpp index bc39818b3..00cc779e7 100644 --- a/uppsrc/ide/Debuggers/Gdb_MI2.cpp +++ b/uppsrc/ide/Debuggers/Gdb_MI2.cpp @@ -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"]); diff --git a/uppsrc/ide/Debuggers/MIValue.cpp b/uppsrc/ide/Debuggers/MIValue.cpp index 587082864..1bf58ba20 100644 --- a/uppsrc/ide/Debuggers/MIValue.cpp +++ b/uppsrc/ide/Debuggers/MIValue.cpp @@ -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(); +} diff --git a/uppsrc/ide/Debuggers/PrettyPrinters.py b/uppsrc/ide/Debuggers/PrettyPrinters.py index 1c260dae6..9293eb142 100644 --- a/uppsrc/ide/Debuggers/PrettyPrinters.py +++ b/uppsrc/ide/Debuggers/PrettyPrinters.py @@ -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):