1
// **************************************************************************
2
// begin : Tue Aug 17 1999
3
// copyright : (C) 1999 by John Birch
4
// email : jbb@kdevelop.org
5
// **************************************************************************
7
// **************************************************************************
9
// This program is free software; you can redistribute it and/or modify *
10
// it under the terms of the GNU General Public License as published by *
11
// the Free Software Foundation; either version 2 of the License, or *
12
// (at your option) any later version. *
14
// **************************************************************************
16
#include "gdbparser.h"
17
#include "variablewidget.h"
28
// **************************************************************************
29
// **************************************************************************
30
// **************************************************************************
32
GDBParser *GDBParser::GDBParser_ = 0;
34
GDBParser *GDBParser::getGDBParser()
37
GDBParser_ = new GDBParser();
42
// **************************************************************************
44
void GDBParser::destroy()
50
// **************************************************************************
52
GDBParser::GDBParser()
56
// **************************************************************************
58
GDBParser::~GDBParser()
63
// **************************************************************************
65
QString GDBParser::getName(const char **buf)
67
const char *start = skipNextTokenStart(*buf);
69
*buf = skipTokenValue(start);
70
return QCString(start, *buf - start + 1);
77
// **************************************************************************
79
QString GDBParser::getValue(const char **buf)
81
const char *start = skipNextTokenStart(*buf);
82
*buf = skipTokenValue(start);
84
QString value(QCString(start, *buf - start + 1).data());
88
QString GDBParser::undecorateValue(DataType type, const QString& s)
90
QCString l8 = s.local8Bit();
91
const char* start = l8;
92
const char* end = start + s.length();
96
// Gdb uses '{' in two cases:
97
// - composites (arrays and structures)
98
// - pointers to functions. In this case type is
99
// enclosed in "{}". Not sure why it's so, as
100
// when printing pointer, type is in parenthesis.
101
if (type == typePointer)
103
// Looks like type in braces at the beginning. Strip it.
104
start = skipDelim(start, '{', '}');
108
// Looks like composite, strip the braces and return.
109
return QCString(start+1, end - start -1);
112
else if (*start == '(')
114
// Strip the type of the pointer from the value.
116
// When printing values of pointers, gdb prints the pointer
117
// type as well. This is not necessary for kdevelop -- after
118
// all, there's separate column with value type. But that behaviour
119
// is not configurable. The only way to change it is to explicitly
120
// pass the 'x' format specifier to the 'print' command.
122
// We probably can achieve that by sending an 'print in hex' request
123
// as soon as we know the type of variable, but that would be complex
124
// and probably conflict with 'toggle hex/decimal' command.
125
// So, address this problem as close to debugger as possible.
127
// We can't find the first ')', because type can contain '(' and ')'
128
// characters if its function pointer. So count opening and closing
131
start = skipDelim(start, '(', ')');
134
QString value(QCString(start, end - start + 1).data());
136
value = value.stripWhiteSpace();
140
// It's a reference, we need to show just the value.
141
if (int i = value.find(":"))
143
value = value.mid(i+2);
147
// Just reference, no value at all, remove all
152
if (value.find("Cannot access memory") == 0)
153
value = "(inaccessible)";
155
return value.stripWhiteSpace();
158
QString GDBParser::undecorateValue(const QString& s)
160
DataType dataType = determineType(s.local8Bit());
161
QString r = undecorateValue(dataType, s.local8Bit());
165
// Given a value that starts with 0xNNNNNN determines if
166
// it looks more like pointer, or a string value.
167
DataType pointerOrValue(const char *buf)
172
else if (*(buf+1) == '\"')
182
DataType GDBParser::determineType(const char *buf) const
184
if (!buf || !*(buf= skipNextTokenStart(buf)))
187
// A reference, probably from a parameter value.
189
return typeReference;
191
// Structures and arrays - (but which one is which?)
192
// {void (void)} 0x804a944 <__builtin_new+41> - this is a fn pointer
193
// (void (*)(void)) 0x804a944 <f(E *, char)> - so is this - ugly!!!
195
if (strncmp(buf, "{{", 2) == 0)
198
if (strncmp(buf, "{<No data fields>}", 18) == 0)
207
buf = skipString(buf);
210
buf = skipQuotes(buf, '\'');
217
if (*(buf+1) == ',' || *(buf+1) == '\n' || !*(buf+1))
218
return typeArray; // Hmm a single element array??
219
if (strncmp(buf+1, " 0x", 3) == 0)
220
return typePointer; // What about references?
221
return typeUnknown; // very odd?
223
buf = skipDelim(buf, '(', ')');
226
buf = skipDelim(buf, '<', '>');
227
// gdb may produce this output:
228
// $1 = 0x804ddf3 ' ' <repeats 20 times>, "TESTSTRING"
229
// after having finished with the "repeats"-block we need
230
// to check if the string continues
231
if ( buf[0] == ',' && (buf[2] == '\"' || buf[2] == '\'') ) {
232
buf++; //set the buffer behind the comma to indicate that the string continues
243
// some sort of address. We need to sort out if we have
244
// a 0x888888 "this is a char*" type which we'll term a value
245
// or whether we just have an address
246
if (strncmp(buf, "0x", 2) == 0) {
247
return pointerOrValue(buf);
250
// Pointers and references - references are a bit odd
251
// and cause GDB to fail to produce all the local data
252
// if they haven't been initialised. but that's not our problem!!
253
// (void (*)(void)) 0x804a944 <f(E *, char)> - this is a fn pointer
255
buf = skipDelim(buf, '(', ')');
256
// This 'if' handles values like this:
257
// (int (&)[3]) @0xbffff684: {5, 6, 7}
258
// which is a reference to array.
260
return typeReference;
261
// This 'if' handles values like this:
262
// (int (*)[3]) 0xbffff810
263
if (strncmp(buf, " 0x", 3) == 0)
266
return pointerOrValue(buf);
273
return typeReference;
279
return typeReference;
285
buf = skipTokenValue(buf);
286
if ((strncmp(buf, " = ", 3) == 0) || (*buf == '='))
292
// **************************************************************************
294
const char *GDBParser::skipString(const char *buf) const
296
if (buf && *buf == '\"') {
297
buf = skipQuotes(buf, *buf);
299
if ((strncmp(buf, ", \"", 3) == 0) ||
300
(strncmp(buf, ", '", 3) == 0))
301
buf = skipQuotes(buf+2, *(buf+2));
302
else if (strncmp(buf, " <", 2) == 0) // take care of <repeats
303
buf = skipDelim(buf+1, '<', '>');
308
// If the string is long then it's chopped and has ... after it.
309
while (*buf && *buf == '.')
316
// ***************************************************************************
318
const char *GDBParser::skipQuotes(const char *buf, char quotes) const
320
if (buf && *buf == quotes) {
325
buf++; // skips \" or \' problems
326
else if (*buf == quotes)
336
// **************************************************************************
338
const char *GDBParser::skipDelim(const char *buf, char open, char close) const
340
if (buf && *buf == open) {
345
buf = skipDelim(buf, open, close);
346
else if (*buf == close)
348
else if (*buf == '\"')
349
buf = skipString(buf);
350
else if (*buf == '\'')
351
buf = skipQuotes(buf, *buf);
359
// **************************************************************************
361
const char *GDBParser::skipTokenValue(const char *buf) const
365
buf = skipTokenEnd(buf);
367
const char *end = buf;
368
while (*end && isspace(*end) && *end != '\n')
371
if (*end == 0 || *end == ',' || *end == '\n' || *end == '=' || *end == '}')
384
// **************************************************************************
386
const char *GDBParser::skipTokenEnd(const char *buf) const
391
return skipString(buf);
393
return skipQuotes(buf, *buf);
395
return skipDelim(buf, '{', '}');
397
buf = skipDelim(buf, '<', '>');
398
// gdb may produce this output:
399
// $1 = 0x804ddf3 ' ' <repeats 20 times>, "TESTSTRING"
400
// after having finished with the "repeats"-block we need
401
// to check if the string continues
402
if ( buf[0] == ',' && (buf[2] == '\"' || buf[2] == '\'') ) {
403
buf++; //set the buffer behind the comma to indicate that the string continues
407
return skipDelim(buf, '(', ')');
410
while (*buf && !isspace(*buf) && *buf != ',' && *buf != '}' && *buf != '=')
417
// **************************************************************************
419
const char *GDBParser::skipNextTokenStart(const char *buf) const
422
while (*buf && (isspace(*buf) || *buf == ',' || *buf == '}' || *buf == '='))
428
// **************************************************************************
429
// **************************************************************************
430
// **************************************************************************