00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
#include "jdbparser.h"
00019
#include "variablewidget.h"
00020
00021
#include <qregexp.h>
00022
00023
#include <ctype.h>
00024
#include <stdlib.h>
00025
00026
namespace JAVADebugger
00027 {
00028
00029
00030
00031
00032
00033 JDBParser::JDBParser()
00034 {
00035 }
00036
00037
00038
00039 JDBParser::~JDBParser()
00040 {
00041 }
00042
00043
00044
00045 void JDBParser::parseData(
TrimmableItem *parent,
char *buf,
00046
bool requested,
bool params)
00047 {
00048
static const char *unknown =
"?";
00049
00050 Q_ASSERT(parent);
00051
if (!buf)
00052
return;
00053
00054
if (parent->
getDataType() == typeArray) {
00055
parseArray(parent, buf);
00056
return;
00057 }
00058
00059
if (requested && !*buf)
00060 buf = (
char*)unknown;
00061
00062
while (*buf) {
00063
QString varName =
"";
00064 DataType dataType =
determineType(buf);
00065
00066
if (dataType == typeName) {
00067 varName =
getName(&buf);
00068 dataType = determineType(buf);
00069 }
00070
00071
QCString value =
getValue(&buf, requested);
00072
setItem(parent, varName, dataType, value, requested, params);
00073 }
00074 }
00075
00076
00077
00078 void JDBParser::parseArray(
TrimmableItem *parent,
char *buf)
00079 {
00080
QString elementRoot = parent->
getName() +
"[%1]";
00081
int idx = 0;
00082
while (*buf) {
00083 buf =
skipNextTokenStart(buf);
00084
if (!*buf)
00085
return;
00086
00087 DataType dataType =
determineType(buf);
00088
QCString value =
getValue(&buf,
false);
00089
QString varName = elementRoot.arg(idx);
00090
setItem(parent, varName, dataType, value,
false,
false);
00091
00092
int pos = value.find(
" <repeats", 0);
00093
if (pos > -1) {
00094
if (
int i = atoi(value.data()+pos+10))
00095 idx += (i-1);
00096 }
00097
00098 idx++;
00099 }
00100 }
00101
00102
00103
00104 QString JDBParser::getName(
char **buf)
00105 {
00106
char *start =
skipNextTokenStart(*buf);
00107
if (*start) {
00108 *buf =
skipTokenValue(start);
00109
return QCString(start, *buf - start + 1);
00110 }
else
00111 *buf = start;
00112
00113
return QString();
00114 }
00115
00116
00117
00118 QCString JDBParser::getValue(
char **buf,
bool requested)
00119 {
00120
char *start =
skipNextTokenStart(*buf);
00121 *buf =
skipTokenValue(start);
00122
00123
if (*start ==
'{')
00124
return QCString(start+1, *buf - start -1);
00125
00126
QCString value(start, *buf - start + 1);
00127
00128
00129
00130
if (requested)
00131
return value.replace(
QRegExp(
"\\\\000"),
"" );
00132
00133
return value;
00134 }
00135
00136
00137
00138 TrimmableItem *JDBParser::getItem(
TrimmableItem *parent, DataType dataType,
00139
const QString &varName,
bool requested)
00140 {
00141
if (requested)
00142
return parent;
00143
00144
if (varName.isEmpty()) {
00145
if (parent->
getDataType() == typeReference)
00146
return parent;
00147
00148
return 0;
00149 }
00150
00151
return parent->
findMatch(varName, dataType);
00152 }
00153
00154
00155
00156 void JDBParser::setItem(
TrimmableItem *parent,
const QString &varName,
00157 DataType dataType,
const QCString &value,
00158
bool requested,
bool)
00159 {
00160
TrimmableItem *item =
getItem(parent, dataType, varName, requested);
00161
if (!item) {
00162
if (varName.isEmpty())
00163
return;
00164
00165 item =
new VarItem(parent, varName, dataType);
00166 }
else {
00167
00168
00169
00170
00171
00172
00173 }
00174
00175
switch (dataType) {
00176
case typePointer:
00177 item->setText(ValueCol, value);
00178 item->setExpandable(varName !=
"_vptr.");
00179
break;
00180
00181
case typeStruct:
00182
case typeArray:
00183 item->
setCache(value);
00184
break;
00185
00186
case typeReference:
00187 {
00188
int pos;
00189
if ((pos = value.find(
':', 0)) != -1) {
00190
QCString rhs((value.mid(pos+2, value.length()).data()));
00191
if (
determineType(rhs.data()) != typeValue) {
00192 item->
setCache(rhs);
00193 item->setText(ValueCol, value.left(pos));
00194
break;
00195 }
00196 }
00197 item->setText(ValueCol, value);
00198 item->setExpandable(!value.isEmpty() && (value[0] ==
'@'));
00199
break;
00200 }
00201
00202
case typeValue:
00203 item->setText(ValueCol, value);
00204
break;
00205
00206
default:
00207
break;
00208 }
00209 }
00210
00211
00212
00213 DataType JDBParser::determineType(
char *buf)
const
00214
{
00215
if (!buf || !*(buf=
skipNextTokenStart(buf)))
00216
return typeUnknown;
00217
00218
00219
if (*buf ==
'@')
00220
return typeReference;
00221
00222
00223
00224
00225
if (*buf ==
'{') {
00226
if (strncmp(buf,
"{{", 2) == 0)
00227
return typeArray;
00228
00229
if (strncmp(buf,
"{<No data fields>}", 18) == 0)
00230
return typeValue;
00231
00232 buf++;
00233
while (*buf) {
00234
switch (*buf) {
00235
case '=':
00236
return typeStruct;
00237
case '"':
00238 buf =
skipString(buf);
00239
break;
00240
case '\'':
00241 buf =
skipQuotes(buf,
'\'');
00242
break;
00243
case ',':
00244
if (*(buf-1) ==
'}')
00245 Q_ASSERT(
false);
00246
return typeArray;
00247
case '}':
00248
if (*(buf+1) ==
',' || *(buf+1) ==
'\n' || !*(buf+1))
00249
return typeArray;
00250
if (strncmp(buf+1,
" 0x", 3) == 0)
00251
return typePointer;
00252
return typeUnknown;
00253
case '(':
00254 buf =
skipDelim(buf,
'(',
')');
00255
break;
00256
case '<':
00257 buf = skipDelim(buf,
'<',
'>');
00258
break;
00259
default:
00260 buf++;
00261
break;
00262 }
00263 }
00264
return typeUnknown;
00265 }
00266
00267
00268
00269
00270
if (strncmp(buf,
"0x", 2) == 0) {
00271
while (*buf) {
00272
if (!isspace(*buf))
00273 buf++;
00274
else if (*(buf+1) ==
'\"')
00275
return typeValue;
00276
else
00277
break;
00278 }
00279
00280
return typePointer;
00281 }
00282
00283
00284
00285
00286
00287
if (*buf ==
'(') {
00288 buf =
skipDelim(buf,
'(',
')');
00289
switch (*(buf-2)) {
00290
case '*':
00291
return typePointer;
00292
case '&':
00293
return typeReference;
00294
default:
00295
return typeUnknown;
00296 }
00297 }
00298
00299 buf =
skipTokenValue(buf);
00300
if ((strncmp(buf,
" = ", 3) == 0) || (*buf ==
'='))
00301
return typeName;
00302
00303
return typeValue;
00304 }
00305
00306
00307
00308 char *JDBParser::skipString(
char *buf)
const
00309
{
00310
if (buf && *buf ==
'\"') {
00311 buf =
skipQuotes(buf, *buf);
00312
while (*buf) {
00313
if ((strncmp(buf,
", \"", 3) == 0) || (strncmp(buf,
", '", 3) == 0))
00314 buf = skipQuotes(buf+2, *(buf+2));
00315
else if (strncmp(buf,
" <", 2) == 0)
00316 buf =
skipDelim(buf+1,
'<',
'>');
00317
else
00318
break;
00319 }
00320
00321
00322
while (*buf && *buf ==
'.')
00323 buf++;
00324 }
00325
00326
return buf;
00327 }
00328
00329
00330
00331 char *JDBParser::skipQuotes(
char *buf,
char quotes)
const
00332
{
00333
if (buf && *buf == quotes) {
00334 buf++;
00335
00336
while (*buf) {
00337
if (*buf ==
'\\')
00338 buf++;
00339
else if (*buf == quotes)
00340
return buf+1;
00341
00342 buf++;
00343 }
00344 }
00345
00346
return buf;
00347 }
00348
00349
00350
00351 char *JDBParser::skipDelim(
char *buf,
char open,
char close)
const
00352
{
00353
if (buf && *buf == open) {
00354 buf++;
00355
00356
while (*buf) {
00357
if (*buf == open)
00358 buf =
skipDelim(buf, open, close);
00359
else if (*buf == close)
00360
return buf+1;
00361
else if (*buf ==
'\"')
00362 buf =
skipString(buf);
00363
else if (*buf ==
'\'')
00364 buf =
skipQuotes(buf, *buf);
00365
else if (*buf)
00366 buf++;
00367 }
00368 }
00369
return buf;
00370 }
00371
00372
00373
00374 char *JDBParser::skipTokenValue(
char *buf)
const
00375
{
00376
if (buf) {
00377
while (
true) {
00378 buf =
skipTokenEnd(buf);
00379
00380
char *end = buf;
00381
while (*end && isspace(*end) && *end !=
'\n')
00382 end++;
00383
00384
if (*end == 0 || *end ==
',' || *end ==
'\n' || *end ==
'=' || *end ==
'}')
00385
break;
00386
00387
if (buf == end)
00388
break;
00389
00390 buf = end;
00391 }
00392 }
00393
00394
return buf;
00395 }
00396
00397
00398
00399 char *JDBParser::skipTokenEnd(
char *buf)
const
00400
{
00401
if (buf) {
00402
switch (*buf) {
00403
case '"':
00404
return skipString(buf);
00405
case '\'':
00406
return skipQuotes(buf, *buf);
00407
case '{':
00408
return skipDelim(buf,
'{',
'}');
00409
case '<':
00410
return skipDelim(buf,
'<',
'>');
00411
case '(':
00412
return skipDelim(buf,
'(',
')');
00413 }
00414
00415
while (*buf && !isspace(*buf) && *buf !=
',' && *buf !=
'}' && *buf !=
'=')
00416 buf++;
00417 }
00418
00419
return buf;
00420 }
00421
00422
00423
00424 char *JDBParser::skipNextTokenStart(
char *buf)
const
00425
{
00426
if (buf)
00427
while (*buf && (isspace(*buf) || *buf ==
',' || *buf ==
'}' || *buf ==
'='))
00428 buf++;
00429
00430
return buf;
00431 }
00432
00433 }
00434
00435
00436
00437