"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "kdbg/gdbdriver.cpp" between
kdbg-2.5.5.tar.gz and kdbg-2.5.6.tar.gz

About: KDbg is a graphical user interface to GDB, the GNU debugger (requires KDE, the K Desktop Environment).

gdbdriver.cpp  (kdbg-2.5.5):gdbdriver.cpp  (kdbg-2.5.6)
skipping to change at line 694 skipping to change at line 694
strncmp(output, "Cannot access memory at", 23) == 0 || strncmp(output, "Cannot access memory at", 23) == 0 ||
strncmp(output, "Attempt to dereference a generic pointer", 40) == 0 || strncmp(output, "Attempt to dereference a generic pointer", 40) == 0 ||
strncmp(output, "Attempt to take contents of ", 28) == 0 || strncmp(output, "Attempt to take contents of ", 28) == 0 ||
strncmp(output, "Attempt to use a type name as an expression", 43) == 0 | | strncmp(output, "Attempt to use a type name as an expression", 43) == 0 | |
strncmp(output, "There is no member or method named", 34) == 0 || strncmp(output, "There is no member or method named", 34) == 0 ||
strncmp(output, "A parse error in expression", 27) == 0 || strncmp(output, "A parse error in expression", 27) == 0 ||
strncmp(output, "No symbol \"", 11) == 0 || strncmp(output, "No symbol \"", 11) == 0 ||
strncmp(output, "Internal error: ", 16) == 0; strncmp(output, "Internal error: ", 16) == 0;
} }
static void skipSpace(const char*& p)
{
while (isspace(*p))
p++;
}
static void skipDecimal(const char*& p)
{
while (isdigit(*p))
p++;
}
/** /**
* Returns true if the output is an error message. If wantErrorValue is * Returns true if the output is an error message. If wantErrorValue is
* true, a new ExprValue object is created and filled with the error message. * true, a new ExprValue object is created and filled with the error message.
* If there are warnings, they are skipped and output points past the warnings * If there are warnings, they are skipped and output points past the warnings
* on return (even if there \e are errors). * on return (even if there \e are errors).
*/ */
static bool parseErrorMessage(const char*& output, static bool parseErrorMessage(const char*& output,
ExprValue*& variable, bool wantErrorValue) ExprValue*& variable, bool wantErrorValue)
{ {
while (isspace(*output)) skipSpace(output);
output++;
// skip warnings // skip warnings
while (strncmp(output, "warning:", 8) == 0) while (strncmp(output, "warning:", 8) == 0)
{ {
const char* end = strchr(output+8, '\n'); const char* end = strchr(output+8, '\n');
if (end == 0) if (end == 0)
output += strlen(output); output += strlen(output);
else else
output = end+1; output = end+1;
while (isspace(*output)) skipSpace(output);
output++;
} }
if (isErrorExpr(output)) if (isErrorExpr(output))
{ {
if (wantErrorValue) { if (wantErrorValue) {
// put the error message as value in the variable // put the error message as value in the variable
variable = new ExprValue(QString(), VarTree::NKplain); variable = new ExprValue(QString(), VarTree::NKplain);
const char* endMsg = strchr(output, '\n'); const char* endMsg = strchr(output, '\n');
if (endMsg == 0) if (endMsg == 0)
endMsg = output + strlen(output); endMsg = output + strlen(output);
skipping to change at line 762 skipping to change at line 772
} }
ExprValue* GdbDriver::parseQCharArray(const char* output, bool wantErrorValue, b ool qt3like) ExprValue* GdbDriver::parseQCharArray(const char* output, bool wantErrorValue, b ool qt3like)
{ {
ExprValue* variable = 0; ExprValue* variable = 0;
/* /*
* Parse off white space. gdb sometimes prints white space first if the * Parse off white space. gdb sometimes prints white space first if the
* printed array leaded to an error. * printed array leaded to an error.
*/ */
while (isspace(*output)) skipSpace(output);
output++;
// special case: empty string (0 repetitions) // special case: empty string (0 repetitions)
if (strncmp(output, "Invalid number 0 of repetitions", 31) == 0) if (strncmp(output, "Invalid number 0 of repetitions", 31) == 0)
{ {
variable = new ExprValue(QString(), VarTree::NKplain); variable = new ExprValue(QString(), VarTree::NKplain);
variable->m_value = "\"\""; variable->m_value = "\"\"";
return variable; return variable;
} }
// check for error conditions // check for error conditions
skipping to change at line 785 skipping to change at line 794
return variable; return variable;
// parse the array // parse the array
// find '=' // find '='
const char* p = output; const char* p = output;
p = strchr(p, '='); p = strchr(p, '=');
if (p == 0) { if (p == 0) {
goto error; goto error;
} }
// skip white space p++;
do { skipSpace(p);
p++;
} while (isspace(*p));
if (*p == '{') if (*p == '{')
{ {
// this is the real data // this is the real data
p++; /* skip '{' */ p++; /* skip '{' */
// parse the array // parse the array
QString result; QString result;
QString repeatCount; QString repeatCount;
enum { wasNothing, wasChar, wasRepeat } lastThing = wasNothing; enum { wasNothing, wasChar, wasRepeat } lastThing = wasNothing;
skipping to change at line 915 skipping to change at line 922
variable = new ExprValue(QString(), VarTree::NKplain); variable = new ExprValue(QString(), VarTree::NKplain);
variable->m_value = "internal parse error"; variable->m_value = "internal parse error";
} }
return variable; return variable;
} }
static ExprValue* parseVar(const char*& s) static ExprValue* parseVar(const char*& s)
{ {
const char* p = s; const char* p = s;
// skip whitespace skipSpace(p);
while (isspace(*p))
p++;
QString name; QString name;
VarTree::NameKind kind; VarTree::NameKind kind;
/* /*
* Detect anonymouse struct values: The 'name =' part is missing: * Detect anonymouse struct values: The 'name =' part is missing:
* s = { a = 1, { b = 2 }} * s = { a = 1, { b = 2 }}
* Note that this detection works only inside structs when the anonymous * Note that this detection works only inside structs when the anonymous
* struct is not the first member: * struct is not the first member:
* s = {{ a = 1 }, b = 2} * s = {{ a = 1 }, b = 2}
* This is misparsed (by parseNested()) because it is mistakenly * This is misparsed (by parseNested()) because it is mistakenly
skipping to change at line 943 skipping to change at line 948
name = i18n("<anonymous struct or union>"); name = i18n("<anonymous struct or union>");
kind = VarTree::NKanonymous; kind = VarTree::NKanonymous;
} }
else else
{ {
if (!parseName(p, name, kind)) { if (!parseName(p, name, kind)) {
return 0; return 0;
} }
// go for '=' // go for '='
while (isspace(*p)) skipSpace(p);
p++;
if (*p != '=') { if (*p != '=') {
TRACE("parse error: = not found after " + name); TRACE("parse error: = not found after " + name);
return 0; return 0;
} }
// skip the '=' and more whitespace // skip the '=' and more whitespace
p++; p++;
while (isspace(*p)) skipSpace(p);
p++;
} }
ExprValue* variable = new ExprValue(name, kind); ExprValue* variable = new ExprValue(name, kind);
if (!parseValue(p, variable)) { if (!parseValue(p, variable)) {
delete variable; delete variable;
return 0; return 0;
} }
s = p; s = p;
return variable; return variable;
skipping to change at line 1084 skipping to change at line 1087
} }
// closing quote // closing quote
p++; p++;
/* /*
* Strings can consist of several parts, some of which contain repeated * Strings can consist of several parts, some of which contain repeated
* characters. * characters.
*/ */
if (quote == '\'') { if (quote == '\'') {
// look ahaead for <repeats 123 times> // look ahaead for <repeats 123 times>
const char* q = p+1; const char* q = p+1;
while (isspace(*q)) skipSpace(q);
q++;
if (strncmp(q, "<repeats ", 9) == 0) { if (strncmp(q, "<repeats ", 9) == 0) {
p = q+9; p = q+9;
while (*p != '\0' && *p != '>') while (*p != '\0' && *p != '>')
p++; p++;
if (*p != '\0') { if (*p != '\0') {
p++; /* skip the '>' */ p++; /* skip the '>' */
} }
} }
} }
// Is the string continued? If so, there is no L in wchar_t strings // Is the string continued? If so, there is no L in wchar_t strings
if (*p == ',') if (*p == ',')
{ {
// look ahead for another quote // look ahead for another quote
const char* q = p+1; const char* q = p+1;
while (isspace(*q)) skipSpace(q);
q++;
if (*q == '"' || *q == '\'') { if (*q == '"' || *q == '\'') {
// yes! // yes!
p = q; p = q;
goto moreStrings; goto moreStrings;
} }
// some strings can end in <incomplete sequence ...> // some strings can end in <incomplete sequence ...>
if (strncmp(q, "<incomplete sequence", 20) == 0) if (strncmp(q, "<incomplete sequence", 20) == 0)
{ {
p = q+20; p = q+20;
skipping to change at line 1170 skipping to change at line 1171
continue; continue;
} }
p++; p++;
} }
if (nest > 0) { if (nest > 0) {
TRACE(QString().sprintf("parse error: mismatching %c%c at %-20.20s", open ing, closing, s)); TRACE(QString().sprintf("parse error: mismatching %c%c at %-20.20s", open ing, closing, s));
} }
s = p; s = p;
} }
inline void skipName(const char*& p) static void skipName(const char*& p)
{ {
// allow : (for enumeration values) and $ and . (for _vtbl.) // allow : (for enumeration values) and $ and . (for _vtbl.)
while (isalnum(*p) || *p == '_' || *p == ':' || *p == '$' || *p == '.') while (isalnum(*p) || *p == '_' || *p == ':' || *p == '$' || *p == '.')
p++; p++;
} }
static void skipFunctionName(const char*& p)
{
while (*p)
{
if (*p == '<') {
// skip template parameter list
skipNestedAngles(p);
} else if (*p == '(') {
// this skips "(anonymous namespace)" as well as the formal
// parameter list of the containing function if this is a member
// of a nested class
skipNestedWithString(p, '(', ')');
} else if (isalnum(*p) || *p == '_' || *p == ':') {
const char* start = p;
skipName(p);
// check for operator
if (p-start >= 8 &&
strncmp(p-8, "operator", 8) == 0 &&
// do not mistake this as the tail of some identifier
(p-start == 8 || !(isalnum(p[-9]) || p[-9] == '_')))
{
// skip forward until we find the opening parenthesis
// this catches both operator()(...) as well as
// type conversion operators, e.g.
// operator char const*() const
// operator void(*)()
while (*p && *p != '(')
p++;
}
} else if (strncmp(p, " const", 6) == 0 &&
// must not mistake "const" as the beginning of
// a subequent identifier
!isalnum(p[6]) && p[6] != '_') {
p += 6;
} else {
break;
}
}
}
static bool parseName(const char*& s, QString& name, VarTree::NameKind& kind) static bool parseName(const char*& s, QString& name, VarTree::NameKind& kind)
{ {
kind = VarTree::NKplain; kind = VarTree::NKplain;
const char* p = s; const char* p = s;
// examples of names: // examples of names:
// name // name
// <Object> // <Object>
// <string<a,b<c>,7> > // <string<a,b<c>,7> >
skipping to change at line 1205 skipping to change at line 1246
skipName(p); skipName(p);
if (p == s) { if (p == s) {
TRACE(QString().sprintf("parse error: not a name %-20.20s", s)); TRACE(QString().sprintf("parse error: not a name %-20.20s", s));
return false; return false;
} }
int len = p - s; int len = p - s;
if (len == 6 && strncmp(s, "static", 6) == 0) { if (len == 6 && strncmp(s, "static", 6) == 0) {
kind = VarTree::NKstatic; kind = VarTree::NKstatic;
// its a static variable, name comes now // its a static variable, name comes now
while (isspace(*p)) skipSpace(p);
p++;
s = p; s = p;
skipName(p); skipName(p);
if (p == s) { if (p == s) {
TRACE(QString().sprintf("parse error: not a name after static %-2 0.20s", s)); TRACE(QString().sprintf("parse error: not a name after static %-2 0.20s", s));
return false; return false;
} }
len = p - s; len = p - s;
} }
name = QString::fromLatin1(s, len); name = QString::fromLatin1(s, len);
} }
skipping to change at line 1240 skipping to change at line 1280
// {<data variable, no debug info>} // {<data variable, no debug info>}
// {<variable (not text or data), no debug info>} // {<variable (not text or data), no debug info>}
if (strncmp(s, "{<text variable, ", 17) == 0 || if (strncmp(s, "{<text variable, ", 17) == 0 ||
strncmp(s, "{<data variable, ", 17) == 0 || strncmp(s, "{<data variable, ", 17) == 0 ||
strncmp(s, "{<variable (not text or data), ", 31) == 0) strncmp(s, "{<variable (not text or data), ", 31) == 0)
{ {
const char* start = s; const char* start = s;
skipNested(s, '{', '}'); skipNested(s, '{', '}');
variable->m_value = QString::fromLatin1(start, s-start); variable->m_value = QString::fromLatin1(start, s-start);
variable->m_value += ' '; // add only a single space variable->m_value += ' '; // add only a single space
while (isspace(*s)) skipSpace(s);
s++;
goto repeat; goto repeat;
} }
else else
{ {
s++; s++;
if (!parseNested(s, variable)) { if (!parseNested(s, variable)) {
return false; return false;
} }
// must be the closing brace // must be the closing brace
if (*s != '}') { if (*s != '}') {
TRACE("parse error: missing } of " + variable->m_name); TRACE("parse error: missing } of " + variable->m_name);
return false; return false;
} }
s++; s++;
// final white space // final white space
while (isspace(*s)) skipSpace(s);
s++;
} }
} }
// Sometimes we find a warning; it ends at the next LF // Sometimes we find a warning; it ends at the next LF
else if (strncmp(s, "warning: ", 9) == 0) { else if (strncmp(s, "warning: ", 9) == 0) {
const char* end = strchr(s, '\n'); const char* end = strchr(s, '\n');
s = end ? end : s+strlen(s); s = end ? end : s+strlen(s);
// skip space at start of next line // skip space at start of next line
while (isspace(*s)) skipSpace(s);
s++;
goto repeat; goto repeat;
} else { } else {
// examples of leaf values (cannot be the empty string): // examples of leaf values (cannot be the empty string):
// 123 // 123
// -123 // -123
// 23.575e+37 // 23.575e+37
// 0x32a45 // 0x32a45
// @0x012ab4 // @0x012ab4
// (DwContentType&) @0x8123456: {...} // (DwContentType&) @0x8123456: {...}
// 0x32a45 "text" // 0x32a45 "text"
// 10 '\n' // 10 '\n'
// <optimized out> // <optimized out>
// 0x823abc <Array<int> virtual table> // 0x823abc <Array<int> virtual table>
// 0x40240f <globarstr> "test" // 0x40240f <globarstr> "test"
// (void (*)()) 0x8048480 <f(E *, char)> // (void (*)()) 0x8048480 <f(E *, char)>
// (E *) 0xbffff450 // (E *) 0xbffff450
// red // red
// &parseP (HTMLClueV *, char *) // &parseP (HTMLClueV *, char *)
// &virtual table offset 0, this adjustment 140737488346016
// &virtual Dl::operator char const*() const
// Variable "x" is not available. // Variable "x" is not available.
// The value of variable 'x' is distributed... // The value of variable 'x' is distributed...
// -nan(0xfffff081defa0) // -nan(0xfffff081defa0)
// @0x100400f08: <error reading variable>
// (void (Templated<double>::*)(Templated<double> * const)) 0x400d74 <Mo
stDerived::PrintV()>, this adjustment -16
const char*p = s; const char*p = s;
// check for type // check for type
QString type; QString type;
if (*p == '(') { if (*p == '(') {
skipNested(p, '(', ')'); skipNested(p, '(', ')');
while (isspace(*p)) skipSpace(p);
p++;
variable->m_value = QString::fromLatin1(s, p - s); variable->m_value = QString::fromLatin1(s, p - s);
} }
bool reference = false; bool reference = false;
if (*p == '@') { if (*p == '@') {
// skip reference marker // skip reference marker
p++; p++;
reference = true; reference = true;
} }
const char* start = p; const char* start = p;
skipping to change at line 1342 skipping to change at line 1382
if (*p == ':') { if (*p == ':') {
p++; p++;
} else { } else {
// Paranoia. (Can this happen, i.e. reference not followed by ':'?) // Paranoia. (Can this happen, i.e. reference not followed by ':'?)
reference = false; reference = false;
} }
} }
checkMultiPart = true; checkMultiPart = true;
} else if (isdigit(*p)) { } else if (isdigit(*p)) {
// parse decimal number, possibly a float // parse decimal number, possibly a float
while (isdigit(*p)) skipDecimal(p);
p++;
if (*p == '.') { /* TODO: obey i18n? */ if (*p == '.') { /* TODO: obey i18n? */
// In long arrays an integer may be followed by '...'. // In long arrays an integer may be followed by '...'.
// We test for this situation and don't gobble the '...'. // We test for this situation and don't gobble the '...'.
if (p[1] != '.' || p[0] != '.') { if (p[1] != '.' || p[0] != '.') {
// fractional part // fractional part
p++; p++;
while (isdigit(*p)) skipDecimal(p);
p++;
} }
} }
if (*p == 'e' || *p == 'E') { if (*p == 'e' || *p == 'E') {
p++; p++;
// exponent // exponent
if (*p == '-' || *p == '+') if (*p == '-' || *p == '+')
p++; p++;
while (isdigit(*p)) skipDecimal(p);
p++;
} }
// for char variables there is the char, eg. 10 '\n' // for char variables there is the char, eg. 10 '\n'
checkMultiPart = true; checkMultiPart = true;
} else if (*p == '<') { } else if (*p == '<') {
// e.g. <optimized out> // e.g. <optimized out>
skipNestedAngles(p); skipNestedAngles(p);
} else if (*p == '"' || *p == '\'') { } else if (*p == '"' || *p == '\'') {
// character may have multipart: '\000' <repeats 11 times> // character may have multipart: '\000' <repeats 11 times>
checkMultiPart = *p == '\''; checkMultiPart = *p == '\'';
// found a string // found a string
skipString(p); skipString(p);
} else if (*p == 'L' && (p[1] == '"' || p[1] == '\'')) { } else if (*p == 'L' && (p[1] == '"' || p[1] == '\'')) {
// ditto for wchar_t strings // ditto for wchar_t strings
checkMultiPart = p[1] == '\''; checkMultiPart = p[1] == '\'';
skipString(p); skipString(p);
} else if (*p == '&') { } else if (*p == '&') {
// function pointer
p++; p++;
skipName(p); if (strncmp(p, "virtual ", 8) == 0) {
while (isspace(*p)) { p += 8;
p++; if (strncmp(p, "table offset ", 13) == 0) {
} p += 13;
if (*p == '(') { skipDecimal(p);
skipNested(p, '(', ')'); checkMultiPart = true;
} else {
skipFunctionName(p);
}
} else {
// function pointer
skipName(p);
skipSpace(p);
if (*p == '(') {
skipNested(p, '(', ')');
}
} }
} else if (strncmp(p, "Variable \"", 10) == 0) { } else if (strncmp(p, "Variable \"", 10) == 0) {
// Variable "x" is not available. // Variable "x" is not available.
p += 10; // skip to " p += 10; // skip to "
skipName(p); skipName(p);
if (strncmp(p, "\" is not available.", 19) == 0) { if (strncmp(p, "\" is not available.", 19) == 0) {
p += 19; p += 19;
} }
} else if (strncmp(p, "The value of variable '", 23) == 0) { } else if (strncmp(p, "The value of variable '", 23) == 0) {
p += 23; p += 23;
skipping to change at line 1424 skipping to change at line 1470
} }
} }
variable->m_value += QString::fromLatin1(start, p - start); variable->m_value += QString::fromLatin1(start, p - start);
// remove line breaks from the value; this is ok since // remove line breaks from the value; this is ok since
// string values never contain a literal line break // string values never contain a literal line break
variable->m_value.replace('\n', ' '); variable->m_value.replace('\n', ' ');
while (checkMultiPart) { while (checkMultiPart) {
// white space // white space
while (isspace(*p)) skipSpace(p);
p++;
// may be followed by a string or <...> // may be followed by a string or <...>
// if this was a pointer with a string, // if this was a pointer with a string,
// reset that pointer flag since we have now a value // reset that pointer flag since we have now a value
start = p; start = p;
checkMultiPart = false; checkMultiPart = false;
if (*p == '"' || *p == '\'') { if (*p == '"' || *p == '\'') {
skipString(p); skipString(p);
variable->m_varKind = VarTree::VKsimple; variable->m_varKind = VarTree::VKsimple;
} else if (*p == 'L' && (p[1] == '"' || p[1] == '\'')) { } else if (*p == 'L' && (p[1] == '"' || p[1] == '\'')) {
skipString(p); // wchar_t string skipString(p); // wchar_t string
variable->m_varKind = VarTree::VKsimple; variable->m_varKind = VarTree::VKsimple;
} else if (*p == '<') { } else if (*p == '<') {
// if this value is part of an array, it might be followed // if this value is part of an array, it might be followed
// by <repeats 15 times>, which we don't skip here // by <repeats 15 times>, which we don't skip here
if (strncmp(p, "<repeats ", 9) != 0) { if (strncmp(p, "<repeats ", 9) == 0)
;
// sometimes, a reference is followed by an error message:
// @0x100400f08: <error reading variable>
// in this case, we do not skip the text here, but leave it
// for the subsequent parsing pass induced by the reference
else if (reference && strncmp(p, "<error reading", 14) == 0)
;
else {
skipNestedAngles(p); skipNestedAngles(p);
checkMultiPart = true; checkMultiPart = true;
} }
} else if (strncmp(p, ", this adjustment ", 18) == 0) {
// pointers-to-member are sometimes followed by
// a "this adjustment" hint
p += 18;
if (*p == '-')
p++;
skipDecimal(p);
// we know that this is not a dereferencable pointer
variable->m_varKind = VarTree::VKsimple;
++start; // skip ',', will be picked up below
} }
if (p != start) { if (p != start) {
// there is always a blank before the string, // there is always a blank before the string,
// which we will include in the final string value // which we will include in the final string value
variable->m_value += QString::fromLatin1(start-1, (p - start)+1); variable->m_value += QString::fromLatin1(start-1, (p - start)+1);
} }
} }
if (variable->m_value.length() == 0) { if (variable->m_value.length() == 0) {
TRACE("parse error: no value for " + variable->m_name); TRACE("parse error: no value for " + variable->m_name);
return false; return false;
} }
// final white space // final white space
while (isspace(*p)) skipSpace(p);
p++;
s = p; s = p;
/* /*
* If this was a reference, the value follows. It might even be a * If this was a reference, the value follows. It might even be a
* composite variable! * composite variable!
*/ */
if (reference) { if (reference) {
goto repeat; goto repeat;
} }
} }
return true; return true;
} }
static bool parseNested(const char*& s, ExprValue* variable) static bool parseNested(const char*& s, ExprValue* variable)
{ {
// could be a structure or an array // could be a structure or an array
while (isspace(*s)) skipSpace(s);
s++;
const char* p = s; const char* p = s;
bool isStruct = false; bool isStruct = false;
/* /*
* If there is a name followed by an = or an < -- which starts a type * If there is a name followed by an = or an < -- which starts a type
* name -- or "static", it is a structure * name -- or "static", it is a structure
*/ */
if (*p == '<' || *p == '}') { if (*p == '<' || *p == '}') {
isStruct = true; isStruct = true;
} else if (strncmp(p, "static ", 7) == 0) { } else if (strncmp(p, "static ", 7) == 0) {
isStruct = true; isStruct = true;
} else if (isalpha(*p) || *p == '_' || *p == '$') { } else if (isalpha(*p) || *p == '_' || *p == '$') {
// look ahead for a comma after the name // look ahead for a comma after the name
skipName(p); skipName(p);
while (isspace(*p)) skipSpace(p);
p++;
if (*p == '=') { if (*p == '=') {
isStruct = true; isStruct = true;
} }
p = s; /* rescan the name */ p = s; /* rescan the name */
} }
if (isStruct) { if (isStruct) {
if (!parseVarSeq(p, variable)) { if (!parseVarSeq(p, variable)) {
return false; return false;
} }
variable->m_varKind = VarTree::VKstruct; variable->m_varKind = VarTree::VKstruct;
skipping to change at line 1537 skipping to change at line 1597
break; break;
} }
var = parseVar(s); var = parseVar(s);
if (var == 0) if (var == 0)
break; /* syntax error */ break; /* syntax error */
variable->appendChild(var); variable->appendChild(var);
if (*s != ',') if (*s != ',')
break; break;
// skip the comma and whitespace // skip the comma and whitespace
s++; s++;
while (isspace(*s)) skipSpace(s);
s++;
} }
return var != 0; return var != 0;
} }
static bool parseValueSeq(const char*& s, ExprValue* variable) static bool parseValueSeq(const char*& s, ExprValue* variable)
{ {
// parse a comma-separated sequence of variables // parse a comma-separated sequence of variables
int index = 0; int index = 0;
bool good; bool good;
for (;;) { for (;;) {
skipping to change at line 1575 skipping to change at line 1634
return false; return false;
} }
TRACE(QString().sprintf("found <repeats %d times> in array", l)); TRACE(QString().sprintf("found <repeats %d times> in array", l));
// replace name and advance index // replace name and advance index
name.sprintf("[%d .. %d]", index, index+l-1); name.sprintf("[%d .. %d]", index, index+l-1);
var->m_name = name; var->m_name = name;
index += l; index += l;
// skip " times>" and space // skip " times>" and space
s = end+7; s = end+7;
// possible final space // possible final space
while (isspace(*s)) skipSpace(s);
s++;
} else { } else {
index++; index++;
} }
variable->appendChild(var); variable->appendChild(var);
// long arrays may be terminated by '...' // long arrays may be terminated by '...'
if (strncmp(s, "...", 3) == 0) { if (strncmp(s, "...", 3) == 0) {
s += 3; s += 3;
ExprValue* var = new ExprValue("...", VarTree::NKplain); ExprValue* var = new ExprValue("...", VarTree::NKplain);
var->m_value = i18n("<additional entries of the array suppressed>"); var->m_value = i18n("<additional entries of the array suppressed>");
variable->appendChild(var); variable->appendChild(var);
break; break;
} }
if (*s != ',') { if (*s != ',') {
break; break;
} }
// skip the comma and whitespace // skip the comma and whitespace
s++; s++;
while (isspace(*s)) skipSpace(s);
s++;
// sometimes there is a closing brace after a comma // sometimes there is a closing brace after a comma
// if (*s == '}') // if (*s == '}')
// break; // break;
} }
return true; return true;
} }
/** /**
* Parses a stack frame. * Parses a stack frame.
*/ */
skipping to change at line 1689 skipping to change at line 1746
/* /*
* Skip parameters. But notice that for complicated conversion * Skip parameters. But notice that for complicated conversion
* functions (eg. "operator int(**)()()", ie. convert to pointer to * functions (eg. "operator int(**)()()", ie. convert to pointer to
* pointer to function) as well as operator()(...) we have to skip * pointer to function) as well as operator()(...) we have to skip
* additional pairs of parentheses. Furthermore, recent gdbs write the * additional pairs of parentheses. Furthermore, recent gdbs write the
* demangled name followed by the arguments in a pair of parentheses, * demangled name followed by the arguments in a pair of parentheses,
* where the demangled name can end in "const". * where the demangled name can end in "const".
*/ */
do { do {
skipNestedWithString(p, '(', ')'); skipNestedWithString(p, '(', ')');
while (isspace(*p)) skipSpace(p);
p++;
// skip "const" // skip "const"
if (strncmp(p, "const", 5) == 0) { if (strncmp(p, "const", 5) == 0) {
p += 5; p += 5;
while (isspace(*p)) skipSpace(p);
p++;
} }
} while (*p == '('); } while (*p == '(');
// check for file position // check for file position
if (strncmp(p, "at ", 3) == 0) { if (strncmp(p, "at ", 3) == 0) {
p += 3; p += 3;
const char* fileStart = p; const char* fileStart = p;
// go for the end of the line // go for the end of the line
while (*p != '\0' && *p != '\n') while (*p != '\0' && *p != '\n')
p++; p++;
skipping to change at line 1789 skipping to change at line 1844
s++; /* skip the hash mark */ s++; /* skip the hash mark */
} else if (strncmp(s, "Breakpoint ", 11) == 0) { } else if (strncmp(s, "Breakpoint ", 11) == 0) {
if (!isdigit(s[11])) if (!isdigit(s[11]))
return false; return false;
s += 11; /* skip "Breakpoint" */ s += 11; /* skip "Breakpoint" */
} else } else
return false; return false;
// frame number // frame number
frameNo = atoi(s); frameNo = atoi(s);
while (isdigit(*s)) skipDecimal(s);
s++;
// space and comma // space and comma
while (isspace(*s) || *s == ',') while (isspace(*s) || *s == ',')
s++; s++;
parseFrameInfo(s, func, file, lineNo, address); parseFrameInfo(s, func, file, lineNo, address);
return true; return true;
} }
void GdbDriver::parseBackTrace(const char* output, std::list<StackFrame>& stack) void GdbDriver::parseBackTrace(const char* output, std::list<StackFrame>& stack)
{ {
QString func, file; QString func, file;
skipping to change at line 1848 skipping to change at line 1902
bp.id = strtol(p, &dummy, 10); /* don't care about overflows */ bp.id = strtol(p, &dummy, 10); /* don't care about overflows */
p = dummy; p = dummy;
// check for continued <MULTIPLE> breakpoint // check for continued <MULTIPLE> breakpoint
if (*p == '.' && isdigit(p[1])) if (*p == '.' && isdigit(p[1]))
{ {
// continuation: skip type and disposition // continuation: skip type and disposition
} }
else else
{ {
// get Type // get Type
while (isspace(*p)) skipSpace(p);
p++;
if (strncmp(p, "breakpoint", 10) == 0) { if (strncmp(p, "breakpoint", 10) == 0) {
p += 10; p += 10;
} else if (strncmp(p, "hw watchpoint", 13) == 0) { } else if (strncmp(p, "hw watchpoint", 13) == 0) {
bp.type = Breakpoint::watchpoint; bp.type = Breakpoint::watchpoint;
p += 13; p += 13;
} else if (strncmp(p, "watchpoint", 10) == 0) { } else if (strncmp(p, "watchpoint", 10) == 0) {
bp.type = Breakpoint::watchpoint; bp.type = Breakpoint::watchpoint;
p += 10; p += 10;
} }
while (isspace(*p)) skipSpace(p);
p++;
if (*p == '\0') if (*p == '\0')
break; break;
// get Disp // get Disp
bp.temporary = *p++ == 'd'; bp.temporary = *p++ == 'd';
} }
while (*p != '\0' && !isspace(*p)) /* "keep" or "del" */ while (*p != '\0' && !isspace(*p)) /* "keep" or "del" */
p++; p++;
while (isspace(*p)) skipSpace(p);
p++;
if (*p == '\0') if (*p == '\0')
break; break;
// get Enb // get Enb
bp.enabled = *p++ == 'y'; bp.enabled = *p++ == 'y';
while (*p != '\0' && !isspace(*p)) /* "y" or "n" */ while (*p != '\0' && !isspace(*p)) /* "y" or "n" */
p++; p++;
while (isspace(*p)) skipSpace(p);
p++;
if (*p == '\0') if (*p == '\0')
break; break;
// the address, if present // the address, if present
if (bp.type == Breakpoint::breakpoint && if (bp.type == Breakpoint::breakpoint &&
strncmp(p, "0x", 2) == 0) strncmp(p, "0x", 2) == 0)
{ {
const char* start = p; const char* start = p;
while (*p != '\0' && !isspace(*p)) while (*p != '\0' && !isspace(*p))
p++; p++;
bp.address = QString::fromLatin1(start, p-start); bp.address = QString::fromLatin1(start, p-start);
skipping to change at line 1908 skipping to change at line 1958
} else { } else {
// location of a <MULTIPLE> filled in from subsequent breakpoints // location of a <MULTIPLE> filled in from subsequent breakpoints
if (strncmp(p, "<MULTIPLE>", 10) != 0) if (strncmp(p, "<MULTIPLE>", 10) != 0)
bp.location = QString::fromLatin1(p, end-p).trimmed(); bp.location = QString::fromLatin1(p, end-p).trimmed();
p = end+1; /* skip over \n */ p = end+1; /* skip over \n */
} }
// may be continued in next line // may be continued in next line
while (isspace(*p)) { /* p points to beginning of line */ while (isspace(*p)) { /* p points to beginning of line */
// skip white space at beginning of line // skip white space at beginning of line
while (isspace(*p)) skipSpace(p);
p++;
// seek end of line // seek end of line
end = strchr(p, '\n'); end = strchr(p, '\n');
if (end == 0) if (end == 0)
end = p+strlen(p); end = p+strlen(p);
if (strncmp(p, "breakpoint already hit", 22) == 0) { if (strncmp(p, "breakpoint already hit", 22) == 0) {
// extract the hit count // extract the hit count
p += 22; p += 22;
bp.hitCount = strtol(p, &dummy, 10); bp.hitCount = strtol(p, &dummy, 10);
skipping to change at line 1973 skipping to change at line 2022
// no threads // no threads
return threads; return threads;
} }
bool newFormat = false; bool newFormat = false;
const char* p = output; const char* p = output;
while (*p != '\0') { while (*p != '\0') {
ThreadInfo thr; ThreadInfo thr;
// seach look for thread id, watching out for the focus indicator // seach look for thread id, watching out for the focus indicator
thr.hasFocus = false; thr.hasFocus = false;
while (isspace(*p)) /* may be \n from prev line: see "No stac skipSpace(p); /* may be \n from prev line: see "No stac
k" below */ k" below */
p++;
// recent GDBs write a header line; skip it // recent GDBs write a header line; skip it
if (threads.empty() && strncmp(p, "Id Target", 11) == 0) { if (threads.empty() && strncmp(p, "Id Target", 11) == 0) {
p = strchr(p, '\n'); p = strchr(p, '\n');
if (p == NULL) if (p == NULL)
break; break;
newFormat = true; newFormat = true;
continue; // next line please, '\n' is skipped above continue; // next line please, '\n' is skipped above
} }
skipping to change at line 2000 skipping to change at line 2048
const char* end; const char* end;
char *temp_end = NULL; /* we need a non-const 'end' for strtol to use...* / char *temp_end = NULL; /* we need a non-const 'end' for strtol to use...* /
thr.id = strtol(p, &temp_end, 10); thr.id = strtol(p, &temp_end, 10);
end = temp_end; end = temp_end;
if (p == end) { if (p == end) {
// syntax error: no number found; bail out // syntax error: no number found; bail out
return threads; return threads;
} }
p = end; p = end;
// skip space skipSpace(p);
while (isspace(*p))
p++;
/* /*
* Now follows the thread's SYSTAG. * Now follows the thread's SYSTAG.
*/ */
if (!newFormat) { if (!newFormat) {
// In the old format, it is terminated by two blanks. // In the old format, it is terminated by two blanks.
end = strstr(p, " "); end = strstr(p, " ");
if (end == 0) { if (end == 0) {
// syntax error; bail out // syntax error; bail out
return threads; return threads;
skipping to change at line 2044 skipping to change at line 2090
} else if (*end == '(') { } else if (*end == '(') {
skipNested(end, '(', ')'); skipNested(end, '(', ')');
n = 2; n = 2;
} else if (n < 2) { } else if (n < 2) {
while (*end && !isspace(*end)) while (*end && !isspace(*end))
++end; ++end;
++n; ++n;
} else { } else {
break; break;
} }
while (isspace(*end)) skipSpace(end);
++end;
} }
} }
thr.threadName = QString::fromLatin1(p, end-p).trimmed(); thr.threadName = QString::fromLatin1(p, end-p).trimmed();
p = end; p = end;
/* /*
* Now follows a standard stack frame. Sometimes, however, gdb * Now follows a standard stack frame. Sometimes, however, gdb
* catches a thread at an instant where it doesn't have a stack. * catches a thread at an instant where it doesn't have a stack.
*/ */
if (strncmp(p, "[No stack.]", 11) != 0) { if (strncmp(p, "[No stack.]", 11) != 0) {
skipping to change at line 2129 skipping to change at line 2174
/* /*
* Mostly, GDB responds with this syntax: * Mostly, GDB responds with this syntax:
* *
* Breakpoint 1 at 0x400b94: file multibrkpt.cpp, line 9. (2 locations) * Breakpoint 1 at 0x400b94: file multibrkpt.cpp, line 9. (2 locations)
* *
* but sometimes it uses this syntax: * but sometimes it uses this syntax:
* *
* Breakpoint 4 at 0x804f158: lotto739.cpp:95. (3 locations) * Breakpoint 4 at 0x804f158: lotto739.cpp:95. (3 locations)
*/ */
char* fileEnd, *numStart = 0; const char* fileEnd, *numStart = 0;
char* fileStart = strstr(p, "file "); const char* fileStart = strstr(p, "file ");
if (fileStart != 0) if (fileStart != 0)
{ {
fileStart += 5; fileStart += 5;
fileEnd = strstr(fileStart, ", line "); fileEnd = strstr(fileStart, ", line ");
if (fileEnd != 0) if (fileEnd != 0)
numStart = fileEnd + 7; numStart = fileEnd + 7;
} }
if (numStart == 0 && p[0] == ':' && p[1] == ' ') if (numStart == 0 && p[0] == ':' && p[1] == ' ')
{ {
fileStart = p+2; fileStart = p+2;
while (isspace(*fileStart)) skipSpace(fileStart);
++fileStart;
fileEnd = strchr(fileStart, ':'); fileEnd = strchr(fileStart, ':');
if (fileEnd != 0) if (fileEnd != 0)
numStart = fileEnd + 1; numStart = fileEnd + 1;
} }
if (numStart == 0) if (numStart == 0)
return !address.isEmpty(); /* parse error only if there's no address */ return !address.isEmpty(); /* parse error only if there's no address */
QString fileName = QString::fromLatin1(fileStart, fileEnd-fileStart); QString fileName = QString::fromLatin1(fileStart, fileEnd-fileStart);
int line = strtoul(numStart, &p, 10); int line = strtoul(numStart, &p, 10);
if (numStart == p) if (numStart == p)
skipping to change at line 2187 skipping to change at line 2231
void GdbDriver::parseLocals(const char* output, std::list<ExprValue*>& newVars) void GdbDriver::parseLocals(const char* output, std::list<ExprValue*>& newVars)
{ {
// check for possible error conditions // check for possible error conditions
if (strncmp(output, "No symbol table", 15) == 0) if (strncmp(output, "No symbol table", 15) == 0)
{ {
return; return;
} }
while (*output != '\0') { while (*output != '\0') {
while (isspace(*output)) skipSpace(output);
output++;
if (*output == '\0') if (*output == '\0')
break; break;
// skip occurrences of "No locals" and "No args" // skip occurrences of "No locals" and "No args"
if (strncmp(output, "No locals", 9) == 0 || if (strncmp(output, "No locals", 9) == 0 ||
strncmp(output, "No arguments", 12) == 0) strncmp(output, "No arguments", 12) == 0)
{ {
output = strchr(output, '\n'); output = strchr(output, '\n');
if (output == 0) { if (output == 0) {
break; break;
} }
skipping to change at line 2326 skipping to change at line 2369
// set message // set message
const char* endOfMessage = strchr(start, '\n'); const char* endOfMessage = strchr(start, '\n');
if (endOfMessage == 0) if (endOfMessage == 0)
endOfMessage = start + strlen(start); endOfMessage = start + strlen(start);
message = QString::fromLatin1(start, endOfMessage-start); message = QString::fromLatin1(start, endOfMessage-start);
} else if (strncmp(start, "[Inferior ", 10) == 0) { } else if (strncmp(start, "[Inferior ", 10) == 0) {
const char* p = start + 10; const char* p = start + 10;
// skip number and space // skip number and space
while (*p && !isspace(*p)) while (*p && !isspace(*p))
++p; ++p;
while (isspace(*p)) skipSpace(p);
++p;
if (*p == '(') { if (*p == '(') {
skipNested(p, '(', ')'); skipNested(p, '(', ')');
if (strncmp(p, " exited ", 8) == 0) { if (strncmp(p, " exited ", 8) == 0) {
flags &= ~SFprogramActive; flags &= ~SFprogramActive;
// set message // set message
const char* end = strchr(p, '\n'); const char* end = strchr(p, '\n');
if (end == 0) if (end == 0)
end = p + strlen(p); end = p + strlen(p);
// strip [] from the message // strip [] from the message
skipping to change at line 2387 skipping to change at line 2429
output++; /* skip '\n' */ output++; /* skip '\n' */
QString shlibName; QString shlibName;
while (*output != '\0') { while (*output != '\0') {
// format of a line is // format of a line is
// 0x404c5000 0x40580d90 Yes /lib/libc.so.5 // 0x404c5000 0x40580d90 Yes /lib/libc.so.5
// 3 blocks of non-space followed by space // 3 blocks of non-space followed by space
for (int i = 0; *output != '\0' && i < 3; i++) { for (int i = 0; *output != '\0' && i < 3; i++) {
while (*output != '\0' && !isspace(*output)) { /* non-space */ while (*output != '\0' && !isspace(*output)) { /* non-space */
output++; output++;
} }
while (isspace(*output)) { /* space */ skipSpace(output); /* space */
output++;
}
} }
if (*output == '\0') if (*output == '\0')
return shlibs; return shlibs;
const char* start = output; const char* start = output;
output = strchr(output, '\n'); output = strchr(output, '\n');
if (output == 0) if (output == 0)
output = start + strlen(start); output = start + strlen(start);
shlibName = QString::fromLatin1(start, output-start); shlibName = QString::fromLatin1(start, output-start);
if (*output != '\0') if (*output != '\0')
output++; output++;
skipping to change at line 2438 skipping to change at line 2478
std::list<RegisterInfo> regs; std::list<RegisterInfo> regs;
if (strncmp(output, "The program has no registers now", 32) == 0) { if (strncmp(output, "The program has no registers now", 32) == 0) {
return regs; return regs;
} }
// parse register values // parse register values
while (*output != '\0') while (*output != '\0')
{ {
RegisterInfo reg; RegisterInfo reg;
// skip space at the start of the line // skip space at the start of the line
while (isspace(*output)) skipSpace(output);
output++;
// register name // register name
const char* start = output; const char* start = output;
while (*output != '\0' && !isspace(*output)) while (*output != '\0' && !isspace(*output))
output++; output++;
if (*output == '\0') if (*output == '\0')
break; break;
reg.regName = QString::fromLatin1(start, output-start); reg.regName = QString::fromLatin1(start, output-start);
// skip space skipSpace(output);
while (isspace(*output))
output++;
QString value; QString value;
/* /*
* If we find a brace now, this is a vector register. We look for * If we find a brace now, this is a vector register. We look for
* the closing brace and treat the result as cooked value. * the closing brace and treat the result as cooked value.
*/ */
if (*output == '{') if (*output == '{')
{ {
start = output; start = output;
skipping to change at line 2703 skipping to change at line 2740
// the address // the address
while (*p != 0) { while (*p != 0) {
MemoryDump md; MemoryDump md;
const char* start = p; const char* start = p;
while (*p != '\0' && *p != ':' && !isspace(*p)) while (*p != '\0' && *p != ':' && !isspace(*p))
p++; p++;
md.address = QString::fromLatin1(start, p-start); md.address = QString::fromLatin1(start, p-start);
if (*p != ':') { if (*p != ':') {
// parse function offset // parse function offset
while (isspace(*p)) skipSpace(p);
p++;
start = p; start = p;
while (*p != '\0' && !(*p == ':' && isspace(p[1]))) while (*p != '\0' && !(*p == ':' && isspace(p[1])))
p++; p++;
md.address.fnoffs = QString::fromLatin1(start, p-start); md.address.fnoffs = QString::fromLatin1(start, p-start);
} }
if (*p == ':') if (*p == ':')
p++; p++;
// skip space; this may skip a new-line char! // skip space; this may skip a new-line char!
while (isspace(*p)) skipSpace(p);
p++;
// everything to the end of the line is the memory dump // everything to the end of the line is the memory dump
const char* end = strchr(p, '\n'); const char* end = strchr(p, '\n');
if (end != 0) { if (end != 0) {
md.dump = QString::fromLatin1(p, end-p); md.dump = QString::fromLatin1(p, end-p);
p = end+1; p = end+1;
} else { } else {
md.dump = QString::fromLatin1(p, strlen(p)); md.dump = QString::fromLatin1(p, strlen(p));
p += strlen(p); p += strlen(p);
} }
memdump.push_back(md); memdump.push_back(md);
skipping to change at line 2740 skipping to change at line 2775
QString GdbDriver::editableValue(VarTree* value) QString GdbDriver::editableValue(VarTree* value)
{ {
QByteArray ba = value->value().toLatin1(); QByteArray ba = value->value().toLatin1();
const char* s = ba.constData(); const char* s = ba.constData();
// if the variable is a pointer value that contains a cast, // if the variable is a pointer value that contains a cast,
// remove the cast // remove the cast
if (*s == '(') { if (*s == '(') {
skipNested(s, '(', ')'); skipNested(s, '(', ')');
// skip space // skip space
while (isspace(*s)) skipSpace(s);
++s;
} }
repeat: repeat:
const char* start = s; const char* start = s;
if (strncmp(s, "0x", 2) == 0) if (strncmp(s, "0x", 2) == 0)
{ {
s += 2; s += 2;
while (isxdigit(*s)) while (isxdigit(*s))
++s; ++s;
skipping to change at line 2765 skipping to change at line 2799
* referenced value. Otherwise, edit the pointer. * referenced value. Otherwise, edit the pointer.
*/ */
if (*s == ':') { if (*s == ':') {
// a reference // a reference
++s; ++s;
goto repeat; goto repeat;
} }
// a pointer // a pointer
// if it's a pointer to a string, remove the string // if it's a pointer to a string, remove the string
const char* end = s; const char* end = s;
while (isspace(*s)) skipSpace(s);
++s;
if (*s == '"') { if (*s == '"') {
// a string // a string
return QString::fromLatin1(start, end-start); return QString::fromLatin1(start, end-start);
} else { } else {
// other pointer // other pointer
return QString::fromLatin1(start, strlen(start)); return QString::fromLatin1(start, strlen(start));
} }
} }
// else leave it unchanged (or stripped of the reference preamble) // else leave it unchanged (or stripped of the reference preamble)
 End of changes. 55 change blocks. 
108 lines changed or deleted 142 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS