1
// **************************************************************************
2
// begin : Tue Aug 17 1999
3
// copyright : (C) 1999 by John Birch
4
// email : jbb@kdevelop.org
6
// Adapted for ruby debugging
7
// --------------------------
8
// begin : Mon Nov 1 2004
9
// copyright : (C) 2004 by Richard Dale
10
// email : Richard_Dale@tipitina.demon.co.uk
11
// **************************************************************************
13
// **************************************************************************
15
// This program is free software; you can redistribute it and/or modify *
16
// it under the terms of the GNU General Public License as published by *
17
// the Free Software Foundation; either version 2 of the License, or *
18
// (at your option) any later version. *
20
// **************************************************************************
22
#include "rdbparser.h"
23
#include "variablewidget.h"
35
// **************************************************************************
37
void RDBParser::parseVariables(LazyFetchItem *parent, char *buf)
39
static const char *unknown = "?";
46
if (buf == 0 || strlen(buf) == 0) {
54
QRegExp var_re("\\s*([^\\n\\s]+) => ([^\\n]+)");
55
QRegExp ref_re("(#<([^:]|::)+:0x[\\da-f]+)\\s*([^=]*)>?");
56
QRegExp struct_re("#<struct Struct::(\\w+)");
58
// Look for 'dataitem => value' pairs. For example:
60
// m => #<MyClass:0x30093540 @temp={"z"=>"zed", "p"=>"pee"}, @foobar="hello">
62
pos = var_re.search(buf);
65
varName = var_re.cap(1);
66
if (ref_re.search(var_re.cap(2)) != -1) {
67
if (var_re.cap(2).contains("=") > 0) {
68
value = (ref_re.cap(1) + ">").latin1();
70
// There are no 'name=value' pairs, as in #<Qt::Color:0x0 #ff0000>
71
value = var_re.cap(2).latin1();
73
} else if (struct_re.search(var_re.cap(2)) != -1) {
74
value = (QString("#<Struct::") + struct_re.cap(1) + ">").latin1();
76
value = var_re.cap(2).latin1();
79
DataType dataType = determineType((char *) var_re.cap(2).latin1());
81
// 'self' variables don't need to be expandable, as their details are
82
// already shown in the current frame. So always make them VALUE_TYPE's.
83
if (varName == "self") {
84
dataType = VALUE_TYPE;
87
setItem(parent, varName, dataType, value);
89
pos += var_re.matchedLength();
90
pos = var_re.search(buf, pos);
97
void RDBParser::parseExpandedVariable(VarItem *parent, char *buf)
103
QRegExp ppref_re("(#<([^:]|::)+:0x[\\da-f]+)([^\\n>]*)(>?)");
105
switch (parent->dataType()) {
108
// Look for a reference type which has been printed via a 'pp' command, to
109
// expand its sub items on multiple lines. For example:
110
// #<MyClass:0x30093540
112
// @sleeper=#<Thread:0x3008fd18 sleep>,
113
// @temp={"z"=>"zed", "p"=>"pee"}>
115
QRegExp ppvalue_re("\\s*([^\\n\\s=]+)=([^\\n]+)[,>]");
117
pos = ppref_re.search(buf);
119
if (ppref_re.cap(4) != "") {
120
// The value is all on one line, so match against name=value
121
// pairs which can't have commas in their values
122
ppvalue_re = QRegExp("\\s*([^\\s=]+)=([^,>]+)([,>])");
125
pos = ppvalue_re.search(buf, pos);
128
varName = ppvalue_re.cap(1);
130
if (ppref_re.search(ppvalue_re.cap(2)) != -1) {
131
if (ppvalue_re.cap(2).contains("=") > 0) {
132
value = (ppref_re.cap(1) + ">").latin1();
134
// There are no 'name=value' pairs, as in #<Qt::Color:0x0 #ff0000>
135
value = ppvalue_re.cap(2).latin1();
138
value = ppvalue_re.cap(2).latin1();
141
dataType = determineType((char *) ppvalue_re.cap(2).latin1());
142
setItem(parent, varName, dataType, value);
144
pos += ppvalue_re.matchedLength();
145
pos = ppvalue_re.search(buf, pos);
154
// Look for a array type which has been printed via a 'pp' command, to
155
// expand its sub items. For example:
159
QRegExp pparray_re("\\s*([^=]+)=([^\\n]+)\\n");
161
pos = pparray_re.search(buf);
164
varName = pparray_re.cap(1);
166
if (ppref_re.search(pparray_re.cap(2)) != -1) {
167
value = (ppref_re.cap(1) + ">").latin1();
169
value = pparray_re.cap(2).latin1();
172
DataType dataType = determineType((char *) pparray_re.cap(2).latin1());
173
setItem(parent, varName, dataType, value);
175
pos += pparray_re.matchedLength();
176
pos = pparray_re.search(buf, pos);
184
// Look for a hash type which has been printed via a 'pp' command, to
185
// expand its sub items. For example:
186
// ["greeting"]="hello"
187
// ["farewell"]="goodbye"
189
QRegExp pphash_re("\\s*(\\[[^\\]]+\\])=([^\\n]+)\\n");
190
pos = pphash_re.search(buf);
193
varName = pphash_re.cap(1);
194
value = pphash_re.cap(2).latin1();
195
DataType dataType = determineType(value.data());
196
setItem(parent, varName, dataType, value);
198
pos += pphash_re.matchedLength();
199
pos = pphash_re.search(buf, pos);
207
// Look for a reference type which has been printed via a 'pp' command, to
208
// expand its sub items. For example:
209
// #<Struct::Customer
211
// @sleeper=#<Thread:0x3008fd18 sleep>,
212
// @temp={"z"=>"zed", "p"=>"pee"}>
214
QRegExp ppstruct_re("(#<Struct::\\w+)\\s([^\\n>]*)(>?)");
215
QRegExp ppvalue_re("\\s*([^\\n\\s=]+)=([^\\n]+)[,>]");
217
pos = ppstruct_re.search(buf);
219
if (ppstruct_re.cap(3) != "" && ppvalue_re.search(ppstruct_re.cap(0)) != -1) {
220
// The line ends with a '>', but we have this case now..
221
// If there is only one instance variable, pp puts everything
223
// #<Struct::Customer @foobar="hello">
224
// So search for '@foobar="hello"', to use as the
225
// first name=value pair
228
// Mltiple lines with name=value pairs:
229
// #<Struct::Customer
231
pos = ppvalue_re.search(buf, pos);
235
varName = ppvalue_re.cap(1);
236
value = ppvalue_re.cap(2).latin1();
237
dataType = determineType(value.data());
238
setItem(parent, varName, dataType, value);
240
pos += ppvalue_re.matchedLength();
241
pos = ppvalue_re.search(buf, pos);
250
// Look for a long String which has been printed via a 'pp' command, to
251
// show it as a sequence of 12 bytes slices in hex. For example:
252
// [0..11]=0x89504e470d0a1a0a0000000d
253
// [12..23]=0x494844520000001600000016
255
QRegExp ppstring_re("\\s*(\\[[^\\]]+\\])=([^\\n]+)\\n");
256
pos = ppstring_re.search(buf);
259
varName = ppstring_re.cap(1);
260
value = ppstring_re.cap(2).latin1();
261
DataType dataType = determineType(value.data());
262
setItem(parent, varName, dataType, value);
264
pos += ppstring_re.matchedLength();
265
pos = ppstring_re.search(buf, pos);
279
// **************************************************************************
281
void RDBParser::setItem(LazyFetchItem *parent, const QString &varName,
282
DataType dataType, const QCString &value)
284
VarItem *item = parent->findItem(varName);
286
item = new VarItem(parent, varName, dataType);
288
// The dataType of an item can change, so update it
289
item->setDataType(dataType);
298
item->setText(VALUE_COLUMN, value);
299
item->setExpandable(true);
305
item->setText(VALUE_COLUMN, value);
306
item->setExpandable(false);
314
// **************************************************************************
316
DataType RDBParser::determineType(char *buf)
318
QRegExp array_re("(Array \\(\\d+ element\\(s\\)\\))");
319
QRegExp hash_re("(Hash \\(\\d+ element\\(s\\)\\))");
320
QRegExp string_re("(String \\(length \\d+\\))");
322
if (qstrncmp(buf, "#<struct", strlen("#<struct")) == 0) {
324
} else if (qstrncmp(buf, "#<Qt::Color:0x", strlen("#<Qt::Color:0x")) == 0) {
326
} else if (qstrncmp(buf, "#<", strlen("#<")) == 0 && strstr(buf, "=") != 0) {
327
// An object instance reference is only expandable and a 'REFERENCE_TYPE'
328
// if it contains an '=' (ie it has at least one '@instance_variable=value').
329
// Otherwise, treat it as a 'VALUE_TYPE'.
330
return REFERENCE_TYPE;
331
} else if (array_re.search(buf) != -1) {
333
} else if (hash_re.search(buf) != -1) {
335
} else if (string_re.search(buf) != -1) {
337
} else if (qstrncmp(buf, "nil", strlen("nil")) == 0) {
338
// return UNKNOWN_TYPE;
346
// **************************************************************************
347
// **************************************************************************
348
// **************************************************************************