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 <kregexp.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
KRegExp ex(
"Breakpoint hit: thread=\\\"(.*)\\\", (.*\\)), line=([0-9]*), bci\\=[0-9]*.*\\n[^\\[]*\\[[0-9]*\\] ");
00417
if (ex.
match( buf)) {
00418
DBG_DISPLAY(
QString(
"Breakpoint hit in line ") + ex.
group(3));
00419
if (
stateIsOn(
s_appStarting)) {
00420
setStateOff(
s_appStarting);
00421 }
00422
curMethod = ex.
group(2),
00423
curLine = ex.
group(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.
group(3)),
"");
00435
actOnProgramPause(
QString(
"Reached Breakpoint in line ")+ex.
group(3));
00436
00437
return buf + ex.
groupEnd(0);
00438 }
00439
00440 }
00441 }
else if (memcmp(buf,
"Step", 4) == 0) {
00442
if ((strncmp(buf,
"Step completed:", 15) == 0)) {
00443
kdDebug() <<
"STEP: " << buf <<
endl;
00444
KRegExp ex(
" thread=\\\"(.*)\\\", (.*\\)), line=([0-9]*)");
00445
if (ex.
match( buf)) {
00446
kdDebug() <<
"MATCH\n";
00447
curMethod = ex.
group(2),
00448
curLine = ex.
group(3);
00449
00450
00451
if (
currentCmd_ &&
currentCmd_->
typeMatch(
STEP)) {
00452
delete currentCmd_;
00453
currentCmd_ = 0;
00454
DBG_DISPLAY(
"Deleting step command");
00455 }
00456
00457
QString curClass =
QString(ex.
group(2)).left(QString(ex.
group(2)).findRev(
"."));
00458 QString curFile =
getFile(curClass);
00459
kdDebug() <<
"Filename: " << curFile <<
endl;
00460 emit
showStepInSource(curFile, atoi(ex.
group(3)),
"");
00461
00462
actOnProgramPause(QString(
"step completed, stopped in ") + ex.
group(2));
00463
00464
return buf + QString(buf).length();
00465 }
00466
00467 }
00468
00469 }
00470
00471
return 0;
00472 }
00473
00474
00475
00476 char* JDBController::parseInfo(
char *buf)
00477 {
00478
00479
00480
00481
if (
currentCmd_ &&
currentCmd_->
typeMatch(BACKTRACE)) {
00482
return parseBacktrace(buf);
00483 }
else if (
currentCmd_ &&
currentCmd_->
typeMatch(LOCALS)) {
00484
setStateOn(
s_parsingLocals);
00485
return parseLocalVars(buf);
00486 }
else if (
currentCmd_ &&
currentCmd_->
typeMatch(DATAREQUEST)) {
00487
setStateOn(
s_parsingLocals);
00488
if (
char* tmp =
parseDump(buf)) {
return tmp; }
00489 }
00490
00491
return 0;
00492 }
00493
00494
00495
00496
00497 char* JDBController::parseBacktrace(
char* buf) {
00498
KRegExp* exp = 0;
00499
00500 exp =
new KRegExp(
"^ \\[[0-9]+\\][^\\)]+\\)");
00501
if (exp->
match( buf)) {
00502
DBG_DISPLAY(
QString(
"Found some stacktrace output"));
00503
frameStack_->
addItem(exp->
group(0));
00504
stackLineCount++;
00505 buf += exp->
groupEnd(0);
00506
delete exp;
00507
return buf;
00508 }
00509
00510
00511
if (
stackLineCount > 0) {
00512
kdDebug() <<
">" << *buf<<
endl;
00513 exp->
compile(
"^[^ ]+\\[[0-9]+\\]");
00514
if (exp->
match( buf)) {
00515
DBG_DISPLAY(
QString(
"Found end of stacktrace (prompt)"));
00516
00517
if (
currentCmd_ &&
currentCmd_->
typeMatch(BACKTRACE)) {
00518
delete currentCmd_;
00519
currentCmd_ = 0;
00520 }
00521
00522
setStateOff(
s_parsingOutput);
00523
00524
frameStack_->
updateDone();
00525 buf += exp->
groupEnd(0);
00526
delete exp;
00527
return buf;
00528
00529 }
00530 }
00531
00532
00533
00534
delete exp;
00535
return 0;
00536 }
00537
00538
00539
00540
00541 char* JDBController::parseLocalVars(
char* buf) {
00542
KRegExp* exp = 0;
00543 exp =
new KRegExp(
"^Local variable information not available. Compile with -g to generate variable information\n");
00544
if (exp->
match( buf)) {
00545
DBG_DISPLAY(
QString(
"No var info available"));
00546
if (
currentCmd_ &&
currentCmd_->
typeMatch(LOCALS)) {
00547
delete currentCmd_;
00548
currentCmd_ = 0;
00549 }
00550
varUpdateDone();
00551 buf += exp->
groupEnd(0);
00552
delete exp;
00553
return buf;
00554 }
00555
00556 exp->
compile(
"^No local variables");
00557
if (exp->
match( buf)) {
00558
DBG_DISPLAY(
QString(
"No locals"));
00559
00560
00561 buf += exp->
groupEnd(0);
00562
delete exp;
00563
return buf;
00564 }
00565
00566
00567
00568 exp->
compile(
"^ ([^ ]+) \\= ([^\\(\n]+)\\s*\\(id\\=[0-9]*\\)");
00569
if (exp->
match( buf)) {
00570
DBG_DISPLAY(
QString(
"Var info:"));
00571
varLineCount++;
00572
kdDebug() <<
"Name: " << exp->
group(1) <<
endl;
00573
kdDebug() <<
"Type: " << exp->
group(2) <<
endl;
00574
00575
00576
00577
nameQueue.append(exp->
group(1));
00578
00579 buf += exp->
groupEnd(0);
00580
delete exp;
00581
return buf;
00582
00583 }
00584
00585 exp->
compile(
"^ ([^ ]+) \\= ([^\n]+)");
00586
if (exp->
match( buf)) {
00587
DBG_DISPLAY(
QString(
"Local Var info:"));
00588
00589
varLineCount++;
00590
kdDebug() <<
"Name: " << exp->
group(1) <<
endl;
00591
kdDebug() <<
"Type: " << exp->
group(2) <<
endl;
00592
00593
00594
analyzeDump(exp->
group(0));
00595
00596 buf += exp->
groupEnd(0);
00597
delete exp;
00598
return buf;
00599
00600 }
00601
00602
00603 exp->
compile(
"^([^ ]+)\\[[0-9]+\\] ");
00604
if (exp->
match(buf)) {
00605
DBG_DISPLAY(
QString(
"Found end of var dump (prompt)"));
00606
kdDebug() <<
">" << exp->
group(0) <<
"<\n";
00607
if (
currentCmd_ &&
currentCmd_->
typeMatch(LOCALS)) {
00608
delete currentCmd_;
00609
currentCmd_ = 0;
00610 }
00611
00612
if (
currentCmd_ &&
currentCmd_->
typeMatch(LOCALS)) {
00613
delete currentCmd_;
00614
currentCmd_ = 0;
00615 }
00616
00617 buf += exp->
groupEnd(0);
00618
delete exp;
00619
return buf;
00620
00621
00622 }
00623
delete exp;
00624
00625
return 0;
00626 }
00627
00628
00629
00630
00631 char* JDBController::parseDump(
char* buf) {
00632
00633
KRegExp *exp;
00634
00635
00636 exp =
new KRegExp(
"^([^ ]+) \\= ([^\\(]+)\\s*\\(id\\=[0-9]*\\) \\{([^\\}]+)\\}");
00637
if (exp->
match( buf)) {
00638
DBG_DISPLAY(
QString(
"Found dump info"));
00639
00640
analyzeDump(exp->
group(0));
00641
00642
if (
currentCmd_ &&
currentCmd_->
typeMatch(DATAREQUEST)) {
00643
delete currentCmd_;
00644
currentCmd_ = 0;
00645 }
00646
00647 buf += exp->
groupEnd(0);
00648
delete exp;
00649
return buf;
00650 }
00651
00652
00653 exp->
compile(
"^ ([^\\[]+\\[[0-9]+\\]) \\= ([^\n]+)");
00654
if (exp->
match( buf)) {
00655
DBG_DISPLAY(
QString(
"Found dump info"));
00656
kdDebug() <<
"Array element: " << exp->
group(1) <<
" - " << exp->
group(2) <<
endl;
00657
analyzeDump(exp->
group(0));
00658
00659
if (
currentCmd_ &&
currentCmd_->
typeMatch(DATAREQUEST)) {
00660
delete currentCmd_;
00661
currentCmd_ = 0;
00662 }
00663
00664
00665 buf += exp->
groupEnd(0);
00666
delete exp;
00667
return buf;
00668 }
00669
00670 exp->
compile(
"^No 'this'. In native or static method\n");
00671
if (exp->
match( buf)) {
00672
00673
if (
currentCmd_ &&
currentCmd_->
typeMatch(DATAREQUEST)) {
00674
delete currentCmd_;
00675
currentCmd_ = 0;
00676 }
00677
00678 buf += exp->
groupEnd(0);
00679
delete exp;
00680
return buf;
00681 }
00682
00683
delete exp;
00684
return 0;
00685 }
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 void JDBController::analyzeDump(
QString data)
00703 {
00704
00705
kdDebug() <<
"Parsing dump: " << data <<
endl;
00706
00707
00708
00709
KRegExp *exp =
new KRegExp(
"^ ([^ \\[]+) \\= ([^\n]+)");
00710
if (exp->
match(data.latin1())) {
00711
QString name = exp->
group(1);
00712
QString value = exp->
group(2);
00713
JDBVarItem *item =
new JDBVarItem();
00714 item->
value = value;
00715 item->
name = name;
00716
if (!
localData[name]) {
00717
kdDebug() <<
"inserting local var" <<
endl;
00718
localData.insert(name, item);
00719 }
else { }
00720
delete exp;
00721
return;
00722
00723 }
00724
00725 exp->
compile(
" ([^ \\[]+)\\[([0-9]+)\\] \\= ([^\n]+)");
00726
if (exp->
match(data.latin1())) {
00727
kdDebug() <<
"Array element: " << exp->
group(1) <<
"[" << exp->
group(2)<<
"] = " << exp->
group(3) <<
endl;
00728
00729
QString name = exp->
group(1);
00730
00731
JDBVarItem *item;
00732
JDBVarItem *subItem =
new JDBVarItem();
00733 subItem->
name =
QString(exp->
group(1)) +
"[" +
QString(exp->
group(2)) +
"]";
00734 subItem->
value = exp->
group(3);
00735 item =
localData[name];
00736 Q_ASSERT((name != 0));
00737
00738
00739
00740
00741
00742 item->
siblings.append(subItem);
00743
00744
delete exp;
00745
return;
00746 }
00747
00748
00749
00750 exp->
compile(
"^([^ ]+) \\= instance of ([^[]+)\\[([0-9])+] \\(id\\=[0-9]+\\) {");
00751
if (exp->
match(data.latin1())) {
00752
kdDebug() <<
"Array...\n";
00753
kdDebug() <<
"Name: " << exp->
group(1) <<
endl;
00754
kdDebug() <<
"Type: " << exp->
group(2) <<
endl;
00755
kdDebug() <<
"Dimension: " << exp->
group(3) <<
endl;
00756
00757
kdDebug() <<
"Adding array to var tree... \n";
00758
JDBVarItem *item =
new JDBVarItem();
00759 item->
name = exp->
group(1);
00760
QString name = exp->
group(1);
00761
if (atoi(exp->
group(3)) == 0) {
00762 item->
value=
"null";
00763 }
00764
if (!
localData[name]) {
00765
kdDebug() <<
"inserting local var " << name <<
" at " << (
int)item <<
endl;
00766
localData.insert(name, item);
00767 }
else { }
00768
00769
for (
int i=0; i<atoi(exp->
group(3)); i++) {
00770
kdDebug() <<
QString(exp->
group(1)) +
QString(
"[") + QString::number((i)) +
QString(
"]") <<
endl;
00771
nameQueue.append(
QString(exp->
group(1)) +
QString(
"[") + QString::number((i)) +
QString(
"]"));
00772 }
00773
00774
delete exp;
00775
return;
00776 }
00777
00778
00779
00780
00781 exp->
compile(
"^([^ ]+) \\= ([^\\(]+)\\s*\\(id\\=[0-9]*\\) \\{([^\\}]+)\\}");
00782
if (exp->
match(data.latin1())) {
00783
kdDebug() <<
"COMPOUND DATA" <<
endl;
00784
00785
00786
QString name = exp->
group(1);
00787
JDBVarItem *item;
00788
if (!
localData[name]) {
00790 item =
new JDBVarItem();
00791
kdDebug() <<
"NAME: " << name <<
" - " << (
int)item <<
endl;
00792 item->
name = name;
00793
localData.insert(name, item);
00794 }
else {
00795
00796 item =
localData[name];
00797 }
00798
00799
00800
00801
unsigned int i = data.find(
"{")+1;
00802 exp =
new KRegExp(
"^([^ \\:]+): ([^\n]+)");
00803
QString tmp;
00804
while (i<data.length()) {
00805
00806
if (exp->
match(data.mid(i).latin1())) {
00807
if (strncmp(exp->
group(2),
"instance of", 11) != 0) {
00808
00809
kdDebug() <<
"Primitive type..." <<
endl;
00810
QString fullName = name +
QString(
".") + QString(exp->
group(1));
00811
00812
00813
JDBVarItem *subItem =
new JDBVarItem();
00814 subItem->
value = exp->
group(2);
00815 subItem->
name = fullName;
00816
if (!
localData[fullName]) {
00817
localData.insert(fullName, subItem);
00818 }
else { }
00819
00820
00821 item->
siblings.append(subItem);
00822
00823
00824
00825 }
else if (
QString(exp->
group(2)).contains(
"[")) {
00826
00827
00828
00829
QString fullName = name +
QString(
".") + QString(exp->
group(1));
00830
00831
JDBVarItem *subItem =
new JDBVarItem();
00832 subItem->
name = fullName;
00833
if (!
localData[fullName]) {
00834
localData.insert(fullName, subItem);
00835 }
else { }
00836
00837
00838
00839
00840
00841 KRegExp *exp2 =
new KRegExp(
"\\[([0-9]+)\\]");
00842
if (exp2->
match(exp->
group(2))) {
00843
int dimension = atoi(exp2->
group(1));
00844
kdDebug() <<
"Array dimension: " << dimension <<
endl;
00845
for (
int i=0; i<dimension; i++) {
00846
nameQueue.append(fullName +
"[" + QString::number((i)) +
"]");
00847 }
00848
00849
00850 item->
siblings.append(subItem);
00851 }
00852
00853 }
else {
00854
00855
00856
kdDebug() <<
"complex..." <<
endl;
00857
QString fullName = name +
QString(
".") + QString(exp->
group(1));
00858
nameQueue.append(fullName);
00859
00860
JDBVarItem *subItem =
new JDBVarItem();
00861 subItem->
name = fullName;
00862
if (!
localData[fullName]) {
00863
localData.insert(fullName, subItem);
00864 }
else { }
00865
00866
kdDebug() <<
"appending: " << fullName <<
" as " << (
int)subItem <<
endl;
00867
00868
00869 item->
siblings.append(subItem);
00870
00871
00872 }
00873 i += exp->
groupEnd(0);
00874 }
else {
00875 i++;
00876 }
00877 }
00878
00879 }
00880
00881
delete exp; exp = 0;
00882 }
00883
00884
00885
00886
00887 void JDBController::parseLocals()
00888 {
00889
if (!
stateIsOn(
s_parsingLocals)) {
return; }
00890
if (
currentCmd_) {
return; }
00891
DBG_DISPLAY(
"Trying to continue with locals");
00892
if (!
nameQueue.isEmpty()) {
00893
DBG_DISPLAY(
"Issueing newdump command");
00894
QString varName =
nameQueue.first();
00895
nameQueue.remove(
nameQueue.begin());
00896
00897
queueCmd(
new JDBCommand(
QString(
"dump " + varName).latin1(),
NOTRUNCMD,
INFOCMD, DATAREQUEST), FALSE);
00898 }
else if (!
parsedThis) {
00899
parsedThis = TRUE;
00900
queueCmd(
new JDBCommand(
QCString(
"dump this"),
NOTRUNCMD,
INFOCMD, DATAREQUEST), FALSE);
00901
00902 }
else {
00903
parsedThis = FALSE;
00904
setStateOff(
s_parsingLocals);
00905
00906
varUpdateDone();
00907 }
00908 }
00909
00910
00911
00912
00913 void JDBController::parseBacktraceList(
char *)
00914 {
00915 }
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934 void JDBController::parseFrameSelected(
char *)
00935 {
00936 }
00937
00938
00939
00940
00941
00942 char *JDBController::parse(
char *buf)
00943 {
00944
00945
if (
stateIsOn(s_dbgNotStarted)) {
00946
kdDebug() <<
"dbgnotstarted" <<
endl;
00947
00948
kdDebug() <<
QString(buf).left(20) <<
endl;
00949
if (
QString(buf).left(20) ==
"Initializing jdb...\n") {
return buf+20; }
00950
if (
QString(buf) ==
"> ") {
00951
setStateOff(s_dbgNotStarted);
00952 emit
debuggerStarted();
00953
return buf + 2;
00954 }
00955
curLine =
"";
00956
return buf++;
00957 }
00958
00959
00960
if (
stateIsOn(
s_appStarting)) {
00961
kdDebug() <<
"appstarting" <<
endl;
00962
char* unparsed = buf;
00963
char* orig = buf;
00964
while (*buf) {
00965
if ( (buf =
parseLine(buf)) ) {
00966
return buf;
00967 }
else {
00968 buf = ++unparsed;
00969 }
00970 }
00971
return orig;
00972 }
00973
00974
00975
00976
00977
if (
stateIsOn(s_appBusy)) {
00978
kdDebug() <<
"\nApp busy:" <<
endl;
00979
char* unparsed = buf;
00980
char* orig = buf;
00981
while (*buf) {
00982
if ( (buf =
parseLine(unparsed)) ) {
00983
return buf;
00984
00985
00986 }
else {
00987 buf = ++unparsed;
00988 }
00989 }
00990
return orig;
00991
00992 }
else {
00993
00994
kdDebug() <<
"\nApp is paused:" <<
endl;
00995
char* unparsed = buf;
00996
char* orig = buf;
00997
while (*buf) {
00998
if ( (buf =
parseInfo(buf)) ) {
00999 unparsed = orig = buf;
01000 }
else {
01001 buf = ++unparsed;
01002 }
01003 }
01004
01005
parseLocals();
01006
01007
return orig;
01008
01009 }
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027 }
01028
01029
01030
01031 void JDBController::setBreakpoint(
const QCString &,
int )
01032 {
01033
01034 }
01035
01036
01037
01038 void JDBController::clearBreakpoint(
const QCString &)
01039 {
01040
01041 }
01042
01043
01044
01045 void JDBController::modifyBreakpoint(
Breakpoint *)
01046 {
01047 }
01048
01049
01050
01051
01052
01053
01054
01055
01059 void JDBController::slotStart(
const QString &,
const QString &args,
const QString &sDbgShell)
01060 {
01061 Q_ASSERT (!dbgProcess_ && !
tty_);
01062
01063
01064
01065
01066 tty_ =
new STTY(
config_dbgTerminal_,
"konsole");
01067
if (!
config_dbgTerminal_) {
01068 connect( tty_, SIGNAL(OutOutput(
const char*)), SIGNAL(
ttyStdout(
const char*)) );
01069 connect( tty_, SIGNAL(ErrOutput(
const char*)), SIGNAL(
ttyStderr(
const char*)) );
01070 }
01071
01072
QString tty(tty_->getSlave());
01073
01074
if (tty.isEmpty()) {
01075 KMessageBox::error(0, i18n(
"JDB cannot use the tty* or pty* devices.\n"
01076
"Check the settings on /dev/tty* and /dev/pty*\n"
01077
"As root you may need to \"chmod ug+rw\" tty* and pty* devices "
01078
"and/or add the user to the tty group using "
01079
"\"usermod -G tty username\""));
01080
01081
delete tty_;
01082 tty_ = 0;
01083
return;
01084 }
01085
01086
JDB_DISPLAY(
"\nStarting JDB - app:["+
mainclass_+
"] classpath:["+
classpath_+
"] args:["+args+
"] sDbgShell:["+sDbgShell+
"]\n");
01087 dbgProcess_ =
new KProcess;
01088
01089 connect( dbgProcess_, SIGNAL(receivedStdout(KProcess *,
char *,
int)),
01090
this, SLOT(
slotDbgStdout(KProcess *,
char *,
int)) );
01091
01092 connect( dbgProcess_, SIGNAL(receivedStderr(KProcess *,
char *,
int)),
01093
this, SLOT(
slotDbgStderr(KProcess *,
char *,
int)) );
01094
01095 connect( dbgProcess_, SIGNAL(wroteStdin(KProcess *)),
01096
this, SLOT(
slotDbgWroteStdin(KProcess *)) );
01097
01098 connect( dbgProcess_, SIGNAL(processExited(KProcess*)),
01099
this, SLOT(
slotDbgProcessExited(KProcess*)) );
01100
01101
01102
if (!sDbgShell.isEmpty())
01103 *dbgProcess_<<
"/bin/sh"<<
"-c"<<sDbgShell+
" "+
config_jdbPath_+
01104
QString(
"jdb")<<
"-classpath"<<
classpath_<<
mainclass_<<args;
01105
else
01106 *dbgProcess_<<
config_jdbPath_+QString(
"jdb")<<
"-classpath"<<
classpath_<<
mainclass_<<args;
01107
01108
if (! dbgProcess_->
start( KProcess::NotifyOnExit,
01109 KProcess::Communication(KProcess::All) ) )
01110 {
01111
JDB_DISPLAY(
"\nFailed to start JDB - app:["+
mainclass_+
"]\n");
01112 }
01113
01114
01115
setStateOn(s_dbgNotStarted);
01116 emit
dbgStatus (
"",
state_);
01117
01118
01119
01120
01121
01122 }
01123
01124
01125
01126 void JDBController::slotCoreFile(
const QString&)
01127 {
01128 }
01129
01130
01131 void JDBController::slotAttachTo(
int)
01132 {
01133 }
01134
01135
01136
01137 void JDBController::slotDebuggerStarted() {
01138
kdDebug() <<
"slotRun()" <<
endl;
01139
if (
stateIsOn(s_appBusy|s_dbgNotStarted|s_shuttingDown))
01140
return;
01141
bool first_flag = FALSE;
01142
01143
kdDebug() <<
"slotRun()" <<
endl;
01144
if (
stateIsOn(s_appNotStarted)) {
01145 first_flag = TRUE;
01146
queueCmd(
new JDBCommand(
QString(
"stop in " +
mainclass_ +
".main(java.lang.String[])" ).latin1() ,
NOTRUNCMD,
NOTINFOCMD, 0 ) );
01147 }
01148
01149
queueCmd(
new JDBCommand(
stateIsOn(s_appNotStarted) ?
"run" :
"cont",
RUNCMD,
NOTINFOCMD, 0));
01150
01151
01152
setStateOn(
s_appStarting);
01153 }
01154
01155 void JDBController::slotRun()
01156 {
01157
if (
stateIsOn(s_dbgNotStarted)) {
01158
01159
01160 connect(
this, SIGNAL(
debuggerStarted()), SLOT(
slotDebuggerStarted()));
01161 }
else {
01162
01163 }
01164
01165 }
01166
01167
01168
01169 void JDBController::slotRunUntil(
const QString &,
int)
01170 {
01171 }
01172
01173
01174
01175 void JDBController::slotStepInto()
01176 {
01177
kdDebug() <<
"slotStepInstruction" <<
endl;
01178
if (
stateIsOn(s_dbgNotStarted) ||
stateIsOn(s_appBusy) ||
stateIsOn(
s_parsingOutput)) {
return; }
01179
queueCmd(
new JDBCommand(
"stepi",
RUNCMD,
NOTINFOCMD, 0));
01180 }
01181
01182
01183
01184 void JDBController::slotStepIntoIns()
01185 {
01186 }
01187
01188
01189
01190 void JDBController::slotStepOver() {
01191
kdDebug() <<
"slotStepOver" <<
endl;
01192
if (
stateIsOn(
s_appStarting) ||
stateIsOn(s_dbgNotStarted) ||
stateIsOn(s_appBusy) ||
stateIsOn(
s_parsingOutput)) {
return; }
01193
queueCmd(
new JDBCommand(
"step",
RUNCMD,
NOTINFOCMD, 0));
01194 }
01195
01196
01197
01198 void JDBController::slotStepOverIns()
01199 {
01200 }
01201
01202
01203
01204 void JDBController::slotStepOutOff()
01205 {
01206 }
01207
01208
01209
01210
01211 void JDBController::slotBreakInto()
01212 {
01213 }
01214
01215
01216
01217
01218 void JDBController::slotBPState(
Breakpoint *)
01219 {
01220 }
01221
01222
01223
01224 void JDBController::slotClearAllBreakpoints()
01225 {
01226 }
01227
01228
01229
01230 void JDBController::slotDisassemble(
const QString &,
const QString &)
01231 {
01232 }
01233
01234
01235
01236 void JDBController::slotMemoryDump(
const QString &,
const QString &)
01237 {
01238 }
01239
01240
01241
01242 void JDBController::slotRegisters()
01243 {
01244 }
01245
01246
01247
01248 void JDBController::slotLibraries()
01249 {
01250 }
01251
01252
01253
01254 void JDBController::slotSelectFrame(
int)
01255 {
01256 }
01257
01258
01259
01260
01261
01262 void JDBController::slotExpandItem(
VarItem *)
01263 {
01264 }
01265
01266
01267
01268
01269
01270
01271 void JDBController::slotExpandUserItem(
VarItem *,
const QCString& )
01272 {
01273 }
01274
01275
01276
01277
01278
01280 void JDBController::slotSetLocalViewState(
bool)
01281 {
01282 }
01283
01284
01285
01286
01287 void JDBController::slotDbgStdout(
KProcess *,
char *buf,
int buflen)
01288 {
01289
01290
if (
jdbOutputLen_+buflen+1 >
jdbSizeofBuf_) {
01291
jdbSizeofBuf_ =
jdbOutputLen_+buflen+1;
01292
char *newBuf =
new char[
jdbSizeofBuf_];
01293
if (
jdbOutputLen_)
01294 memcpy(newBuf,
jdbOutput_,
jdbOutputLen_+1);
01295
delete[]
jdbOutput_;
01296
jdbOutput_ = newBuf;
01297 }
01298
01299
01300
01301 memcpy(
jdbOutput_+
jdbOutputLen_, buf, buflen);
01302 jdbOutputLen_ += buflen;
01303 *(
jdbOutput_+jdbOutputLen_) = 0;
01304
01305
if (
char *nowAt =
parse(
jdbOutput_)) {
01306 Q_ASSERT(nowAt <=
jdbOutput_+jdbOutputLen_+1);
01307 jdbOutputLen_ = strlen(nowAt);
01308
01309
if (jdbOutputLen_)
01310 memmove(
jdbOutput_, nowAt, jdbOutputLen_);
01311
01312 }
01313
01314
executeCmd();
01315
kdDebug() <<
"stdout" <<
endl;
01316 }
01317
01318
01319
01320 void JDBController::slotDbgStderr(
KProcess *,
char *buf,
int)
01321 {
01322
01323
01324
kdDebug() <<
"STDERR\n";
01325
DBG_DISPLAY(
QString(
"\nSTDERR: ")+
QString(buf));
01326
01327 }
01328
01329
01330
01331 void JDBController::slotDbgWroteStdin(
KProcess *)
01332 {
01333
setStateOff(s_waitForWrite);
01334
executeCmd();
01335
kdDebug() <<
"dbgwrotestdin" <<
endl;
01336 }
01337
01338
01339
01340 void JDBController::slotDbgProcessExited(
KProcess*)
01341 {
01342
destroyCmds();
01343
state_ = s_appNotStarted|s_programExited|(
state_&s_viewLocals);
01344 emit
dbgStatus (i18n(
"Process exited"),
state_);
01345
01346
JDB_DISPLAY(
QString(
"\n(jdb) Process exited"));
01347 }
01348
01349
01350
01351
01358 QString JDBController::getFile(
QString className)
01359 {
01360
return QString(
projectDirectory_ +
"/" + className +
".java");
01361 }
01362
01363
01364
01365 void JDBController::varUpdateDone()
01366 {
01367
kdDebug() <<
"VarUpdateDone" <<
endl;
01368
01369
QString locals =
"";
01370
QDictIterator<JDBVarItem> it(
localData);
01371
if (!it.toFirst()) {
return; }
01372
01373
while (it.current()) {
01374
01375
if (!it.currentKey().contains(
".")) {
01376 locals += it.current()->toString() +
QString(
",");
01377 }
01378 ++it;
01379 }
01380
01381 locals[locals.length()-1] =
' ';
01382
char* _l =
new char[locals.length()];
01383 strcpy(_l, locals.latin1());
01384
kdDebug() <<
"\nLocals: "<< _l <<
endl;
01385
01386
01387
varTree_->
trim();
01388
01389
FrameRoot *frame;
01390
01391
01392
if (!(frame =
varTree_->
findFrame(
currentFrame_)))
01393 frame =
new FrameRoot(
varTree_,
currentFrame_);
01394
01395 Q_ASSERT(frame);
01396 frame->
setFrameName(
frameStack_->
getFrameName(
currentFrame_));
01397
01398 frame->
setLocals(_l);
01399
01400
varTree_->viewport()->setUpdatesEnabled(
true);
01401
varTree_->repaint();
01402
localData.clear();
01403
setStateOff(
s_parsingOutput);
01404
01405 }
01406
01407
01408
01409 void JDBController::slotAbortTimedEvent()
01410 {
01411
setStateOff(s_waitTimer);
01412
DBG_DISPLAY(
QString(
"Timer aborted\n"));
01413 }
01414
01415
01416
01417 void JDBController::slotStepInSource(
const QString &fileName,
int lineNum)
01418 {
01419
DBG_DISPLAY((
QString(
"(Show step in source) ")+fileName+
QString(
":")
01420 +
QString().setNum(lineNum)).local8Bit().
data());
01421 }
01422
01423
01424
01425 void JDBController::slotDbgStatus(
const QString &status,
int state)
01426 {
01427
QString s(
"(status) ");
01428
if (!state)
01429 s +=
QString(
"<program paused>");
01430
if (state & s_dbgNotStarted)
01431 s += QString(
"<dbg not started>");
01432
if (state & s_appNotStarted)
01433 s += QString(
"<app not started>");
01434
if (state & s_appBusy)
01435 s += QString(
"<app busy>");
01436
if (state & s_waitForWrite)
01437 s += QString(
"<wait for write>");
01438
if (state & s_programExited)
01439 s += QString(
"<program exited>");
01440
if (state & s_silent)
01441 s += QString(
"<silent>");
01442
if (state & s_viewLocals)
01443 s += QString(
"<viewing locals>");
01444
01445
DBG_DISPLAY((s+status).local8Bit().
data());
01446 }
01447
01448
01449 JDBVarItem::JDBVarItem() {
01450
value =
"";
01451
name =
"";
01452 }
01453
01454 QString JDBVarItem::toString() {
01455
if (!
value.isEmpty()) {
01456
kdDebug() <<
value <<
" - ";
01457
return name +
" = " +
value;
01458 }
else {
01459
01460
QString tmp;
01461
JDBVarItem *item;
01462
01463
for (item = this->
siblings.first(); item != 0; item = this->
siblings.next()) {
01464 tmp += item->
toString() +
",";
01465
delete item;
01466 }
01467
01468 tmp =
name +
" = {" +tmp;
01469 tmp[tmp.length()-1] =
'}';
01470
return tmp;
01471 }
01472 }
01473
01474 }
01475
01476
01477
#include "jdbcontroller.moc"