00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "jdbcontroller.h"
00019
00020 #include "javadebuggerpart.h"
00021 #include "breakpoint.h"
00022 #include "framestackwidget.h"
00023 #include "variablewidget.h"
00024 #include "jdbcommand.h"
00025 #include "stty.h"
00026
00027 #include <kapplication.h>
00028 #include <kconfig.h>
00029 #include <kmessagebox.h>
00030
00031 #include <kglobal.h>
00032 #include <klocale.h>
00033
00034 #include <kprocess.h>
00035 #include <kdebug.h>
00036
00037 #include <qregexp.h>
00038 #include <qstring.h>
00039 #include <qtimer.h>
00040 #include <qurl.h>
00041
00042 #include <iostream>
00043 #include <ctype.h>
00044 #include <stdlib.h>
00045
00046 using namespace std;
00047
00048 #define BREAKPOINT_HIT 1
00049 #define MARK_FOUND 2
00050 #define JDB_MONITOR 1
00051
00052
00053
00054 #if defined(DBG_MONITOR)
00055 #define JDB_MONITOR
00056 #define DBG_DISPLAY(X) {kdDebug() << QString(X) << endl;}
00057 #else
00058 #define DBG_DISPLAY(X) {kdDebug() << QString(X) << endl;}
00059 #endif
00060
00061 #if defined(JDB_MONITOR)
00062 #define JDB_DISPLAY(X) {kdDebug() << QString(X) << endl;}
00063 #else
00064 #define JDB_DISPLAY(X) {kdDebug() << QString(X) << endl;}
00065 #endif
00066
00067
00068 namespace JAVADebugger
00069 {
00070
00094 JDBController::JDBController(VariableTree *varTree, FramestackWidget *frameStack, QString projectDirectory, QString mainProgram)
00095 : DbgController(),
00096
00097 classpath_(projectDirectory + "/src:" + (getenv("CLASSPATH") == 0 ? "." : getenv("CLASSPATH"))),
00098 mainclass_(mainProgram),
00099 projectDirectory_(projectDirectory + "/src"),
00100 frameStack_(frameStack),
00101 varTree_(varTree),
00102 currentFrame_(0),
00103 state_(s_dbgNotStarted|s_appNotStarted|s_silent),
00104 jdbSizeofBuf_(2048),
00105 jdbOutputLen_(0),
00106 jdbOutput_(new char[2048]),
00107 currentCmd_(0),
00108 tty_(0),
00109 programHasExited_(false),
00110 config_forceBPSet_(true),
00111 config_displayStaticMembers_(false),
00112 config_dbgTerminal_(false),
00113 config_jdbPath_()
00114 {
00115 KConfig *config = JavaDebuggerFactory::instance()->config();
00116 config->setGroup("Debug");
00117 Q_ASSERT(!config->readBoolEntry("Use external debugger", false));
00118
00119 config_displayStaticMembers_ = config->readBoolEntry("Display static members", false);
00120 config_forceBPSet_ = config->readBoolEntry("Allow forced BP set", true);
00121 config_jdbPath_ = config->readPathEntry("JDB path");
00122 config_dbgTerminal_ = config->readBoolEntry("Debug on separate tty console", false);
00123
00124 #if defined (JDB_MONITOR)
00125 kdDebug() << "Connect\n";
00126 connect( this, SIGNAL(dbgStatus(const QString&, int)),
00127 SLOT(slotDbgStatus(const QString&, int)));
00128 #endif
00129
00130 #if defined (DBG_MONITOR)
00131 connect( this, SIGNAL(showStepInSource(const QString&, int, const QString&)),
00132 SLOT(slotStepInSource(const QString&,int)));
00133 #endif
00134
00135 cmdList_.setAutoDelete(true);
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145 JDBController::~JDBController()
00146 {
00147 setStateOn(s_shuttingDown);
00148 destroyCmds();
00149
00150 if (dbgProcess_) {
00151 setStateOn(s_silent);
00152 pauseApp();
00153 setStateOn(s_waitTimer);
00154
00155 QTimer *timer;
00156
00157 timer = new QTimer(this);
00158 connect(timer, SIGNAL(timeout()), this, SLOT(slotAbortTimedEvent()) );
00159
00160
00161 setStateOn(s_waitTimer|s_appBusy);
00162 const char *quit="quit\n";
00163 dbgProcess_->writeStdin(quit, strlen(quit));
00164 JDB_DISPLAY(quit);
00165 timer->start(3000, TRUE);
00166 DBG_DISPLAY("<quit wait>\n");
00167 while (stateIsOn(s_waitTimer)) {
00168 if (stateIsOn(s_programExited))
00169 break;
00170 kapp->processEvents(20);
00171 }
00172
00173
00174 if (stateIsOn(s_shuttingDown))
00175 dbgProcess_->kill(SIGKILL);
00176 }
00177
00178 delete tty_; tty_ = 0;
00179 delete[] jdbOutput_;
00180
00181 emit dbgStatus (i18n("Debugger stopped"), state_);
00182 }
00183
00184
00185
00186 void JDBController::reConfig()
00187 {
00188 KConfig *config = JavaDebuggerFactory::instance()->config();
00189 config->setGroup("Debug");
00190 Q_ASSERT(!config->readBoolEntry("Use external debugger", false));
00191
00192 bool old_displayStatic = config_displayStaticMembers_;
00193 config_displayStaticMembers_ = config->readBoolEntry("Display static members", false);
00194
00195
00196 if (( old_displayStatic != config_displayStaticMembers_)&&
00197 dbgProcess_) {
00198 bool restart = false;
00199 if (stateIsOn(s_appBusy)) {
00200 setStateOn(s_silent);
00201 pauseApp();
00202 restart = true;
00203 }
00204
00205
00206 if (restart)
00207 queueCmd(new JDBCommand("cont", RUNCMD, NOTINFOCMD, 0));
00208 }
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 void JDBController::queueCmd(DbgCommand *cmd, bool executeNext)
00220 {
00221
00222
00223
00224
00225
00226 if (cmd->isARunCmd())
00227 removeInfoRequests();
00228
00229 if (executeNext)
00230 cmdList_.insert(0, cmd);
00231 else
00232 cmdList_.append (cmd);
00233
00234 executeCmd();
00235 }
00236
00237
00238
00239
00240
00241
00242
00243 void JDBController::executeCmd()
00244 {
00245
00246 if (stateIsOn(s_dbgNotStarted|s_waitForWrite|s_appBusy)) {
00247 return;
00248 }
00249
00250
00251 if (!currentCmd_) {
00252 if (cmdList_.isEmpty()) {
00253 DBG_DISPLAY("Commandlist empty...\n");
00254 return;
00255 }
00256
00257 currentCmd_ = cmdList_.take(0);
00258 } else {
00259
00260 if (!currentCmd_->moreToSend()) {
00261 if (currentCmd_->expectReply()) {
00262 return;
00263 }
00264
00265 delete currentCmd_;
00266 if (cmdList_.isEmpty()) {
00267 currentCmd_ = 0;
00268
00269 return;
00270 }
00271
00272 currentCmd_ = cmdList_.take(0);
00273 }
00274 }
00275
00276 Q_ASSERT(currentCmd_ && currentCmd_->moreToSend());
00277
00278
00279 dbgProcess_->writeStdin(currentCmd_->cmdToSend().data(), currentCmd_->cmdLength());
00280 setStateOn(s_waitForWrite);
00281
00282 if (currentCmd_->isARunCmd()) {
00283 setStateOn(s_appBusy);
00284 setStateOff(s_appNotStarted|s_programExited|s_silent);
00285 }
00286
00287 JDB_DISPLAY("Written command: " + currentCmd_->cmdToSend());
00288 if (!stateIsOn(s_silent))
00289 emit dbgStatus ("", state_);
00290 }
00291
00292
00293
00294 void JDBController::destroyCmds()
00295 {
00296 if (currentCmd_) {
00297 delete currentCmd_;
00298 currentCmd_ = 0;
00299 }
00300
00301 while (!cmdList_.isEmpty())
00302 delete cmdList_.take(0);
00303 }
00304
00305
00306
00307 void JDBController::removeInfoRequests()
00308 {
00309 int i = cmdList_.count();
00310 while (i) {
00311 i--;
00312 DbgCommand *cmd = cmdList_.at(i);
00313 if (cmd->isAnInfoCmd() || cmd->isARunCmd())
00314 delete cmdList_.take(i);
00315 }
00316 }
00317
00318
00319
00320
00321
00322
00323 void JDBController::pauseApp()
00324 {
00325 }
00326
00327
00328
00329
00330
00331 void JDBController::actOnProgramPause(const QString &msg)
00332 {
00333
00334 if (stateIsOn(s_appBusy)) {
00335 DBG_DISPLAY("Acting on program paused: " + msg);
00336 setStateOff(s_appBusy);
00337
00338
00339 currentFrame_ = 0;
00340 varTree_->setActiveFlag();
00341
00342 emit dbgStatus("", state_);
00343
00344 stackLineCount = 0;
00345
00346 frameStack_->clearList();
00347
00348 setStateOn(s_parsingOutput);
00349 queueCmd(new JDBCommand("where", NOTRUNCMD, NOTINFOCMD, BACKTRACE), TRUE);
00350
00351 executeCmd();
00352
00353 varLineCount = 0;
00354
00355 localData.clear();
00356 nameQueue.clear();
00357
00358
00359 setStateOn(s_parsingOutput);
00360 parsedThis = FALSE;
00361 queueCmd(new JDBCommand("locals", NOTRUNCMD, INFOCMD, LOCALS), FALSE);
00362 executeCmd();
00363
00364 } else { kdDebug() << "Not running\n";}
00365 }
00366
00367
00368
00369
00370
00371
00372
00373 void JDBController::programNoApp(const QString &, bool)
00374 {
00375 }
00376
00377
00378
00379 enum lineStarts
00380 {
00381
00382
00383
00384
00385
00386 START_Brea = 0x42726561,
00387
00388 START_Step = 0x70657453
00389 };
00390
00391
00392
00393
00394
00395
00396 char* JDBController::parseLine(char *buf)
00397 {
00398
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 if (memcmp(buf, "Brea", 4) == 0) {
00414 kdDebug() << "Checking for breakpoint\n";
00415 if ((strncmp(buf, "Breakpoint hit: thread", 22) == 0)) {
00416 QRegExp ex( "Breakpoint hit: thread=\\\"(.*)\\\", (.*\\)), line=([0-9]*), bci\\=[0-9]*.*\\n[^\\[]*\\[[0-9]*\\] ");
00417 if (ex.search( buf) != -1 ) {
00418 DBG_DISPLAY(QString("Breakpoint hit in line ") + ex.cap(3));
00419 if (stateIsOn(s_appStarting)) {
00420 setStateOff(s_appStarting);
00421 }
00422 curMethod = ex.cap(2),
00423 curLine = ex.cap(3);
00424
00425
00426 if (currentCmd_ && currentCmd_->isARunCmd()) {
00427 delete currentCmd_;
00428 currentCmd_ = 0;
00429 kdDebug() << "Deleting step command\n";
00430 }
00431
00432
00433 emit showStepInSource(QString(classpath_ + "/" + mainclass_ + ".java").latin1(),
00434 atoi(ex.cap(3).latin1()), "");
00435 actOnProgramPause(QString("Reached Breakpoint in line ")+ex.cap(3));
00436
00437 char *retStr;
00438 QString retQString = QString( buf + ex.cap(ex.numCaptures()) );
00439 memcpy( retStr, retQString.latin1(), retQString.length() );
00440 return retStr;
00441 }
00442
00443 }
00444 } else if (memcmp(buf, "Step", 4) == 0) {
00445 if ((strncmp(buf, "Step completed:", 15) == 0)) {
00446 kdDebug() << "STEP: " << buf << endl;
00447 QRegExp ex( " thread=\\\"(.*)\\\", (.*\\)), line=([0-9]*)");
00448 if (ex.search( buf) != -1 ) {
00449 kdDebug() << "MATCH\n";
00450 curMethod = ex.cap(2),
00451 curLine = ex.cap(3);
00452
00453
00454 if (currentCmd_ && currentCmd_->typeMatch(STEP)) {
00455 delete currentCmd_;
00456 currentCmd_ = 0;
00457 DBG_DISPLAY("Deleting step command");
00458 }
00459
00460 QString curClass = QString(ex.cap(2)).left(QString(ex.cap(2)).findRev("."));
00461 QString curFile = getFile(curClass);
00462 kdDebug() << "Filename: " << curFile <<endl;
00463 emit showStepInSource(curFile, atoi(ex.cap(3).latin1() ), "");
00464
00465 actOnProgramPause(QString("step completed, stopped in ") + ex.cap(2));
00466
00467 return buf + QString(buf).length();
00468 }
00469
00470 }
00471
00472 }
00473
00474 return 0;
00475 }
00476
00477
00478
00479 char* JDBController::parseInfo(char *buf)
00480 {
00481
00482
00483
00484 if (currentCmd_ && currentCmd_->typeMatch(BACKTRACE)) {
00485 return parseBacktrace(buf);
00486 } else if (currentCmd_ && currentCmd_->typeMatch(LOCALS)) {
00487 setStateOn(s_parsingLocals);
00488 return parseLocalVars(buf);
00489 } else if (currentCmd_ && currentCmd_->typeMatch(DATAREQUEST)) {
00490 setStateOn(s_parsingLocals);
00491 if (char* tmp = parseDump(buf)) { return tmp; }
00492 }
00493
00494 return 0;
00495 }
00496
00497
00498
00499
00500 char* JDBController::parseBacktrace(char* buf) {
00501 QRegExp* exp = 0;
00502
00503 exp = new QRegExp( "^ \\[[0-9]+\\][^\\)]+\\)");
00504 if (exp->search( buf) != -1) {
00505 DBG_DISPLAY(QString("Found some stacktrace output"));
00506 frameStack_->addItem(exp->cap(0).latin1() );
00507 stackLineCount++;
00508
00509 QString retQString = QString( buf + exp->cap(exp->numCaptures()) );
00510 memcpy( buf, retQString.latin1(), retQString.length() );
00511
00512 delete exp;
00513 return buf;
00514 }
00515
00516
00517 if (stackLineCount > 0) {
00518 kdDebug() << ">" << *buf<<endl;
00519 exp->setPattern("^[^ ]+\\[[0-9]+\\]");
00520 if (exp->search( buf) != -1) {
00521 DBG_DISPLAY(QString("Found end of stacktrace (prompt)"));
00522
00523 if (currentCmd_ && currentCmd_->typeMatch(BACKTRACE)) {
00524 delete currentCmd_;
00525 currentCmd_ = 0;
00526 }
00527
00528 setStateOff(s_parsingOutput);
00529
00530 frameStack_->updateDone();
00531
00532 QString retQString = QString( buf + exp->cap(exp->numCaptures()) );
00533 memcpy( buf, retQString.latin1(), retQString.length() );
00534
00535 delete exp;
00536 return buf;
00537
00538 }
00539 }
00540
00541
00542
00543 delete exp;
00544 return 0;
00545 }
00546
00547
00548
00549
00550 char* JDBController::parseLocalVars(char* buf) {
00551 QRegExp* exp = 0;
00552 exp = new QRegExp( "^Local variable information not available. Compile with -g to generate variable information\n");
00553 if (exp->search( buf) != -1) {
00554 DBG_DISPLAY(QString("No var info available"));
00555 if (currentCmd_ && currentCmd_->typeMatch(LOCALS)) {
00556 delete currentCmd_;
00557 currentCmd_ = 0;
00558 }
00559 varUpdateDone();
00560
00561 QString retQString = QString( buf + exp->cap(exp->numCaptures()) );
00562 memcpy( buf, retQString.latin1(), retQString.length() );
00563
00564 delete exp;
00565 return buf;
00566 }
00567
00568 exp->setPattern( "^No local variables");
00569 if (exp->search( buf) != -1) {
00570 DBG_DISPLAY(QString("No locals"));
00571
00572
00573 QString retQString = QString( buf + exp->cap(exp->numCaptures()) );
00574 memcpy( buf, retQString.latin1(), retQString.length() );
00575
00576 delete exp;
00577 return buf;
00578 }
00579
00580
00581
00582 exp->setPattern( "^ ([^ ]+) \\= ([^\\(\n]+)\\s*\\(id\\=[0-9]*\\)");
00583 if (exp->search( buf) != -1 ) {
00584 DBG_DISPLAY(QString("Var info:"));
00585 varLineCount++;
00586 kdDebug() << "Name: " << exp->cap(1) << endl;
00587 kdDebug() << "Type: " << exp->cap(2) << endl;
00588
00589
00590
00591 nameQueue.append(exp->cap(1));
00592
00593 QString retQString = QString( buf + exp->cap(exp->numCaptures()) );
00594 memcpy( buf, retQString.latin1(), retQString.length() );
00595
00596 delete exp;
00597 return buf;
00598
00599 }
00600
00601 exp->setPattern("^ ([^ ]+) \\= ([^\n]+)");
00602 if (exp->search( buf) != -1) {
00603 DBG_DISPLAY(QString("Local Var info:"));
00604
00605 varLineCount++;
00606 kdDebug() << "Name: " << exp->cap(1) << endl;
00607 kdDebug() << "Type: " << exp->cap(2) << endl;
00608
00609
00610 analyzeDump(exp->cap(0));
00611
00612 QString retQString = QString( buf + exp->cap(exp->numCaptures()) );
00613 memcpy( buf, retQString.latin1(), retQString.length() );
00614
00615 delete exp;
00616 return buf;
00617
00618 }
00619
00620
00621 exp->setPattern("^([^ ]+)\\[[0-9]+\\] ");
00622 if (exp->search(buf) != -1 ) {
00623 DBG_DISPLAY(QString("Found end of var dump (prompt)"));
00624 kdDebug() << ">" << exp->cap(0) << "<\n";
00625 if (currentCmd_ && currentCmd_->typeMatch(LOCALS)) {
00626 delete currentCmd_;
00627 currentCmd_ = 0;
00628 }
00629
00630 if (currentCmd_ && currentCmd_->typeMatch(LOCALS)) {
00631 delete currentCmd_;
00632 currentCmd_ = 0;
00633 }
00634 QString retQString = QString( buf + exp->cap(exp->numCaptures()) );
00635 memcpy( buf, retQString.latin1(), retQString.length() );
00636
00637 delete exp;
00638 return buf;
00639
00640
00641 }
00642 delete exp;
00643
00644 return 0;
00645 }
00646
00647
00648
00649
00650 char* JDBController::parseDump(char* buf) {
00651
00652 QRegExp *exp;
00653
00654
00655 exp = new QRegExp( "^([^ ]+) \\= ([^\\(]+)\\s*\\(id\\=[0-9]*\\) \\{([^\\}]+)\\}");
00656 if (exp->search( buf) != -1 ) {
00657 DBG_DISPLAY(QString("Found dump info"));
00658
00659 analyzeDump(exp->cap(0));
00660
00661 if (currentCmd_ && currentCmd_->typeMatch(DATAREQUEST)) {
00662 delete currentCmd_;
00663 currentCmd_ = 0;
00664 }
00665
00666 QString retQString = QString( buf + exp->cap(exp->numCaptures()) );
00667 memcpy( buf, retQString.latin1(), retQString.length() );
00668 delete exp;
00669 return buf;
00670 }
00671
00672
00673 exp->setPattern("^ ([^\\[]+\\[[0-9]+\\]) \\= ([^\n]+)");
00674 if (exp->search( buf) != -1 ) {
00675 DBG_DISPLAY(QString("Found dump info"));
00676 kdDebug() << "Array element: " << exp->cap(1) << " - " << exp->cap(2) << endl;
00677 analyzeDump(exp->cap(0));
00678
00679 if (currentCmd_ && currentCmd_->typeMatch(DATAREQUEST)) {
00680 delete currentCmd_;
00681 currentCmd_ = 0;
00682 }
00683
00684 QString retQString = QString( buf + exp->cap(exp->numCaptures()) );
00685 memcpy( buf, retQString.latin1(), retQString.length() );
00686
00687 delete exp;
00688 return buf;
00689 }
00690
00691 exp->setPattern("^No 'this'. In native or static method\n");
00692 if (exp->search( buf) != -1) {
00693
00694 if (currentCmd_ && currentCmd_->typeMatch(DATAREQUEST)) {
00695 delete currentCmd_;
00696 currentCmd_ = 0;
00697 }
00698
00699 QString retQString = QString( buf + exp->cap(exp->numCaptures()) );
00700 memcpy( buf, retQString.latin1(), retQString.length() );
00701
00702 delete exp;
00703 return buf;
00704 }
00705
00706 delete exp;
00707 return 0;
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 void JDBController::analyzeDump(QString data)
00726 {
00727
00728 kdDebug() << "Parsing dump: " << data << endl;
00729
00730
00731
00732 QRegExp *exp = new QRegExp( "^ ([^ \\[]+) \\= ([^\n]+)");
00733 if (exp->search(data.latin1()) != -1 ) {
00734 QString name = exp->cap(1);
00735 QString value = exp->cap(2);
00736 JDBVarItem *item = new JDBVarItem();
00737 item->value = value;
00738 item->name = name;
00739 if (!localData[name]) {
00740 kdDebug() << "inserting local var" << endl;
00741 localData.insert(name, item);
00742 } else { }
00743 delete exp;
00744 return;
00745
00746 }
00747
00748 exp->setPattern( " ([^ \\[]+)\\[([0-9]+)\\] \\= ([^\n]+)");
00749 if (exp->search(data.latin1()) != -1) {
00750 kdDebug() << "Array element: " << exp->cap(1) << "[" << exp->cap(2)<< "] = " << exp->cap(3) << endl;
00751
00752 QString name = exp->cap(1);
00753
00754 JDBVarItem *item;
00755 JDBVarItem *subItem = new JDBVarItem();
00756 subItem->name = QString(exp->cap(1)) + "[" + QString(exp->cap(2)) + "]";
00757 subItem->value = exp->cap(3);
00758 item = localData[name];
00759 Q_ASSERT((name != 0));
00760
00761
00762
00763
00764
00765 item->siblings.append(subItem);
00766
00767 delete exp;
00768 return;
00769 }
00770
00771
00772
00773 exp->setPattern( "^([^ ]+) \\= instance of ([^[]+)\\[([0-9])+] \\(id\\=[0-9]+\\) {");
00774 if (exp->search(data.latin1()) != -1 ) {
00775 kdDebug() << "Array...\n";
00776 kdDebug() << "Name: " << exp->cap(1) << endl;
00777 kdDebug() << "Type: " << exp->cap(2) << endl;
00778 kdDebug() << "Dimension: " << exp->cap(3) << endl;
00779
00780 kdDebug() << "Adding array to var tree... \n";
00781 JDBVarItem *item = new JDBVarItem();
00782 item->name = exp->cap(1);
00783 QString name = exp->cap(1);
00784 if (atoi(exp->cap(3).latin1()) == 0) {
00785 item->value="null";
00786 }
00787 if (!localData[name]) {
00788 kdDebug() << "inserting local var " << name << " at " << (int)item << endl;
00789 localData.insert(name, item);
00790 } else { }
00791
00792 for (int i=0; i<atoi(exp->cap(3).latin1()); i++) {
00793 kdDebug() << QString(exp->cap(1)) + QString("[") + QString::number((i)) + QString("]") << endl;
00794 nameQueue.append(QString(exp->cap(1)) + QString("[") + QString::number((i)) + QString("]"));
00795 }
00796
00797 delete exp;
00798 return;
00799 }
00800
00801
00802
00803
00804 exp->setPattern( "^([^ ]+) \\= ([^\\(]+)\\s*\\(id\\=[0-9]*\\) \\{([^\\}]+)\\}");
00805 if (exp->search(data.latin1()) != -1) {
00806 kdDebug() << "COMPOUND DATA" << endl;
00807
00808
00809 QString name = exp->cap(1);
00810 JDBVarItem *item;
00811 if (!localData[name]) {
00813 item = new JDBVarItem();
00814 kdDebug() << "NAME: " << name << " - " << (int)item << endl;
00815 item->name = name;
00816 localData.insert(name, item);
00817 } else {
00818
00819 item = localData[name];
00820 }
00821
00822
00823
00824 unsigned int i = data.find("{")+1;
00825 exp = new QRegExp("^([^ \\:]+): ([^\n]+)");
00826 QString tmp;
00827 while (i<data.length()) {
00828
00829 if (exp->search(data.mid(i).latin1()) != -1) {
00830 if (strncmp(exp->cap(2).latin1(), "instance of", 11) != 0) {
00831
00832 kdDebug() << "Primitive type..." << endl;
00833 QString fullName = name + QString(".") + QString(exp->cap(1));
00834
00835
00836 JDBVarItem *subItem = new JDBVarItem();
00837 subItem->value = exp->cap(2);
00838 subItem->name = fullName;
00839 if (!localData[fullName]) {
00840 localData.insert(fullName, subItem);
00841 } else { }
00842
00843
00844 item->siblings.append(subItem);
00845
00846
00847
00848 } else if (QString(exp->cap(2)).contains("[")) {
00849
00850
00851
00852 QString fullName = name + QString(".") + QString(exp->cap(1));
00853
00854 JDBVarItem *subItem = new JDBVarItem();
00855 subItem->name = fullName;
00856 if (!localData[fullName]) {
00857 localData.insert(fullName, subItem);
00858 } else { }
00859
00860
00861
00862
00863
00864 QRegExp *exp2 = new QRegExp("\\[([0-9]+)\\]");
00865 if (exp2->search(exp->cap(2)) != -1 ) {
00866 int dimension = atoi(exp2->cap(1).latin1());
00867 kdDebug() << "Array dimension: " << dimension << endl;
00868 for (int i=0; i<dimension; i++) {
00869 nameQueue.append(fullName + "[" + QString::number((i)) + "]");
00870 }
00871
00872
00873 item->siblings.append(subItem);
00874 }
00875
00876 } else {
00877
00878
00879 kdDebug() << "complex..." << endl;
00880 QString fullName = name + QString(".") + QString(exp->cap(1));
00881 nameQueue.append(fullName);
00882
00883 JDBVarItem *subItem = new JDBVarItem();
00884 subItem->name = fullName;
00885 if (!localData[fullName]) {
00886 localData.insert(fullName, subItem);
00887 } else { }
00888
00889 kdDebug() << "appending: " << fullName << " as " << (int)subItem << endl;
00890
00891
00892 item->siblings.append(subItem);
00893
00894
00895 }
00896 i += atoi( exp->cap(exp->numCaptures()).latin1() );
00897 } else {
00898 i++;
00899 }
00900 }
00901
00902 }
00903
00904 delete exp; exp = 0;
00905 }
00906
00907
00908
00909
00910 void JDBController::parseLocals()
00911 {
00912 if (!stateIsOn(s_parsingLocals)) { return; }
00913 if (currentCmd_) { return; }
00914 DBG_DISPLAY("Trying to continue with locals");
00915 if (!nameQueue.isEmpty()) {
00916 DBG_DISPLAY("Issueing newdump command");
00917 QString varName = nameQueue.first();
00918 nameQueue.remove(nameQueue.begin());
00919
00920 queueCmd(new JDBCommand(QString("dump " + varName).latin1(), NOTRUNCMD, INFOCMD, DATAREQUEST), FALSE);
00921 } else if (!parsedThis) {
00922 parsedThis = TRUE;
00923 queueCmd(new JDBCommand(QCString("dump this"), NOTRUNCMD, INFOCMD, DATAREQUEST), FALSE);
00924
00925 } else {
00926 parsedThis = FALSE;
00927 setStateOff(s_parsingLocals);
00928
00929 varUpdateDone();
00930 }
00931 }
00932
00933
00934
00935
00936 void JDBController::parseBacktraceList(char *)
00937 {
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957 void JDBController::parseFrameSelected(char *)
00958 {
00959 }
00960
00961
00962
00963
00964
00965 char *JDBController::parse(char *buf)
00966 {
00967
00968 if (stateIsOn(s_dbgNotStarted)) {
00969 kdDebug() << "dbgnotstarted" << endl;
00970
00971 kdDebug() << QString(buf).left(20) << endl;
00972 if (QString(buf).left(20) == "Initializing jdb...\n") { return buf+20; }
00973 if (QString(buf) == "> ") {
00974 setStateOff(s_dbgNotStarted);
00975 emit debuggerStarted();
00976 return buf + 2;
00977 }
00978 curLine = "";
00979 return buf++;
00980 }
00981
00982
00983 if (stateIsOn(s_appStarting)) {
00984 kdDebug() << "appstarting" << endl;
00985 char* unparsed = buf;
00986 char* orig = buf;
00987 while (*buf) {
00988 if ( (buf = parseLine(buf)) ) {
00989 return buf;
00990 } else {
00991 buf = ++unparsed;
00992 }
00993 }
00994 return orig;
00995 }
00996
00997
00998
00999
01000 if (stateIsOn(s_appBusy)) {
01001 kdDebug() << "\nApp busy:" << endl;
01002 char* unparsed = buf;
01003 char* orig = buf;
01004 while (*buf) {
01005 if ( (buf = parseLine(unparsed)) ) {
01006 return buf;
01007
01008
01009 } else {
01010 buf = ++unparsed;
01011 }
01012 }
01013 return orig;
01014
01015 } else {
01016
01017 kdDebug() << "\nApp is paused:" << endl;
01018 char* unparsed = buf;
01019 char* orig = buf;
01020 while (*buf) {
01021 if ( (buf = parseInfo(buf)) ) {
01022 unparsed = orig = buf;
01023 } else {
01024 buf = ++unparsed;
01025 }
01026 }
01027
01028 parseLocals();
01029
01030 return orig;
01031
01032 }
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 }
01051
01052
01053
01054 void JDBController::setBreakpoint(const QCString &, int )
01055 {
01056
01057 }
01058
01059
01060
01061 void JDBController::clearBreakpoint(const QCString &)
01062 {
01063
01064 }
01065
01066
01067
01068 void JDBController::modifyBreakpoint(Breakpoint *)
01069 {
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01082 void JDBController::slotStart(const QString &, const QString &args, const QString &sDbgShell)
01083 {
01084 Q_ASSERT (!dbgProcess_ && !tty_);
01085
01086
01087
01088
01089 tty_ = new STTY(config_dbgTerminal_, "konsole");
01090 if (!config_dbgTerminal_) {
01091 connect( tty_, SIGNAL(OutOutput(const char*)), SIGNAL(ttyStdout(const char*)) );
01092 connect( tty_, SIGNAL(ErrOutput(const char*)), SIGNAL(ttyStderr(const char*)) );
01093 }
01094
01095 QString tty(tty_->getSlave());
01096
01097 if (tty.isEmpty()) {
01098 KMessageBox::error(0, i18n("JDB cannot use the tty* or pty* devices.\n"
01099 "Check the settings on /dev/tty* and /dev/pty*\n"
01100 "As root you may need to \"chmod ug+rw\" tty* and pty* devices "
01101 "and/or add the user to the tty group using "
01102 "\"usermod -G tty username\""));
01103
01104 delete tty_;
01105 tty_ = 0;
01106 return;
01107 }
01108
01109 JDB_DISPLAY("\nStarting JDB - app:["+mainclass_+"] classpath:["+classpath_+"] args:["+args+"] sDbgShell:["+sDbgShell+"]\n");
01110 dbgProcess_ = new KProcess;
01111
01112 connect( dbgProcess_, SIGNAL(receivedStdout(KProcess *, char *, int)),
01113 this, SLOT(slotDbgStdout(KProcess *, char *, int)) );
01114
01115 connect( dbgProcess_, SIGNAL(receivedStderr(KProcess *, char *, int)),
01116 this, SLOT(slotDbgStderr(KProcess *, char *, int)) );
01117
01118 connect( dbgProcess_, SIGNAL(wroteStdin(KProcess *)),
01119 this, SLOT(slotDbgWroteStdin(KProcess *)) );
01120
01121 connect( dbgProcess_, SIGNAL(processExited(KProcess*)),
01122 this, SLOT(slotDbgProcessExited(KProcess*)) );
01123
01124
01125 if (!sDbgShell.isEmpty())
01126 *dbgProcess_<<"/bin/sh"<<"-c"<<sDbgShell+" "+config_jdbPath_+
01127 QString("jdb")<<"-classpath"<<classpath_<<mainclass_<<args;
01128 else
01129 *dbgProcess_<<config_jdbPath_+QString("jdb")<<"-classpath"<<classpath_<<mainclass_<<args;
01130
01131 if (! dbgProcess_->start( KProcess::NotifyOnExit,
01132 KProcess::Communication(KProcess::All) ) )
01133 {
01134 JDB_DISPLAY("\nFailed to start JDB - app:["+mainclass_+"]\n");
01135 }
01136
01137
01138 setStateOn(s_dbgNotStarted);
01139 emit dbgStatus ("", state_);
01140
01141
01142
01143
01144
01145 }
01146
01147
01148
01149 void JDBController::slotCoreFile(const QString&)
01150 {
01151 }
01152
01153
01154 void JDBController::slotAttachTo(int)
01155 {
01156 }
01157
01158
01159
01160 void JDBController::slotDebuggerStarted() {
01161 kdDebug() << "slotRun()" << endl;
01162 if (stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01163 return;
01164 bool first_flag = FALSE;
01165
01166 kdDebug() << "slotRun()" << endl;
01167 if (stateIsOn(s_appNotStarted)) {
01168 first_flag = TRUE;
01169 queueCmd(new JDBCommand(QString("stop in " + mainclass_ + ".main(java.lang.String[])" ).latin1() , NOTRUNCMD, NOTINFOCMD, 0 ) );
01170 }
01171
01172 queueCmd(new JDBCommand(stateIsOn(s_appNotStarted) ? "run" : "cont", RUNCMD, NOTINFOCMD, 0));
01173
01174
01175 setStateOn(s_appStarting);
01176 }
01177
01178 void JDBController::slotRun()
01179 {
01180 if (stateIsOn(s_dbgNotStarted)) {
01181
01182
01183 connect(this, SIGNAL(debuggerStarted()), SLOT(slotDebuggerStarted()));
01184 } else {
01185
01186 }
01187
01188 }
01189
01190
01191
01192 void JDBController::slotRunUntil(const QString &, int)
01193 {
01194 }
01195
01196
01197
01198 void JDBController::slotStepInto()
01199 {
01200 kdDebug() << "slotStepInstruction" << endl;
01201 if (stateIsOn(s_dbgNotStarted) || stateIsOn(s_appBusy) || stateIsOn(s_parsingOutput)) { return; }
01202 queueCmd(new JDBCommand("stepi", RUNCMD, NOTINFOCMD, 0));
01203 }
01204
01205
01206
01207 void JDBController::slotStepIntoIns()
01208 {
01209 }
01210
01211
01212
01213 void JDBController::slotStepOver() {
01214 kdDebug() << "slotStepOver" << endl;
01215 if (stateIsOn(s_appStarting) || stateIsOn(s_dbgNotStarted) || stateIsOn(s_appBusy) || stateIsOn(s_parsingOutput)) { return; }
01216 queueCmd(new JDBCommand("step", RUNCMD, NOTINFOCMD, 0));
01217 }
01218
01219
01220
01221 void JDBController::slotStepOverIns()
01222 {
01223 }
01224
01225
01226
01227 void JDBController::slotStepOutOff()
01228 {
01229 }
01230
01231
01232
01233
01234 void JDBController::slotBreakInto()
01235 {
01236 }
01237
01238
01239
01240
01241 void JDBController::slotBPState(Breakpoint *)
01242 {
01243 }
01244
01245
01246
01247 void JDBController::slotClearAllBreakpoints()
01248 {
01249 }
01250
01251
01252
01253 void JDBController::slotDisassemble(const QString &, const QString &)
01254 {
01255 }
01256
01257
01258
01259 void JDBController::slotMemoryDump(const QString &, const QString &)
01260 {
01261 }
01262
01263
01264
01265 void JDBController::slotRegisters()
01266 {
01267 }
01268
01269
01270
01271 void JDBController::slotLibraries()
01272 {
01273 }
01274
01275
01276
01277 void JDBController::slotSelectFrame(int)
01278 {
01279 }
01280
01281
01282
01283
01284
01285 void JDBController::slotExpandItem(VarItem *)
01286 {
01287 }
01288
01289
01290
01291
01292
01293
01294 void JDBController::slotExpandUserItem(VarItem *, const QCString& )
01295 {
01296 }
01297
01298
01299
01300
01301
01303 void JDBController::slotSetLocalViewState(bool)
01304 {
01305 }
01306
01307
01308
01309
01310 void JDBController::slotDbgStdout(KProcess *, char *buf, int buflen)
01311 {
01312
01313 if (jdbOutputLen_+buflen+1 > jdbSizeofBuf_) {
01314 jdbSizeofBuf_ = jdbOutputLen_+buflen+1;
01315 char *newBuf = new char[jdbSizeofBuf_];
01316 if (jdbOutputLen_)
01317 memcpy(newBuf, jdbOutput_, jdbOutputLen_+1);
01318 delete[] jdbOutput_;
01319 jdbOutput_ = newBuf;
01320 }
01321
01322
01323
01324 memcpy(jdbOutput_+jdbOutputLen_, buf, buflen);
01325 jdbOutputLen_ += buflen;
01326 *(jdbOutput_+jdbOutputLen_) = 0;
01327
01328 if (char *nowAt = parse(jdbOutput_)) {
01329 Q_ASSERT(nowAt <= jdbOutput_+jdbOutputLen_+1);
01330 jdbOutputLen_ = strlen(nowAt);
01331
01332 if (jdbOutputLen_)
01333 memmove(jdbOutput_, nowAt, jdbOutputLen_);
01334
01335 }
01336
01337 executeCmd();
01338 kdDebug() << "stdout" << endl;
01339 }
01340
01341
01342
01343 void JDBController::slotDbgStderr(KProcess *, char *buf, int)
01344 {
01345
01346
01347 kdDebug() << "STDERR\n";
01348 DBG_DISPLAY(QString("\nSTDERR: ")+QString(buf));
01349
01350 }
01351
01352
01353
01354 void JDBController::slotDbgWroteStdin(KProcess *)
01355 {
01356 setStateOff(s_waitForWrite);
01357 executeCmd();
01358 kdDebug() << "dbgwrotestdin" << endl;
01359 }
01360
01361
01362
01363 void JDBController::slotDbgProcessExited(KProcess*)
01364 {
01365 destroyCmds();
01366 state_ = s_appNotStarted|s_programExited|(state_&s_viewLocals);
01367 emit dbgStatus (i18n("Process exited"), state_);
01368
01369 JDB_DISPLAY(QString("\n(jdb) Process exited"));
01370 }
01371
01372
01373
01374
01381 QString JDBController::getFile(QString className)
01382 {
01383 return QString(projectDirectory_ + "/" + className + ".java");
01384 }
01385
01386
01387
01388 void JDBController::varUpdateDone()
01389 {
01390 kdDebug() << "VarUpdateDone" << endl;
01391
01392 QString locals = "";
01393 QDictIterator<JDBVarItem> it(localData);
01394 if (!it.toFirst()) { return; }
01395
01396 while (it.current()) {
01397
01398 if (!it.currentKey().contains(".")) {
01399 locals += it.current()->toString() + QString(",");
01400 }
01401 ++it;
01402 }
01403
01404 locals[locals.length()-1] = ' ';
01405 char* _l = new char[locals.length()];
01406 strcpy(_l, locals.latin1());
01407 kdDebug() << "\nLocals: "<< _l << endl;
01408
01409
01410 varTree_->trim();
01411
01412 FrameRoot *frame;
01413
01414
01415 if (!(frame = varTree_->findFrame(currentFrame_)))
01416 frame = new FrameRoot(varTree_, currentFrame_);
01417
01418 Q_ASSERT(frame);
01419 frame->setFrameName(frameStack_->getFrameName(currentFrame_));
01420
01421 frame->setLocals(_l);
01422
01423 varTree_->viewport()->setUpdatesEnabled(true);
01424 varTree_->repaint();
01425 localData.clear();
01426 setStateOff(s_parsingOutput);
01427
01428 }
01429
01430
01431
01432 void JDBController::slotAbortTimedEvent()
01433 {
01434 setStateOff(s_waitTimer);
01435 DBG_DISPLAY(QString("Timer aborted\n"));
01436 }
01437
01438
01439
01440 void JDBController::slotStepInSource(const QString &fileName, int lineNum)
01441 {
01442 DBG_DISPLAY((QString("(Show step in source) ")+fileName+QString(":")
01443 +QString().setNum(lineNum)).local8Bit().data());
01444 }
01445
01446
01447
01448 void JDBController::slotDbgStatus(const QString &status, int state)
01449 {
01450 QString s("(status) ");
01451 if (!state)
01452 s += QString("<program paused>");
01453 if (state & s_dbgNotStarted)
01454 s += QString("<dbg not started>");
01455 if (state & s_appNotStarted)
01456 s += QString("<app not started>");
01457 if (state & s_appBusy)
01458 s += QString("<app busy>");
01459 if (state & s_waitForWrite)
01460 s += QString("<wait for write>");
01461 if (state & s_programExited)
01462 s += QString("<program exited>");
01463 if (state & s_silent)
01464 s += QString("<silent>");
01465 if (state & s_viewLocals)
01466 s += QString("<viewing locals>");
01467
01468 DBG_DISPLAY((s+status).local8Bit().data());
01469 }
01470
01471
01472 JDBVarItem::JDBVarItem() {
01473 value = "";
01474 name = "";
01475 }
01476
01477 QString JDBVarItem::toString() {
01478 if (!value.isEmpty()) {
01479 kdDebug() << value <<" - ";
01480 return name + " = " + value;
01481 } else {
01482
01483 QString tmp;
01484 JDBVarItem *item;
01485
01486 for (item = this->siblings.first(); item != 0; item = this->siblings.next()) {
01487 tmp += item->toString() + ",";
01488 delete item;
01489 }
01490
01491 tmp = name + " = {" +tmp;
01492 tmp[tmp.length()-1] = '}';
01493 return tmp;
01494 }
01495 }
01496
01497 }
01498
01499
01500 #include "jdbcontroller.moc"