KDevelop API Documentation

jdbparser.cpp

Go to the documentation of this file.
00001 // **************************************************************************
00002 //                          jdbparser.cpp  -  description
00003 //                             -------------------
00004 //    begin                : Tue Aug 17 1999
00005 //    copyright            : (C) 1999 by John Birch
00006 //    email                : jbb@kdevelop.org
00007 // **************************************************************************
00008 
00009 // **************************************************************************
00010 //                                                                          *
00011 //    This program is free software; you can redistribute it and/or modify  *
00012 //    it under the terms of the GNU General Public License as published by  *
00013 //    the Free Software Foundation; either version 2 of the License, or     *
00014 //    (at your option) any later version.                                   *
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     // QT2.x string handling
00129     // A very bad hack alert!
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         // Don't update a "this" item because it'll alwasy stay red because the local
00168         // this looks different than the param this.
00169         // @todo - this is not good code. We should check to see if the address is the
00170         // same between params and locals before ignoring the param.
00171         //    if (params && varName == "this")
00172         //      return;
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     // A reference, probably from a parameter value.
00219     if (*buf == '@')
00220         return typeReference;
00221 
00222     // Structures and arrays - (but which one is which?)
00223     // {void (void)} 0x804a944 <__builtin_new+41> - this is a fn pointer
00224     // (void (*)(void)) 0x804a944 <f(E *, char)>  - so is this - ugly!!!
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;                     // Hmm a single element array??
00250                 if (strncmp(buf+1, " 0x", 3) == 0)
00251                     return typePointer;                   // What about references?
00252                 return typeUnknown;                     // very odd?
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     // some sort of address. We need to sort out if we have
00268     // a 0x888888 "this is a char*" type which we'll term a value
00269     // or whether we just have an address
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     // Pointers and references - references are a bit odd
00284     // and cause JDB to fail to produce all the local data
00285     // if they haven't been initialised. but that's not our problem!!
00286     // (void (*)(void)) 0x804a944 <f(E *, char)> - this is a fn pointer
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)         // take care of <repeats
00316                 buf = skipDelim(buf+1, '<', '>');
00317             else
00318                 break;
00319         }
00320 
00321         // If the string is long then it's chopped and has ... after it.
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++;             // skips \" or \' problems
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 // **************************************************************************
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:30 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003