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