Ablexec.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. //===========================================================================//
  2. // Copyright (C) Microsoft Corporation. All rights reserved. //
  3. //===========================================================================//
  4. //***************************************************************************
  5. //
  6. // ABLEXEC.CPP
  7. //
  8. //***************************************************************************
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #ifndef ABLGEN_H
  13. #include "ablgen.h"
  14. #endif
  15. #ifndef ABLERR_H
  16. #include "ablerr.h"
  17. #endif
  18. #ifndef ABLSCAN_H
  19. #include "ablscan.h"
  20. #endif
  21. #ifndef ABLEXEC_H
  22. #include "ablexec.h"
  23. #endif
  24. #ifndef ABLDBUG_H
  25. #include "abldbug.h"
  26. #endif
  27. //***************************************************************************
  28. //--------
  29. // GLOBALS
  30. char* codeBuffer = NULL;
  31. char* codeBufferPtr = NULL;
  32. char* codeSegmentPtr = NULL;
  33. char* codeSegmentLimit = NULL;
  34. char* statementStartPtr = NULL;
  35. TokenCodeType codeToken;
  36. long execLineNumber;
  37. long execStatementCount = 0;
  38. StackItem* stack = NULL;
  39. StackItemPtr tos = NULL;
  40. StackItemPtr stackFrameBasePtr = NULL;
  41. StackItemPtr StaticDataPtr = NULL;
  42. long* StaticVariablesSizes = NULL;
  43. long* EternalVariablesSizes = NULL;
  44. long eternalOffset = 0;
  45. long MaxStaticVariables = 0;
  46. long MaxEternalVariables = 0;
  47. long NumStaticVariables = 0;
  48. long NumOrderCalls = 1;
  49. long NumStateHandles = 0;
  50. StateHandleInfo StateHandleList[MAX_STATE_HANDLES_PER_MODULE];
  51. long CurModuleHandle = 0;
  52. long MaxCodeBufferSize = 0;
  53. bool CallModuleInit = false;
  54. bool AutoReturnFromOrders = false;
  55. long MaxLoopIterations = 100001;
  56. bool AssertEnabled = false;
  57. bool PrintEnabled = true;
  58. bool StringFunctionsEnabled = true;
  59. bool DebugCodeEnabled = false;
  60. bool IncludeDebugInfo = true;
  61. bool ProfileABL = false;
  62. bool Crunch = true;
  63. char SetStateDebugStr[256];
  64. //----------
  65. // EXTERNALS
  66. extern SymTableNodePtr CurRoutineIdPtr;
  67. extern ModuleEntryPtr ModuleRegistry;
  68. extern ABLModulePtr* ModuleInstanceRegistry;
  69. extern ABLModulePtr CurModule;
  70. extern ABLModulePtr CurLibrary;
  71. extern long NumStateTransitions;
  72. extern TokenCodeType curToken;
  73. extern long lineNumber;
  74. extern long FileNumber;
  75. extern long level;
  76. extern TypePtr IntegerTypePtr;
  77. extern TypePtr CharTypePtr;
  78. extern TypePtr RealTypePtr;
  79. extern TypePtr BooleanTypePtr;
  80. extern StackItem returnValue;
  81. extern bool ExitWithReturn;
  82. extern bool ExitFromTacOrder;
  83. extern DebuggerPtr debugger;
  84. extern bool NewStateSet;
  85. extern void (*ABLEndlessStateCallback) (UserFile* log);
  86. //***************************************************************************
  87. // CRUNCH/DECRUNCH routines
  88. //***************************************************************************
  89. void crunchToken (void) {
  90. if (!Crunch)
  91. return;
  92. if (codeBufferPtr >= (codeBuffer + MaxCodeBufferSize - 100))
  93. syntaxError(ABL_ERR_SYNTAX_CODE_SEGMENT_OVERFLOW);
  94. else {
  95. *codeBufferPtr = curToken;
  96. codeBufferPtr++;
  97. }
  98. }
  99. //***************************************************************************
  100. void crunchSymTableNodePtr (SymTableNodePtr nodePtr) {
  101. if (!Crunch)
  102. return;
  103. if (codeBufferPtr >= (codeBuffer + MaxCodeBufferSize - 100))
  104. syntaxError(ABL_ERR_SYNTAX_CODE_SEGMENT_OVERFLOW);
  105. else {
  106. SymTableNodePtr* nodePtrPtr = (SymTableNodePtr*)codeBufferPtr;
  107. *nodePtrPtr = nodePtr;
  108. codeBufferPtr += sizeof(SymTableNodePtr);
  109. }
  110. }
  111. //***************************************************************************
  112. void crunchStatementMarker (void) {
  113. if (!Crunch)
  114. return;
  115. if (codeBufferPtr >= (codeBuffer + MaxCodeBufferSize - 100))
  116. syntaxError(ABL_ERR_SYNTAX_CODE_SEGMENT_OVERFLOW);
  117. else {
  118. char saveCode = *(--codeBufferPtr);
  119. *codeBufferPtr = (char)TKN_STATEMENT_MARKER;
  120. codeBufferPtr++;
  121. if (IncludeDebugInfo) {
  122. *((unsigned char*)codeBufferPtr) = (unsigned char)FileNumber;
  123. codeBufferPtr += sizeof(unsigned char);
  124. *((long*)codeBufferPtr) = lineNumber;
  125. codeBufferPtr += sizeof(long);
  126. }
  127. *codeBufferPtr = saveCode;
  128. codeBufferPtr++;
  129. }
  130. }
  131. //***************************************************************************
  132. void uncrunchStatementMarker (void) {
  133. //-------------------------
  134. // Pull code off the buffer
  135. codeBufferPtr--;
  136. //-------------------------------
  137. // Pull debug info off the buffer
  138. if (IncludeDebugInfo)
  139. codeBufferPtr -= (sizeof(unsigned char) + sizeof(long));
  140. //-------------------------------------
  141. // Pull statement marker off the buffer
  142. codeBufferPtr--;
  143. }
  144. //***************************************************************************
  145. char* crunchAddressMarker (Address address) {
  146. if (!Crunch)
  147. return(NULL);
  148. char* saveCodeBufferPtr = NULL;
  149. if (codeBufferPtr >= (codeBuffer + MaxCodeBufferSize - 100))
  150. syntaxError(ABL_ERR_SYNTAX_CODE_SEGMENT_OVERFLOW);
  151. else {
  152. char saveCode = *(--codeBufferPtr);
  153. *codeBufferPtr = (char)TKN_ADDRESS_MARKER;
  154. codeBufferPtr++;
  155. saveCodeBufferPtr = codeBufferPtr;
  156. *((Address*)codeBufferPtr) = address;
  157. codeBufferPtr += sizeof(Address);
  158. *codeBufferPtr = saveCode;
  159. codeBufferPtr++;
  160. }
  161. return(saveCodeBufferPtr);
  162. }
  163. //***************************************************************************
  164. char* fixupAddressMarker (Address address) {
  165. if (!Crunch)
  166. return(NULL);
  167. char* oldAddress = *((Address*)address);
  168. *((long*)address) = codeBufferPtr - address;
  169. return(oldAddress);
  170. }
  171. //***************************************************************************
  172. void crunchInteger (long value) {
  173. if (!Crunch)
  174. return;
  175. if (codeBufferPtr >= (codeBuffer + MaxCodeBufferSize - 100))
  176. syntaxError(ABL_ERR_SYNTAX_CODE_SEGMENT_OVERFLOW);
  177. else {
  178. *((long*)codeBufferPtr) = value;
  179. codeBufferPtr += sizeof(long);
  180. }
  181. }
  182. //***************************************************************************
  183. void crunchByte (unsigned char value) {
  184. if (!Crunch)
  185. return;
  186. if (codeBufferPtr >= (codeBuffer + MaxCodeBufferSize - 100))
  187. syntaxError(ABL_ERR_SYNTAX_CODE_SEGMENT_OVERFLOW);
  188. else {
  189. *((unsigned char*)codeBufferPtr) = value;
  190. codeBufferPtr += sizeof(unsigned char);
  191. }
  192. }
  193. //***************************************************************************
  194. void crunchOffset (Address address) {
  195. if (!Crunch)
  196. return;
  197. if (codeBufferPtr >= (codeBuffer + MaxCodeBufferSize - 100))
  198. syntaxError(ABL_ERR_SYNTAX_CODE_SEGMENT_OVERFLOW);
  199. else {
  200. *((long*)codeBufferPtr) = address - codeBufferPtr;
  201. codeBufferPtr += sizeof(long);
  202. }
  203. }
  204. //***************************************************************************
  205. char* createCodeSegment (long& codeSegmentSize) {
  206. codeSegmentSize = codeBufferPtr - codeBuffer + 1;
  207. char* codeSegment = (char*)ABLCodeMallocCallback(codeSegmentSize);
  208. if (!codeSegment)
  209. ABL_Fatal(0, " ABL: Unable to AblCodeHeap->malloc code segment ");
  210. for (long i = 0; i < codeSegmentSize; i++)
  211. codeSegment[i] = codeBuffer[i];
  212. codeBufferPtr = codeBuffer;
  213. return(codeSegment);
  214. }
  215. //***************************************************************************
  216. SymTableNodePtr getCodeSymTableNodePtr (void) {
  217. SymTableNodePtr* nodePtrPtr = (SymTableNodePtr*)codeSegmentPtr;
  218. SymTableNodePtr nodePtr = *nodePtrPtr;
  219. codeSegmentPtr += sizeof(SymTableNodePtr);
  220. return(nodePtr);
  221. }
  222. //***************************************************************************
  223. long getCodeStatementMarker (void) {
  224. //------------------------------------------
  225. // NOTE: If there's a problem, we return -1.
  226. long lineNum = -1;
  227. if (codeToken == TKN_STATEMENT_MARKER) {
  228. if (IncludeDebugInfo) {
  229. FileNumber = *((unsigned char*)codeSegmentPtr);
  230. codeSegmentPtr += sizeof(unsigned char);
  231. lineNum = *((long*)codeSegmentPtr);
  232. codeSegmentPtr += sizeof(long);
  233. }
  234. }
  235. return(lineNum);
  236. }
  237. //***************************************************************************
  238. char* getCodeAddressMarker (void) {
  239. Address address = NULL;
  240. if (codeToken == TKN_ADDRESS_MARKER) {
  241. address = *((long*)codeSegmentPtr) + codeSegmentPtr - 1;
  242. codeSegmentPtr += sizeof(Address);
  243. }
  244. return(address);
  245. }
  246. //***************************************************************************
  247. long getCodeInteger (void) {
  248. long value = *((long*)codeSegmentPtr);
  249. codeSegmentPtr += sizeof(long);
  250. return(value);
  251. }
  252. //***************************************************************************
  253. unsigned char getCodeByte (void) {
  254. unsigned char value = *((unsigned char*)codeSegmentPtr);
  255. codeSegmentPtr += sizeof(unsigned char);
  256. return(value);
  257. }
  258. //***************************************************************************
  259. char* getCodeAddress (void) {
  260. Address address = *((long*)codeSegmentPtr) + codeSegmentPtr - 1;
  261. codeSegmentPtr += sizeof(long);
  262. return(address);
  263. }
  264. //***************************************************************************
  265. // STACK routines
  266. //***************************************************************************
  267. void pop (void) {
  268. --tos;
  269. }
  270. //***************************************************************************
  271. void getCodeToken (void) {
  272. codeToken = (TokenCodeType)*codeSegmentPtr;
  273. codeSegmentPtr++;
  274. }
  275. //***************************************************************************
  276. void pushInteger (long value) {
  277. StackItemPtr valuePtr = ++tos;
  278. if (valuePtr >= &stack[MAXSIZE_STACK])
  279. runtimeError(ABL_ERR_RUNTIME_STACK_OVERFLOW);
  280. valuePtr->integer = value;
  281. }
  282. //***************************************************************************
  283. void pushReal (float value) {
  284. StackItemPtr valuePtr = ++tos;
  285. if (valuePtr >= &stack[MAXSIZE_STACK])
  286. runtimeError(ABL_ERR_RUNTIME_STACK_OVERFLOW);
  287. valuePtr->real = value;
  288. }
  289. //***************************************************************************
  290. void pushByte (char value) {
  291. StackItemPtr valuePtr = ++tos;
  292. if (valuePtr >= &stack[MAXSIZE_STACK])
  293. runtimeError(ABL_ERR_RUNTIME_STACK_OVERFLOW);
  294. valuePtr->byte = value;
  295. }
  296. //***************************************************************************
  297. void pushAddress (Address address) {
  298. StackItemPtr valuePtr = ++tos;
  299. if (valuePtr >= &stack[MAXSIZE_STACK])
  300. runtimeError(ABL_ERR_RUNTIME_STACK_OVERFLOW);
  301. valuePtr->address = address;
  302. }
  303. //***************************************************************************
  304. void pushBoolean (bool value) {
  305. StackItemPtr valuePtr = ++tos;
  306. if (valuePtr >= &stack[MAXSIZE_STACK])
  307. runtimeError(ABL_ERR_RUNTIME_STACK_OVERFLOW);
  308. valuePtr->integer = (value ? 1 : 0);
  309. }
  310. //***************************************************************************
  311. void pushStackFrameHeader (long oldLevel, long newLevel) {
  312. //-----------------------------------
  313. // Make space for the return value...
  314. pushInteger(0);
  315. StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr;
  316. //----------------------------------------------------------------------
  317. // STATIC LINK
  318. // Currently, let's not allow functions defined within functions. Assume
  319. // the old scope level equals the new scope level, for now.
  320. if (newLevel == -1) {
  321. //--------------------------------------------------------------------
  322. // Calling a library function, so push a NULL static link since
  323. // it's scope is in a different module than the calling function.
  324. // Note that global variables in libraries should be STATIC, otherwise
  325. // they're never in scope! Weird "feature" which we may want
  326. // to fix later...
  327. pushAddress(NULL);
  328. }
  329. else if (newLevel == oldLevel + 1) {
  330. //----------------------------------------------------------------
  331. // Calling a routine nested within the caller, so push the pointer
  332. // to the caller's stack frame. In ABL, as currently defined
  333. // (2/22/96), this should only be when a module's code section is
  334. // calling a function...
  335. pushAddress((Address)headerPtr);
  336. }
  337. else if (newLevel == oldLevel) {
  338. //---------------------------------------------------------------
  339. // Calling a function at the same scope level. We like that! Push
  340. // pointer to stack frame of their common parent...
  341. pushAddress(headerPtr->staticLink.address);
  342. }
  343. else {
  344. //-------------------------------------------------------
  345. // Oops. We don't want nested functions, for now, in ABL.
  346. runtimeError(ABL_ERR_RUNTIME_NESTED_FUNCTION_CALL);
  347. }
  348. pushAddress((Address)stackFrameBasePtr);
  349. //---------------------------
  350. // Push the return address...
  351. pushAddress(0);
  352. }
  353. //***************************************************************************
  354. void allocLocal (TypePtr typePtr) {
  355. if (typePtr == IntegerTypePtr)
  356. pushInteger(0);
  357. else if (typePtr == RealTypePtr)
  358. pushReal((float)0.0);
  359. else if (typePtr == BooleanTypePtr)
  360. pushByte(0);
  361. else if (typePtr == CharTypePtr)
  362. pushByte(0);
  363. else
  364. switch (typePtr->form) {
  365. case FRM_ENUM:
  366. pushInteger(0);
  367. break;
  368. // NOTE: We currently are not supporting sub ranges, until
  369. // we really want 'em...
  370. // case FRM_SUBRANGE:
  371. // allocLocal(typePtr->info.subrange.rangeTypePtr);
  372. // break;
  373. case FRM_ARRAY:
  374. char* ptr = (char*)ABLStackMallocCallback(typePtr->size);
  375. if (!ptr)
  376. ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc local array ");
  377. pushAddress((Address)ptr);
  378. break;
  379. }
  380. }
  381. //***************************************************************************
  382. void freeLocal (SymTableNodePtr idPtr) {
  383. //---------------------------------------
  384. // Frees data allocated on local stack...
  385. TypePtr typePtr = (TypePtr)(idPtr->typePtr);
  386. StackItemPtr itemPtr = NULL;
  387. if (((typePtr->form == FRM_ARRAY) /* || (typePtr->form == FRM_RECORD)*/) &&
  388. (idPtr->defn.key != DFN_REFPARAM)) {
  389. switch (idPtr->defn.info.data.varType) {
  390. case VAR_TYPE_NORMAL:
  391. itemPtr = stackFrameBasePtr + idPtr->defn.info.data.offset;
  392. break;
  393. // case VAR_TYPE_ETERNAL:
  394. // itemPtr = stack + idPtr->defn.info.data.offset;
  395. // break;
  396. // case VAR_TYPE_STATIC:
  397. // itemPtr = StaticDataPtr + idPtr->defn.info.data.offset;
  398. // break;
  399. }
  400. if (!itemPtr)
  401. runtimeError(0);
  402. else
  403. ABLStackFreeCallback(itemPtr->address);
  404. }
  405. }
  406. //***************************************************************************
  407. // FUNCTION ENTRY/EXIT routines
  408. //***************************************************************************
  409. void routineEntry (SymTableNodePtr routineIdPtr) {
  410. if (debugger)
  411. debugger->traceRoutineEntry(routineIdPtr);
  412. memset(&returnValue, 0, sizeof(StackItem));
  413. //------------------------------
  414. // Switch to new code segment...
  415. codeSegmentPtr = routineIdPtr->defn.info.routine.codeSegment;
  416. //----------------------------------------------
  417. // Allocate local variables onto system stack...
  418. for (SymTableNodePtr varIdPtr = (SymTableNodePtr)(routineIdPtr->defn.info.routine.locals);
  419. varIdPtr != NULL;
  420. varIdPtr = varIdPtr->next)
  421. if (varIdPtr->defn.info.data.varType == VAR_TYPE_NORMAL)
  422. allocLocal((TypePtr)(varIdPtr->typePtr));
  423. }
  424. //***************************************************************************
  425. void routineExit (SymTableNodePtr routineIdPtr) {
  426. if (debugger)
  427. debugger->traceRoutineExit(routineIdPtr);
  428. //-----------------------------------------
  429. // De-alloc parameters & local variables...
  430. for (SymTableNodePtr idPtr = (SymTableNodePtr)(routineIdPtr->defn.info.routine.params);
  431. idPtr != NULL;
  432. idPtr = idPtr->next)
  433. freeLocal(idPtr);
  434. for (idPtr = (SymTableNodePtr)(routineIdPtr->defn.info.routine.locals);
  435. idPtr != NULL;
  436. idPtr = idPtr->next)
  437. if (idPtr->defn.info.data.varType == VAR_TYPE_NORMAL)
  438. freeLocal(idPtr);
  439. StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr;
  440. codeSegmentPtr = headerPtr->returnAddress.address;
  441. if (routineIdPtr->typePtr == NULL)
  442. tos = stackFrameBasePtr - 1;
  443. else
  444. tos = stackFrameBasePtr;
  445. stackFrameBasePtr = (StackItemPtr)headerPtr->dynamicLink.address;
  446. }
  447. //***************************************************************************
  448. void execute (SymTableNodePtr routineIdPtr) {
  449. SymTableNodePtr thisRoutineIdPtr = CurRoutineIdPtr;
  450. CurRoutineIdPtr = routineIdPtr;
  451. routineEntry(routineIdPtr);
  452. //----------------------------------------------------
  453. // Now, search this module for the function we want...
  454. if (CallModuleInit) {
  455. CallModuleInit = false;
  456. SymTableNodePtr initFunctionIdPtr = searchSymTable("init", ModuleRegistry[CurModule->getHandle()].moduleIdPtr->defn.info.routine.localSymTable);
  457. if (initFunctionIdPtr) {
  458. execRoutineCall(initFunctionIdPtr, false);
  459. //-------------------------------------------------------------------------
  460. // Since we're calling the function directly, we need to compensate for the
  461. // codeSegmentPtr being incremented by 1 in the normal execRoutineCall...
  462. codeSegmentPtr--;
  463. }
  464. }
  465. if (routineIdPtr->defn.info.routine.flags & ROUTINE_FLAG_FSM) {
  466. NewStateSet = true;
  467. static char stateList[60][256];
  468. strcpy(SetStateDebugStr, "--");
  469. while (NewStateSet) {
  470. NumStateTransitions++;
  471. sprintf(stateList[NumStateTransitions], "%s (%s)", CurModule->getState()->name, SetStateDebugStr);
  472. if (NumStateTransitions == 50) {
  473. UserFile* userFile = UserFile::getNewFile();
  474. char errStr[512];
  475. if (userFile) {
  476. long err = userFile->open("endless.log");
  477. if (!err) {
  478. //char s[1024];
  479. //sprintf(s, "Current Date: %s\n", GetTime());
  480. //userFile->write(s);
  481. userFile->write(ModuleRegistry[CurModule->getHandle()].fileName);
  482. for (long i = 1; i < 51; i++)
  483. userFile->write(stateList[i]);
  484. userFile->write(" ");
  485. if (ABLEndlessStateCallback)
  486. (*ABLEndlessStateCallback)(userFile);
  487. userFile->close();
  488. }
  489. }
  490. sprintf(errStr, " ABL endless state loop in %s [%s:%s] ", ModuleRegistry[CurModule->getHandle()].fileName, CurModule->getState()->name, CurModule->getPrevState()->name);
  491. #if 0
  492. ABL_Fatal(NumStateTransitions, errStr);
  493. #else
  494. NewStateSet = false;
  495. #endif
  496. }
  497. else {
  498. NewStateSet = false;
  499. SymTableNodePtr curState = CurModule->getState();
  500. if (!curState)
  501. ABL_Fatal(0, " ABL.execute: NULL state in FSM ");
  502. execRoutineCall(curState, false);
  503. codeSegmentPtr--;
  504. }
  505. //---------------------------------------------
  506. // In case we exited with a return statement...
  507. ExitWithReturn = false;
  508. ExitFromTacOrder = false;
  509. }
  510. }
  511. else {
  512. getCodeToken();
  513. execStatement();
  514. //---------------------------------------------
  515. // In case we exited with a return statement...
  516. ExitWithReturn = false;
  517. ExitFromTacOrder = false;
  518. }
  519. routineExit(routineIdPtr);
  520. CurRoutineIdPtr = thisRoutineIdPtr;
  521. }
  522. //***************************************************************************
  523. void executeChild (SymTableNodePtr routineIdPtr, SymTableNodePtr childRoutineIdPtr) {
  524. // THIS DOES NOT SUPPORT CALLING FUNCTIONS WITH PARAMETERS YET!
  525. SymTableNodePtr thisRoutineIdPtr = CurRoutineIdPtr;
  526. CurRoutineIdPtr = routineIdPtr;
  527. routineEntry(routineIdPtr);
  528. //----------------------------------------------------
  529. // Now, search this module for the function we want...
  530. SymTableNodePtr initFunctionIdPtr = NULL;
  531. if (CallModuleInit) {
  532. CallModuleInit = false;
  533. initFunctionIdPtr = searchSymTable("init", routineIdPtr->defn.info.routine.localSymTable);
  534. if (initFunctionIdPtr) {
  535. execRoutineCall(initFunctionIdPtr, false);
  536. //-------------------------------------------------------------------------
  537. // Since we're calling the function directly, we need to compensate for the
  538. // codeSegmentPtr being incremented by 1 in the normal execRoutineCall...
  539. codeSegmentPtr--;
  540. }
  541. }
  542. if (initFunctionIdPtr != childRoutineIdPtr) {
  543. //-----------------------------------------------------------------------
  544. // If we're calling the module's init function, and we just did above,
  545. // don't call it again! That's why we make the check on the above line...
  546. execRoutineCall(childRoutineIdPtr, false);
  547. //-------------------------------------------------------------------------
  548. // Since we're calling the function directly, we need to compensate for the
  549. // codeSegmentPtr being incremented by 1 in the normal execRoutineCall...
  550. codeSegmentPtr--;
  551. }
  552. //---------------------------------------------
  553. // In case we exited with a return statement...
  554. ExitWithReturn = false;
  555. ExitFromTacOrder = false;
  556. routineExit(routineIdPtr);
  557. CurRoutineIdPtr = thisRoutineIdPtr;
  558. }
  559. //***************************************************************************
  560. // MISC routines
  561. //***************************************************************************