Abldbug.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311
  1. //===========================================================================//
  2. // Copyright (C) Microsoft Corporation. All rights reserved. //
  3. //===========================================================================//
  4. //***************************************************************************
  5. //
  6. // ABLDBUG.CPP
  7. //
  8. //***************************************************************************
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #ifndef ABLGEN_H
  12. #include "ablgen.h"
  13. #endif
  14. #ifndef ABLERR_H
  15. #include "ablerr.h"
  16. #endif
  17. #ifndef ABLSCAN_H
  18. #include "ablscan.h"
  19. #endif
  20. #ifndef ABLSYMT_H
  21. #include "ablsymt.h"
  22. #endif
  23. #ifndef ABLEXEC_H
  24. #include "ablexec.h"
  25. #endif
  26. #ifndef ABLDBUG_H
  27. #include "abldbug.h"
  28. #endif
  29. //***************************************************************************
  30. //----------
  31. // EXTERNALS
  32. extern long level;
  33. extern long execLineNumber;
  34. //extern long execStatementCount;
  35. extern TokenCodeType codeToken;
  36. extern char* codeBuffer;
  37. extern char* codeBufferPtr;
  38. extern char* codeSegmentPtr;
  39. extern char* statementStartPtr;
  40. extern StackItemPtr tos;
  41. //extern StackItemPtr stackFrameBasePtr;
  42. extern SymTableNodePtr CurRoutineIdPtr;
  43. extern SymTableNodePtr symTableDisplay[];
  44. extern long errorCount;
  45. extern char curChar;
  46. extern TokenCodeType curToken;
  47. extern long lineNumber;
  48. extern Literal curLiteral;
  49. extern long bufferOffset;
  50. extern char sourceBuffer[MAXLEN_SOURCELINE];
  51. //extern long bufferOffset;
  52. extern char* bufferp;
  53. //extern char* tokenp;
  54. extern char wordString[MAXLEN_TOKENSTRING];
  55. extern TypePtr IntegerTypePtr;
  56. extern TypePtr CharTypePtr;
  57. extern TypePtr RealTypePtr;
  58. extern TypePtr BooleanTypePtr;
  59. extern Type DummyType;
  60. extern ModuleEntryPtr ModuleRegistry;
  61. extern ABLModulePtr* ModuleInstanceRegistry;
  62. extern long MaxModules;
  63. extern long NumModulesRegistered;
  64. extern long NumModuleInstances;
  65. extern long MaxWatchesPerModule;
  66. extern long MaxBreakPointsPerModule;
  67. extern char* TokenStrings[NUM_TOKENS];
  68. //extern StackItem* stack;
  69. //extern StackItemPtr stackFrameBasePtr;
  70. extern StackItemPtr StaticDataPtr;
  71. //extern SymTableNodePtr CurRoutineIdPtr;
  72. //extern long MaxLoopIterations;
  73. void CheckMouse(void);
  74. //---------------------------------------------------------------------------
  75. long MaxBreaks = 50;
  76. long MaxWatches = 50;
  77. DebuggerPtr debugger = NULL;
  78. char Debugger::message[512];
  79. extern bool takeScreenShot;
  80. #ifdef USE_IFACE
  81. extern aTextObject* ABLDebuggerIn;
  82. extern ScrollingTextWindow* ABLDebuggerOut;
  83. #endif
  84. //***************************************************************************
  85. // WATCH MANAGER class
  86. //***************************************************************************
  87. void* WatchManager::operator new (size_t mySize) {
  88. void *result = ABLStackMallocCallback(mySize);
  89. return(result);
  90. }
  91. //---------------------------------------------------------------------------
  92. void WatchManager::operator delete (void* us) {
  93. ABLStackFreeCallback(us);
  94. }
  95. //---------------------------------------------------------------------------
  96. long WatchManager::init (long max) {
  97. maxWatches = max;
  98. numWatches = 0;
  99. watches = (WatchPtr)ABLStackMallocCallback(max * sizeof(Watch));
  100. if (!watches)
  101. return(-1);
  102. return(ABL_NO_ERR);
  103. }
  104. //---------------------------------------------------------------------------
  105. void WatchManager::destroy (void) {
  106. if (watches) {
  107. ABLStackFreeCallback(watches);
  108. watches = NULL;
  109. }
  110. maxWatches = 0;
  111. numWatches = 0;
  112. }
  113. //---------------------------------------------------------------------------
  114. WatchPtr WatchManager::add (SymTableNodePtr idPtr) {
  115. //------------------------------------------
  116. // This routine assumes idPtr is non-NULL...
  117. switch (idPtr->defn.key) {
  118. case DFN_CONST:
  119. case DFN_VAR:
  120. case DFN_VALPARAM:
  121. case DFN_REFPARAM:
  122. //case DFN_FIELD:
  123. if (idPtr->info)
  124. return((WatchPtr)idPtr->info);
  125. else if (numWatches < maxWatches) {
  126. idPtr->info = (char*)&watches[numWatches];
  127. watches[numWatches].idPtr = idPtr;
  128. watches[numWatches].store = false;
  129. watches[numWatches].breakOnStore = false;
  130. watches[numWatches].fetch = false;
  131. watches[numWatches].breakOnFetch = false;
  132. return(&watches[numWatches++]);
  133. }
  134. break;
  135. }
  136. return(NULL);
  137. }
  138. //---------------------------------------------------------------------------
  139. long WatchManager::remove (SymTableNodePtr idPtr) {
  140. if (!idPtr)
  141. return(1);
  142. if (!idPtr->info)
  143. return(2);
  144. //------------------------------------------
  145. // Find this id's watch in the watch list...
  146. long removeIndex;
  147. for (removeIndex = 0; removeIndex < numWatches; removeIndex++)
  148. if (&watches[removeIndex] == (WatchPtr)idPtr->info)
  149. break;
  150. //--------------------------------------------------------
  151. // The id no longer points to a watch in the watch list...
  152. idPtr->info = NULL;
  153. numWatches--;
  154. //-------------------------------------
  155. // Fill in the gap in the watch list...
  156. for (long i = removeIndex; removeIndex < numWatches; removeIndex++) {
  157. watches[i].idPtr = watches[i + 1].idPtr;
  158. watches[i].store = watches[i + 1].store;
  159. watches[i].breakOnStore = watches[i + 1].breakOnStore;
  160. watches[i].fetch = watches[i + 1].fetch;
  161. watches[i].breakOnFetch = watches[i + 1].breakOnFetch;
  162. watches[i].idPtr->info = (char*)&watches[i];
  163. }
  164. return(ABL_NO_ERR);
  165. }
  166. //---------------------------------------------------------------------------
  167. long WatchManager::removeAll (void) {
  168. for (long i = 0; i < numWatches; i++) {
  169. watches[i].idPtr->info = NULL;
  170. watches[i].idPtr = NULL;
  171. watches[i].store = false;
  172. watches[i].breakOnStore = false;
  173. watches[i].fetch = false;
  174. watches[i].breakOnFetch = false;
  175. }
  176. long numRemoved = numWatches;
  177. numWatches = 0;
  178. return(numRemoved);
  179. }
  180. //---------------------------------------------------------------------------
  181. long WatchManager::setStore (SymTableNodePtr idPtr, bool state, bool breakToDebug) {
  182. if (!idPtr)
  183. return(1);
  184. WatchPtr watch = (WatchPtr)idPtr->info;
  185. if (state) {
  186. if (!watch)
  187. watch = add(idPtr);
  188. if (!watch)
  189. return(2);
  190. watch->store = true;
  191. watch->breakOnStore = breakToDebug;
  192. }
  193. else {
  194. if (watch) {
  195. if (watch->fetch) {
  196. watch->store = false;
  197. watch->breakOnStore = false;
  198. }
  199. else
  200. remove(idPtr);
  201. }
  202. }
  203. return(ABL_NO_ERR);
  204. }
  205. //---------------------------------------------------------------------------
  206. long WatchManager::setFetch (SymTableNodePtr idPtr, bool state, bool breakToDebug) {
  207. if (!idPtr)
  208. return(1);
  209. WatchPtr watch = (WatchPtr)idPtr->info;
  210. if (state) {
  211. if (!watch)
  212. watch = add(idPtr);
  213. if (!watch)
  214. return(2);
  215. watch->fetch = true;
  216. watch->breakOnFetch = breakToDebug;
  217. }
  218. else {
  219. if (watch) {
  220. if (watch->store) {
  221. watch->fetch = false;
  222. watch->breakOnFetch = false;
  223. }
  224. else
  225. remove(idPtr);
  226. }
  227. }
  228. return(ABL_NO_ERR);
  229. }
  230. //---------------------------------------------------------------------------
  231. bool WatchManager::getStore (SymTableNodePtr idPtr) {
  232. if (!idPtr->info)
  233. return(false);
  234. return(((WatchPtr)idPtr->info)->store);
  235. }
  236. //---------------------------------------------------------------------------
  237. bool WatchManager::getFetch (SymTableNodePtr idPtr) {
  238. if (!idPtr->info)
  239. return(false);
  240. return(((WatchPtr)idPtr->info)->fetch);
  241. }
  242. //---------------------------------------------------------------------------
  243. void WatchManager::print (void) {
  244. for (long i = 0; i < numWatches; i++) {
  245. //SymTableNodePtr idPtr = watches[i].idPtr;
  246. // Display info here...
  247. }
  248. }
  249. //***************************************************************************
  250. // BREAK POINT MANAGER class
  251. //***************************************************************************
  252. void* BreakPointManager::operator new (size_t mySize) {
  253. void *result = ABLStackMallocCallback(mySize);
  254. return(result);
  255. }
  256. //---------------------------------------------------------------------------
  257. void BreakPointManager::operator delete (void* us) {
  258. ABLStackFreeCallback(us);
  259. }
  260. //---------------------------------------------------------------------------
  261. long BreakPointManager::init (long max) {
  262. maxBreakPoints = max;
  263. numBreakPoints = 0;
  264. breakPoints = (long*)ABLStackMallocCallback(max * sizeof(long));
  265. if (!breakPoints)
  266. return(-1);
  267. return(ABL_NO_ERR);
  268. }
  269. //---------------------------------------------------------------------------
  270. void BreakPointManager::destroy (void) {
  271. if (breakPoints) {
  272. ABLStackFreeCallback(breakPoints);
  273. breakPoints = NULL;
  274. }
  275. maxBreakPoints = 0;
  276. numBreakPoints = 0;
  277. }
  278. //---------------------------------------------------------------------------
  279. long BreakPointManager::add (long lineNumber) {
  280. //----------------------------------------------------------------
  281. // This does not check to make sure the line number is within
  282. // the source code's range--if it isn't, the break is simply never
  283. // hit...
  284. if (numBreakPoints == maxBreakPoints)
  285. return(1);
  286. else if (lineNumber <= 0)
  287. return(2);
  288. else {
  289. //------------------------------------------------
  290. // Insert it into the list (in ascending order)...
  291. long insertPoint = 0;
  292. for (insertPoint = 0; insertPoint < numBreakPoints; insertPoint++) {
  293. if (lineNumber == breakPoints[insertPoint])
  294. return(ABL_NO_ERR);
  295. else if (lineNumber < breakPoints[insertPoint])
  296. break;
  297. }
  298. for (long i = insertPoint; i < numBreakPoints; i++)
  299. breakPoints[i + 1] = breakPoints[i];
  300. breakPoints[insertPoint] = lineNumber;
  301. numBreakPoints++;
  302. }
  303. return(ABL_NO_ERR);
  304. }
  305. //---------------------------------------------------------------------------
  306. long BreakPointManager::remove (long lineNumber) {
  307. long index;
  308. for (index = 0; index < numBreakPoints; index++)
  309. if (lineNumber == breakPoints[index])
  310. break;
  311. numBreakPoints--;
  312. //------------------
  313. // Shift 'em down...
  314. for (long i = index; i < numBreakPoints; i++)
  315. breakPoints[i] = breakPoints[i + 1];
  316. return(ABL_NO_ERR);
  317. }
  318. //---------------------------------------------------------------------------
  319. long BreakPointManager::removeAll (void) {
  320. long numRemoved = numBreakPoints;
  321. numBreakPoints = 0;
  322. return(numRemoved);
  323. }
  324. //---------------------------------------------------------------------------
  325. bool BreakPointManager::isBreakPoint (long lineNumber) {
  326. if (numBreakPoints > 0) {
  327. for (long i = 0; i < numBreakPoints; i++)
  328. if (lineNumber == breakPoints[i])
  329. return(true);
  330. }
  331. return(false);
  332. }
  333. //---------------------------------------------------------------------------
  334. void BreakPointManager::print (void) {
  335. //--------------------------------------------------------------
  336. // If no line number, do default action--list all breakpoints...
  337. for (long i = 0; i < numBreakPoints; i++) {
  338. // print info...
  339. }
  340. }
  341. //***************************************************************************
  342. // DEBUGGER class
  343. //***************************************************************************
  344. void* Debugger::operator new (size_t mySize) {
  345. void *result = ABLStackMallocCallback(mySize);
  346. return(result);
  347. }
  348. //---------------------------------------------------------------------------
  349. void Debugger::operator delete (void* us) {
  350. ABLStackFreeCallback(us);
  351. }
  352. //---------------------------------------------------------------------------
  353. long Debugger::init (void (*callback)(char* s), ABLModulePtr _module) {
  354. printCallback = callback;
  355. module = _module;
  356. if (module) {
  357. watchManager = module->getWatchManager();
  358. breakPointManager = module->getBreakPointManager();
  359. }
  360. return(ABL_NO_ERR);
  361. }
  362. //---------------------------------------------------------------------------
  363. void Debugger::destroy (void) {
  364. }
  365. //---------------------------------------------------------------------------
  366. long Debugger::print (char* s) {
  367. if (printCallback)
  368. (*printCallback)(s);
  369. return(ABL_NO_ERR);
  370. }
  371. //---------------------------------------------------------------------------
  372. void Debugger::setModule (ABLModulePtr _module) {
  373. module = _module;
  374. breakPointManager = module->getBreakPointManager();
  375. watchManager = module->getWatchManager();
  376. step = module->getStep();
  377. trace = traceEntry = traceExit = module->getTrace();
  378. }
  379. //---------------------------------------------------------------------------
  380. long Debugger::setWatch (long states) {
  381. getToken();
  382. switch (curToken) {
  383. case TKN_SEMICOLON:
  384. print("Variables currently watched:\n");
  385. //-------------------------------------------------------------
  386. // No variable, so default watch action--display all watches...
  387. watchManager->print();
  388. break;
  389. case TKN_IDENTIFIER:
  390. SymTableNodePtr idPtr = NULL;
  391. searchAndFindAllSymTables(idPtr);
  392. getToken();
  393. //-----------------
  394. // STORE setting...
  395. bool breakToDebug = ((states & WATCH_BREAK) != 0);
  396. if (states & WATCH_STORE_OFF)
  397. watchManager->setStore(idPtr, false, breakToDebug);
  398. else if (states & WATCH_STORE_ON)
  399. watchManager->setStore(idPtr, true, breakToDebug);
  400. //-----------------
  401. // FETCH setting...
  402. if (states & WATCH_FETCH_OFF)
  403. watchManager->setFetch(idPtr, false, breakToDebug);
  404. else if (states & WATCH_FETCH_ON)
  405. watchManager->setFetch(idPtr, true, breakToDebug);
  406. break;
  407. }
  408. return(ABL_NO_ERR);
  409. }
  410. //---------------------------------------------------------------------------
  411. long Debugger::addBreakPoint (void) {
  412. getToken();
  413. switch (curToken) {
  414. case TKN_SEMICOLON:
  415. print("Variables currently watched:\n");
  416. breakPointManager->print();
  417. break;
  418. case TKN_NUMBER:
  419. if (curLiteral.type == LIT_INTEGER)
  420. breakPointManager->add(curLiteral.value.integer);
  421. getToken();
  422. break;
  423. }
  424. return(ABL_NO_ERR);
  425. }
  426. //---------------------------------------------------------------------------
  427. long Debugger::removeBreakPoint (void) {
  428. getToken();
  429. switch (curToken) {
  430. case TKN_SEMICOLON:
  431. breakPointManager->removeAll();
  432. break;
  433. case TKN_NUMBER:
  434. if (curLiteral.type == LIT_INTEGER)
  435. breakPointManager->remove(curLiteral.value.integer);
  436. getToken();
  437. break;
  438. }
  439. return(ABL_NO_ERR);
  440. }
  441. //---------------------------------------------------------------------------
  442. void Debugger::sprintStatement (char* dest) {
  443. //---------------------------------------------------------------------
  444. // First, rebuild the the current statement from the module code. Then,
  445. // spit it out as we do so...
  446. bool done = false;
  447. char* cp = statementStartPtr;
  448. do {
  449. TokenCodeType token = (TokenCodeType)*cp;
  450. cp++;
  451. switch (token) {
  452. case TKN_STATEMENT_MARKER:
  453. done = true;
  454. break;
  455. case TKN_SEMICOLON:
  456. case TKN_END_IF:
  457. case TKN_END_WHILE:
  458. case TKN_END_FOR:
  459. case TKN_END_FUNCTION:
  460. case TKN_END_MODULE:
  461. case TKN_END_FSM:
  462. case TKN_END_LIBRARY:
  463. case TKN_END_CASE:
  464. case TKN_END_SWITCH:
  465. case TKN_END_ORDER:
  466. case TKN_END_STATE:
  467. case TKN_THEN:
  468. //case TKN_UNTIL:
  469. done = true;
  470. //--------------------------
  471. // Do NOT want break here...
  472. default:
  473. //done = false;
  474. switch (token) {
  475. case TKN_ADDRESS_MARKER:
  476. cp += sizeof(Address);
  477. break;
  478. case TKN_IDENTIFIER:
  479. case TKN_NUMBER:
  480. case TKN_STRING: {
  481. SymTableNodePtr symbol = *((SymTableNodePtr*)cp);
  482. strcat(dest, " ");
  483. strcat(dest, symbol->name);
  484. cp += sizeof(SymTableNodePtr);
  485. }
  486. break;
  487. default:
  488. strcat(dest, " ");
  489. strcat(dest, TokenStrings[token]);
  490. break;
  491. }
  492. break;
  493. }
  494. } while (!done);
  495. }
  496. //---------------------------------------------------------------------------
  497. void Debugger::sprintLineNumber (char* dest) {
  498. //--------------------------
  499. // PRINT LINE NUMBER HERE...
  500. sprintf(dest, "LINE#");
  501. }
  502. //---------------------------------------------------------------------------
  503. void Debugger::sprintDataValue (char* dest, StackItemPtr data, TypePtr dataType) {
  504. if ((dataType->form == FRM_ENUM) && (dataType != BooleanTypePtr))
  505. dataType = IntegerTypePtr;
  506. if (dataType == IntegerTypePtr)
  507. sprintf(dest, "%d", data->integer);
  508. else if (dataType == RealTypePtr)
  509. sprintf(dest, "%0.6f", data->real);
  510. else if (dataType == BooleanTypePtr)
  511. sprintf(dest, "%s", (data->integer == 1) ? "true" : "false");
  512. else if (dataType == CharTypePtr)
  513. sprintf(dest, "%c", data->byte);
  514. else if (dataType->form == FRM_ARRAY) {
  515. if (dataType->info.array.elementTypePtr == CharTypePtr) {
  516. // PRINT CHAR ARRAY HERE...
  517. sprintf(dest, "CHAR ARRAY");
  518. }
  519. else {
  520. // PRINT ARRAY HERE...
  521. sprintf(dest, "ARRAY");
  522. }
  523. }
  524. }
  525. //---------------------------------------------------------------------------
  526. long Debugger::sprintSimpleValue (char* dest, SymTableNodePtr symbol) {
  527. //--------------------------------------------------------------------
  528. // This code is adapted from execVariable(). If that function changes,
  529. // this better too!
  530. TypePtr typePtr = (TypePtr)(symbol->typePtr);
  531. if (symbol->defn.key == DFN_CONST) {
  532. if (typePtr == IntegerTypePtr)
  533. sprintf(dest, "%d", symbol->defn.info.constant.value.integer);
  534. else if (typePtr == CharTypePtr)
  535. sprintf(dest, "%c", symbol->defn.info.constant.value.character);
  536. else
  537. sprintf(dest, "%.4f", symbol->defn.info.constant.value.real);
  538. }
  539. else {
  540. //--------------------------------------------------------------------
  541. // First, point to the variable's stack item. If the variable's scope
  542. // level is less than the current scope level, follow the static links
  543. // to the proper stack frame base...
  544. StackItemPtr dataPtr = NULL;
  545. switch (symbol->defn.info.data.varType) {
  546. case VAR_TYPE_NORMAL: {
  547. StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr;
  548. long delta = level - symbol->level;
  549. while (delta-- > 0)
  550. headerPtr = (StackFrameHeaderPtr)headerPtr->staticLink.address;
  551. dataPtr = (StackItemPtr)headerPtr + symbol->defn.info.data.offset;
  552. }
  553. break;
  554. case VAR_TYPE_ETERNAL:
  555. dataPtr = (StackItemPtr)stack + symbol->defn.info.data.offset;
  556. break;
  557. case VAR_TYPE_STATIC:
  558. dataPtr = (StackItemPtr)StaticDataPtr + symbol->defn.info.data.offset;
  559. break;
  560. }
  561. //---------------------------------------------------------------
  562. // If it's a scalar or enumeration reference parameter, that item
  563. // points to the actual item...
  564. if ((symbol->defn.key == DFN_REFPARAM) && (typePtr->form != FRM_ARRAY)/* && (typePtr->form != FRM_RECORD)*/)
  565. dataPtr = (StackItemPtr)dataPtr->address;
  566. if ((typePtr->form != FRM_ARRAY) /*&& (typePtr->form != FRM_RECORD)*/) {
  567. ABL_Assert(dataPtr != NULL, 0, " Debugger.sprintSimpleValue(): dataPtr is NULL ");
  568. if ((typePtr == IntegerTypePtr) || (typePtr->form == FRM_ENUM))
  569. sprintf(dest, "%d", *((long*)dataPtr));
  570. else if (typePtr == CharTypePtr)
  571. sprintf(dest, "\"%c\"", *((char*)dataPtr));
  572. else
  573. sprintf(dest, "%.4f", *((float*)dataPtr));
  574. }
  575. else
  576. sprintf(dest, "ARRAY");
  577. }
  578. return(ABL_NO_ERR);
  579. }
  580. //---------------------------------------------------------------------------
  581. long Debugger::sprintArrayValue (char* dest, SymTableNodePtr symbol, char* subscriptString) {
  582. //--------------------------------------------------------------------
  583. // This code is adapted from execVariable(). If that function changes,
  584. // this better too!
  585. //--------------------------------------------------------------------
  586. // First, point to the variable's stack item. If the variable's scope
  587. // level is less than the current scope level, follow the static links
  588. // to the proper stack frame base...
  589. if (symbol->defn.key == DFN_CONST)
  590. sprintf(dest, "\"%s\"", symbol->defn.info.constant.value.stringPtr);
  591. else {
  592. StackItemPtr dataPtr = NULL;
  593. switch (symbol->defn.info.data.varType) {
  594. case VAR_TYPE_NORMAL: {
  595. StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr;
  596. long delta = level - symbol->level;
  597. while (delta-- > 0)
  598. headerPtr = (StackFrameHeaderPtr)headerPtr->staticLink.address;
  599. dataPtr = (StackItemPtr)headerPtr + symbol->defn.info.data.offset;
  600. }
  601. break;
  602. case VAR_TYPE_ETERNAL:
  603. dataPtr = (StackItemPtr)stack + symbol->defn.info.data.offset;
  604. break;
  605. case VAR_TYPE_STATIC:
  606. dataPtr = (StackItemPtr)StaticDataPtr + symbol->defn.info.data.offset;
  607. break;
  608. }
  609. TypePtr typePtr = (TypePtr)(symbol->typePtr);
  610. ABL_Assert(dataPtr != NULL, 0, " Debugger.sprintArrayValue(): dataPtr is NULL ");
  611. Address elementAddress = (Address)dataPtr->address;
  612. if (subscriptString) {
  613. char* cp = subscriptString;
  614. //-----------------------------
  615. // Get past the open bracket...
  616. cp++;
  617. char* token = strtok(&subscriptString[1], ",]");
  618. while (token) {
  619. //----------------
  620. // Read integer...
  621. long index = atoi(token);
  622. //-------------------------
  623. // Range check the index...
  624. if ((index < 0) || (index >= typePtr->info.array.elementCount))
  625. return(1);
  626. elementAddress += (index * typePtr->info.array.elementTypePtr->size);
  627. typePtr = typePtr->info.array.elementTypePtr;
  628. token = strtok(NULL, ",]");
  629. }
  630. }
  631. if ((typePtr->form != FRM_ARRAY)) {
  632. if ((typePtr == IntegerTypePtr) || (typePtr->form == FRM_ENUM))
  633. sprintf(dest, "%d", *((long*)elementAddress));
  634. else if (typePtr == CharTypePtr)
  635. sprintf(dest, "\"%c\"", *((char*)elementAddress));
  636. else
  637. sprintf(dest, "%.4f", *((float*)elementAddress));
  638. }
  639. else if (typePtr->info.array.elementTypePtr == CharTypePtr)
  640. sprintf(dest, "\"%s\"", (char*)elementAddress);
  641. else
  642. sprintf(dest, "Could you be more specific?");
  643. }
  644. return(ABL_NO_ERR);
  645. }
  646. //---------------------------------------------------------------------------
  647. long Debugger::sprintValue (char* dest, char* exprString) {
  648. char* subscript = strchr(exprString, '[');
  649. if (!subscript) {
  650. //------------------------------------------
  651. // Probably a simple variable or constant...
  652. SymTableNodePtr symbol = debugModule->findSymbol(exprString, CurRoutineIdPtr);
  653. if (!symbol)
  654. return(1);
  655. if (symbol->typePtr->form != FRM_ARRAY) {
  656. sprintSimpleValue(dest, symbol);
  657. return(ABL_NO_ERR);
  658. }
  659. }
  660. //-----------------
  661. // Must be array...
  662. if (subscript) {
  663. //--------------------------------
  664. // Looking for specific element...
  665. char subscriptString[255];
  666. strcpy(subscriptString, subscript);
  667. *subscript = NULL;
  668. SymTableNodePtr symbol = debugModule->findSymbol(exprString, CurRoutineIdPtr);
  669. if (!symbol)
  670. return(1);
  671. sprintArrayValue(dest, symbol, subscriptString);
  672. }
  673. else {
  674. //-------------------------
  675. // Print the whole thing...
  676. SymTableNodePtr symbol = debugModule->findSymbol(exprString, CurRoutineIdPtr);
  677. if (!symbol)
  678. return(1);
  679. sprintArrayValue(dest, symbol, NULL);
  680. }
  681. //-----------------------------------------------
  682. // We have the symbol, so parse the subscripts...
  683. return(ABL_NO_ERR);
  684. }
  685. //---------------------------------------------------------------------------
  686. long Debugger::traceStatementExecution (void) {
  687. bool halt = step;
  688. //--------------------------------------
  689. // Do we have a breakpoint on this line?
  690. if (breakPointManager) {
  691. if (breakPointManager->isBreakPoint(execLineNumber)) {
  692. sprintf(message, "HIT BP: (%d) %s [%d]", module->getId(), module->getName(), execLineNumber);
  693. print(message);
  694. halt = true;
  695. }
  696. }
  697. // if (trace) {
  698. // message[0] = NULL;
  699. // sprintLineNumber(message);
  700. // print(message);
  701. // }
  702. //------------------------------------------------------------------
  703. // If we've hit a breakpoint or are currently halted due to
  704. // some other debugging thingy, wait for another debugger command...
  705. if (halt)
  706. debugMode();
  707. return(ABL_NO_ERR);
  708. }
  709. //---------------------------------------------------------------------------
  710. long Debugger::traceRoutineEntry (SymTableNodePtr idPtr) {
  711. if (traceEntry) {
  712. sprintf(message, "ENTER (%d) %s:%s", module->getId(), module->getName(), idPtr->name);
  713. print(message);
  714. }
  715. return(ABL_NO_ERR);
  716. }
  717. //---------------------------------------------------------------------------
  718. long Debugger::traceRoutineExit (SymTableNodePtr idPtr) {
  719. if (traceExit) {
  720. sprintf(message, "EXIT (%d) %s:%s", module->getId(), module->getName(), idPtr->name);
  721. print(message);
  722. }
  723. return(ABL_NO_ERR);
  724. }
  725. //---------------------------------------------------------------------------
  726. long Debugger::traceDataStore (SymTableNodePtr id, TypePtr idType, StackItemPtr target, TypePtr targetType) {
  727. //SymTableNodePtr idPtr = debugModule->findSymbol(strParam1);
  728. //if (!idPtr) {
  729. // print("Unknown identifier in current scope.\n");
  730. // return;
  731. // }
  732. // char message[255];
  733. // sprintSymbolValue(message, idPtr);
  734. // print(message);
  735. // }
  736. if (id->info && ((WatchPtr)id->info)->store) {
  737. char valString[255];
  738. sprintDataValue(valString, target, targetType);
  739. if (idType->form == FRM_ARRAY)
  740. sprintf(message, "STORE: (%d) %s [%d] -> %s[#] = %s\n", module->getId(), module->getName(), execLineNumber, id->name, valString);
  741. //else if (idType->form == FRM_RECORD)
  742. // sprintf(message, "STORE AT LINE %d - %s.# = %s\n", execLineNumber, id->name, valString);
  743. else
  744. sprintf(message, "STORE: (%d) %s [%d] -> %s = %s\n", module->getId(), module->getName(), execLineNumber, id->name, valString);
  745. print(message);
  746. if (((WatchPtr)id->info)->breakOnStore)
  747. debugMode();
  748. }
  749. return(ABL_NO_ERR);
  750. }
  751. //---------------------------------------------------------------------------
  752. long Debugger::traceDataFetch (SymTableNodePtr id, TypePtr idType, StackItemPtr data) {
  753. TypePtr idTypePtr = id->typePtr;
  754. if (id->info && ((WatchPtr)id->info)->fetch) {
  755. char valString[255];
  756. sprintDataValue(valString, data, idType);
  757. if (idTypePtr->form == FRM_ARRAY)
  758. sprintf(message, "FETCH: (%d) %s [%d] - %s[#] = %s\n", module->getId(), module->getName(), execLineNumber, id->name, valString);
  759. //else if (idTypePtr->form == FRM_RECORD)
  760. // sprintf(message, "STORE AT LINE %d - %s.# = %s\n", id->name, valString);
  761. else
  762. sprintf(message, "FETCH: (%d) %s [%d] - %s = %s\n", module->getId(), module->getName(), execLineNumber, id->name, valString);
  763. print(message);
  764. if (((WatchPtr)id->info)->breakOnFetch)
  765. debugMode();
  766. }
  767. return(ABL_NO_ERR);
  768. }
  769. //---------------------------------------------------------------------------
  770. void Debugger::showValue (void) {
  771. getToken();
  772. if (curToken == TKN_SEMICOLON)
  773. print("Bad Expression.\n");
  774. else {
  775. //------------------------------------------------------------
  776. // NOTE: Need a SOFT FATAL for parsing expressions here so the
  777. // debugger's errors don't Fatal out of the game!
  778. //------------------------------------------------------------
  779. //---------------------------------------------------------------
  780. // It's important that the expression parser return an error code
  781. // rather than fatal!
  782. TypePtr typePtr = expression();
  783. if (errorCount > 0)
  784. return;
  785. char* savedCodeSegmentPtr = codeSegmentPtr;
  786. TokenCodeType savedCodeToken = codeToken;
  787. execExpression();
  788. if (typePtr->form == FRM_ARRAY) {
  789. print("SHOW ARRAY\n");
  790. }
  791. else {
  792. char message[255];
  793. sprintDataValue(message, tos, typePtr);
  794. strcat(message, "\n");
  795. print(message);
  796. }
  797. pop();
  798. codeSegmentPtr = savedCodeSegmentPtr;
  799. codeToken = savedCodeToken;
  800. }
  801. }
  802. //---------------------------------------------------------------------------
  803. void Debugger::assignVariable (void) {
  804. getToken();
  805. #if 0
  806. if (curToken == TKN_SEMICOLON)
  807. print("Need a variable.\n");
  808. else if (curToken == TKN_IDENTIFIER) {
  809. //----------------------------------
  810. // Parse the assignment statement...
  811. SymTableNodePtr idPtr = NULL;
  812. searchAndFindAllSymTables(idPtr);
  813. assigmentStatement(idPtr);
  814. if (errorCount > 0)
  815. return;
  816. //-------------------
  817. // Now, execute it...
  818. char* savedCodeSegmentPtr = codeSegmentPtr;
  819. long savedCodeToken = codeToken;
  820. codeSegmentPtr = codeBuffer + 1;
  821. getCodeToken();
  822. idPtr = getSymTableCodePtr();
  823. execAssignmentStatement(idPtr);
  824. //----------------------------
  825. // Restore the code segment...
  826. codeSegmentPtr = savedCodeSegmentPtr;
  827. codeToken = savedCodeToken;
  828. }
  829. #endif
  830. }
  831. //---------------------------------------------------------------------------
  832. void Debugger::displayModuleInstanceRegistry (void) {
  833. char buffer1[200], buffer2[40];
  834. for (long i = 0; i < ((NumModuleInstances + 1) / 2); i++) {
  835. sprintf(buffer1, "(%02d) %-20s ", ModuleInstanceRegistry[i * 2]->getId(), ModuleInstanceRegistry[i * 2]->getName());
  836. if ((i * 2 + 1) < NumModuleInstances) {
  837. sprintf(buffer2, "(%02d) %-20s ", ModuleInstanceRegistry[i * 2 + 1]->getId(), ModuleInstanceRegistry[i * 2 + 1]->getName());
  838. strcat(buffer1, buffer2);
  839. }
  840. print(buffer1);
  841. }
  842. }
  843. //---------------------------------------------------------------------------
  844. void Debugger::processCommand (long commandId, char* strParam1, long numParam1, ABLModulePtr moduleParam1) {
  845. switch (commandId) {
  846. case DEBUG_COMMAND_SET_MODULE:
  847. if (moduleParam1) {
  848. debugModule = moduleParam1;
  849. print(" ");
  850. sprintf(message, "SET MODULE: %s", debugModule->getName());
  851. print(message);
  852. }
  853. else {
  854. print(" ");
  855. displayModuleInstanceRegistry();
  856. sprintf(message, "CURRENT MODULE: %s", debugModule->getName());
  857. print(message);
  858. }
  859. break;
  860. case DEBUG_COMMAND_TRACE:
  861. if (numParam1) {
  862. debugModule->setTrace(true);
  863. debugModule->setStep(false);
  864. if (module == debugModule) {
  865. trace = true;
  866. traceEntry = true;
  867. traceExit = true;
  868. step = false;
  869. }
  870. }
  871. else {
  872. debugModule->setTrace(false);
  873. if (module == debugModule) {
  874. trace = false;
  875. traceEntry = false;
  876. traceExit = false;
  877. }
  878. }
  879. break;
  880. case DEBUG_COMMAND_STEP:
  881. if (numParam1) {
  882. debugModule->setStep(true);
  883. debugModule->setTrace(false);
  884. if (module == debugModule) {
  885. step = true;
  886. trace = false;
  887. traceEntry = false;
  888. traceExit = false;
  889. }
  890. }
  891. else {
  892. debugModule->setStep(false);
  893. if (module == debugModule)
  894. step = false;
  895. }
  896. break;
  897. case DEBUG_COMMAND_BREAKPOINT_SET:
  898. print(" ");
  899. debugModule->getBreakPointManager()->add(numParam1);
  900. sprintf(message, "SET BP: %s (%d)", debugModule->getName(), numParam1);
  901. print(message);
  902. break;
  903. case DEBUG_COMMAND_BREAKPOINT_REMOVE:
  904. print(" ");
  905. debugModule->getBreakPointManager()->remove(numParam1);
  906. sprintf(message, "REMOVE BP: %s (%d)", debugModule->getName(), numParam1);
  907. print(message);
  908. break;
  909. case DEBUG_COMMAND_WATCH_SET: {
  910. print(" ");
  911. SymTableNodePtr idPtr = debugModule->findSymbol(strParam1);
  912. if (!idPtr) {
  913. print("Unknown identifier in current scope.\n");
  914. return;
  915. }
  916. bool breakToDebug = ((numParam1 & WATCH_BREAK) != 0);
  917. if (numParam1 & WATCH_STORE_ON) {
  918. long result = debugModule->getWatchManager()->setStore(idPtr, true, breakToDebug);
  919. if (result == 2) {
  920. print("Reached max watch limit--unable to set watch.\n");
  921. return;
  922. }
  923. }
  924. if (numParam1 & WATCH_FETCH_ON) {
  925. long result = debugModule->getWatchManager()->setFetch(idPtr, true, breakToDebug);
  926. if (result == 2) {
  927. print("Reached max watch limit--unable to set watch.\n");
  928. return;
  929. }
  930. }
  931. if (numParam1 & WATCH_STORE_OFF)
  932. debugModule->getWatchManager()->setStore(idPtr, false, breakToDebug);
  933. if (numParam1 & WATCH_FETCH_OFF)
  934. debugModule->getWatchManager()->setFetch(idPtr, false, breakToDebug);
  935. bool store = debugModule->getWatchManager()->getStore(idPtr);
  936. bool fetch = debugModule->getWatchManager()->getFetch(idPtr);
  937. if (store || fetch) {
  938. sprintf(message, "SET WATCH: %s.%s (", debugModule->getName(), strParam1);
  939. if (store)
  940. strcat(message, "s");
  941. if (fetch)
  942. strcat(message, "f");
  943. strcat(message, ")");
  944. }
  945. else
  946. sprintf(message, "REMOVE WATCH: %s.%s", debugModule->getName(), strParam1);
  947. print(message);
  948. }
  949. break;
  950. case DEBUG_COMMAND_WATCH_REMOVE_ALL:
  951. debugModule->getWatchManager()->removeAll();
  952. break;
  953. case DEBUG_COMMAND_PRINT: {
  954. print(" ");
  955. long err = sprintValue(message, strParam1);
  956. switch (err) {
  957. case ABL_NO_ERR:
  958. print(message);
  959. break;
  960. case 1:
  961. print("Unknown identifier in current scope.");
  962. break;
  963. }
  964. }
  965. break;
  966. case DEBUG_COMMAND_CONTINUE:
  967. debugCommand = false;
  968. break;
  969. case DEBUG_COMMAND_HELP:
  970. print(" ");
  971. print("b{+|-} <line#> set/remove breakpt");
  972. print("m [0 thru warrior #] set current module (or list them)");
  973. print("w[f|s]{+|-}{.} <variable> set/remove variable watch (fetch & store)");
  974. print("p <variable> display current value of variable");
  975. print("s{+|-} start/stop step mode");
  976. print("t{+|-} start/stop trace mode");
  977. print("?? current module info");
  978. print("? help");
  979. break;
  980. case DEBUG_COMMAND_INFO: {
  981. print(" ");
  982. sprintf(message, "CURRENT MODULE: %s", debugModule->getName());
  983. print(message);
  984. ModuleInfo moduleInfo;
  985. debugModule->getInfo(&moduleInfo);
  986. sprintf(message, "%d static vars, %d bytes, %d largest",
  987. moduleInfo.numStaticVars,
  988. moduleInfo.totalSizeStaticVars,
  989. moduleInfo.largestStaticVar);
  990. print(message);
  991. }
  992. break;
  993. }
  994. }
  995. //---------------------------------------------------------------------------
  996. void Debugger::debugMode (void) {
  997. //--------------------------------------------------------------------
  998. // Some assumptions: this will never be called during a smacker movie.
  999. //-------------------------------------------------------------------------------
  1000. // When we enter debug mode, we grab control of all message handling from windows
  1001. // until we exit ABL debug mode. This way, the ABL system is preserved for
  1002. // debugging...
  1003. debugModule = module;
  1004. message[0] = NULL;
  1005. sprintStatement(message);
  1006. print(message);
  1007. #ifdef USE_IFACE
  1008. debugCommand = true;
  1009. while (debugCommand) {
  1010. //----------------------------------------------------------
  1011. // Since MSWindows is locked out, we must Unlock the screen,
  1012. // peek for MSWindows messages, then relock it.
  1013. QueryPerformanceCounter((LARGE_INTEGER*)&startTime);
  1014. bool result;
  1015. do {
  1016. MSG msg;
  1017. result = PeekMessage(&msg,NULL,0,0,PM_REMOVE);
  1018. if (result) {
  1019. if (msg.message == WM_QUIT) {
  1020. debugCommand = false;
  1021. halt = false;
  1022. trace = false;
  1023. step = false;
  1024. traceEntry = false;
  1025. traceExit = false;
  1026. break;
  1027. }
  1028. else {
  1029. TranslateMessage(&msg);
  1030. DispatchMessage(&msg);
  1031. }
  1032. }
  1033. } while (result);
  1034. // make sure we lock the screen for a valid ptr before we go to the user routines.
  1035. if (applicationActive) {
  1036. UpdateDisplay(takeScreenShot);
  1037. takeScreenShot = false;
  1038. QueryPerformanceCounter((LARGE_INTEGER*)&stopTime);
  1039. if (MPlayer) {
  1040. //WaitForSingleObject(ReceiveMutex, INFINITE);
  1041. //WaitForSingleObject(FreeListMutex, INFINITE);
  1042. MPlayer->processReceiveList();
  1043. //ReleaseMutex(FreeListMutex);
  1044. //ReleaseMutex(ReceiveMutex);
  1045. }
  1046. // Insert our message loop here....
  1047. // and jump to the users idle
  1048. // .
  1049. // .
  1050. // .
  1051. //
  1052. //
  1053. //
  1054. // finished with our user loop...
  1055. CheckMouse();
  1056. }
  1057. prevStart = startTime;
  1058. L_INTEGER totalTime = stopTime - startTime;
  1059. frameRate = (float)countsPerSecond / (float)totalTime ;
  1060. }
  1061. #endif
  1062. }
  1063. //---------------------------------------------------------------------------
  1064. DebuggerPtr ABLi_getDebugger (void) {
  1065. return(debugger);
  1066. }
  1067. //***************************************************************************