Ablscan.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369
  1. //===========================================================================//
  2. // Copyright (C) Microsoft Corporation. All rights reserved. //
  3. //===========================================================================//
  4. //***************************************************************************
  5. //
  6. // ABLSCAN.CPP
  7. //
  8. //***************************************************************************
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12. #include <string.h>
  13. #include <time.h>
  14. #ifndef ABLGEN_H
  15. #include "ablgen.h"
  16. #endif
  17. #ifndef ABLERR_H
  18. #include "ablerr.h"
  19. #endif
  20. #ifndef ABLSCAN_H
  21. #include "ablscan.h"
  22. #endif
  23. #ifndef ABLPARSE_H
  24. #include "ablparse.h"
  25. #endif
  26. #ifndef ABLENV_H
  27. #include "ablenv.h"
  28. #endif
  29. //***************************************************************************
  30. #pragma warning(disable:4244)
  31. //---------------------
  32. // RESERVED WORD tables
  33. #define MINLEN_RESERVED_WORD 2
  34. #define MAXLEN_RESERVED_WORD 11
  35. ReservedWord reservedWord2[] = {
  36. {"if", TKN_IF},
  37. {"or", TKN_OR},
  38. {"do", TKN_DO},
  39. {"to", TKN_TO},
  40. {NULL, TKN_NONE}
  41. };
  42. ReservedWord reservedWord3[] = {
  43. {"and", TKN_AND},
  44. {"for", TKN_FOR},
  45. {"mod", TKN_MOD},
  46. {"not", TKN_NOT},
  47. {"var", TKN_VAR},
  48. {"fsm", TKN_FSM},
  49. {NULL, TKN_NONE}
  50. };
  51. ReservedWord reservedWord4[] = {
  52. {"else", TKN_ELSE},
  53. {"then", TKN_THEN},
  54. {"case", TKN_CASE},
  55. {"code", TKN_CODE},
  56. {"type", TKN_TYPE},
  57. {NULL, TKN_NONE}
  58. };
  59. ReservedWord reservedWord5[] = {
  60. {"const", TKN_CONST},
  61. {"until", TKN_UNTIL},
  62. {"while", TKN_WHILE},
  63. {"endif", TKN_END_IF},
  64. {"order", TKN_ORDER},
  65. {"state", TKN_STATE},
  66. {"trans", TKN_TRANS},
  67. {NULL, TKN_NONE}
  68. };
  69. ReservedWord reservedWord6[] = {
  70. {"module", TKN_MODULE},
  71. {"repeat", TKN_REPEAT},
  72. {"endfor", TKN_END_FOR},
  73. {"switch", TKN_SWITCH},
  74. {"static", TKN_STATIC},
  75. {"endfsm", TKN_END_FSM},
  76. {NULL, TKN_NONE}
  77. };
  78. ReservedWord reservedWord7[] = {
  79. {"endcase", TKN_END_CASE},
  80. {"eternal", TKN_ETERNAL},
  81. {"library", TKN_LIBRARY},
  82. {NULL, TKN_NONE}
  83. };
  84. ReservedWord reservedWord8[] = {
  85. {"function", TKN_FUNCTION},
  86. {"endwhile", TKN_END_WHILE},
  87. {"endorder", TKN_END_ORDER},
  88. {"endstate", TKN_END_STATE},
  89. {NULL, TKN_NONE}
  90. };
  91. ReservedWord reservedWord9[] = {
  92. {"endswitch", TKN_END_SWITCH},
  93. {"endmodule", TKN_END_MODULE},
  94. {"transback", TKN_TRANS_BACK},
  95. {NULL, TKN_NONE} //This was missing. Thank You Symantec!!!! 1/24/97 -fs
  96. };
  97. ReservedWord reservedWord10[] = {
  98. {"endlibrary", TKN_END_LIBRARY},
  99. {NULL, TKN_NONE}
  100. };
  101. ReservedWord reservedWord11[] = {
  102. {"endfunction", TKN_END_FUNCTION},
  103. {NULL, TKN_NONE}
  104. };
  105. ReservedWord* reservedWordTable[] = {
  106. NULL,
  107. NULL,
  108. reservedWord2,
  109. reservedWord3,
  110. reservedWord4,
  111. reservedWord5,
  112. reservedWord6,
  113. reservedWord7,
  114. reservedWord8,
  115. reservedWord9,
  116. reservedWord10,
  117. reservedWord11
  118. };
  119. //------------
  120. // TOKEN lists
  121. TokenCodeType statementStartList[] = {
  122. TKN_FOR,
  123. TKN_IF,
  124. TKN_REPEAT,
  125. TKN_WHILE,
  126. TKN_SWITCH,
  127. TKN_TRANS,
  128. TKN_TRANS_BACK,
  129. TKN_IDENTIFIER,
  130. TKN_NONE
  131. };
  132. TokenCodeType statementEndList[] = {
  133. TKN_SEMICOLON,
  134. TKN_END_IF,
  135. TKN_END_WHILE,
  136. TKN_END_FOR,
  137. TKN_END_SWITCH,
  138. TKN_END_FUNCTION,
  139. TKN_END_ORDER,
  140. TKN_END_STATE,
  141. TKN_ELSE,
  142. TKN_ELSIF,
  143. TKN_UNTIL,
  144. TKN_EOF,
  145. TKN_NONE
  146. };
  147. TokenCodeType declarationStartList[] = {
  148. TKN_CONST,
  149. TKN_VAR,
  150. TKN_FUNCTION,
  151. TKN_ORDER,
  152. TKN_STATE,
  153. TKN_NONE
  154. };
  155. char* TokenStrings[NUM_TOKENS] = {
  156. "{BAD TOKEN}",
  157. "{IDENTIFIER}",
  158. "{NUMBER}",
  159. "{TYPE}",
  160. "{STRING}",
  161. "*",
  162. "(",
  163. ")",
  164. "-",
  165. "+",
  166. "=",
  167. "[",
  168. "]",
  169. ":",
  170. ";",
  171. "<",
  172. ">",
  173. ",",
  174. ".",
  175. "/",
  176. "==",
  177. "<=",
  178. ">=",
  179. "<>",
  180. "{EOF}",
  181. "{ERROR}",
  182. "code",
  183. "order",
  184. "state",
  185. "and",
  186. "switch",
  187. "case",
  188. "const",
  189. "div",
  190. "do",
  191. "of",
  192. "else",
  193. "endif",
  194. "endwhile",
  195. "endfor",
  196. "endfunction",
  197. "endorder",
  198. "endstate",
  199. "endmodule",
  200. "endfsm",
  201. "endlibrary",
  202. "endvar",
  203. "endcode",
  204. "endcase",
  205. "endswitch",
  206. "for",
  207. "function",
  208. "if",
  209. "mod",
  210. "not",
  211. "or",
  212. "repeat",
  213. "then",
  214. "to",
  215. "until",
  216. "var",
  217. "@",
  218. "while",
  219. "elsif",
  220. "return",
  221. "module",
  222. "fsm",
  223. "trans",
  224. "transback",
  225. "library",
  226. "eternal",
  227. "static",
  228. "#",
  229. "{UNEXPECTED TOKEN}",
  230. "{STATEMENT MARKER}",
  231. "{ADDRESS MARKER}"
  232. };
  233. //--------
  234. // GLOBALS
  235. char curChar;
  236. TokenCodeType curToken;
  237. Literal curLiteral;
  238. long level = 0;
  239. long lineNumber = 0;
  240. long FileNumber = 0;
  241. ABLFile* sourceFile = NULL;
  242. bool printFlag = true;
  243. bool blockFlag = false;
  244. BlockType blockType = BLOCK_MODULE;
  245. SymTableNodePtr CurModuleIdPtr = NULL;
  246. SymTableNodePtr CurRoutineIdPtr = NULL;
  247. bool DumbGetCharOn = false;
  248. long NumOpenFiles = 0;
  249. long NumSourceFiles = 0;
  250. char SourceFiles[MAX_SOURCE_FILES][MAXLEN_FILENAME];
  251. SourceFile openFiles[MAX_INCLUDE_DEPTH];
  252. char sourceBuffer[MAXLEN_SOURCELINE];
  253. char tokenString[MAXLEN_TOKENSTRING];
  254. char wordString[MAXLEN_TOKENSTRING];
  255. long bufferOffset = 0;
  256. char* bufferp = sourceBuffer;
  257. char* tokenp = tokenString;
  258. long digitCount = 0;
  259. bool countError = false;
  260. long pageNumber = 0;
  261. long lineCount = MAX_LINES_PER_PAGE;
  262. char sourceName[MAXLEN_FILENAME];
  263. char date[LEN_DATESTRING];
  264. CharCodeType charTable[256];
  265. extern bool AssertEnabled;
  266. extern bool PrintEnabled;
  267. extern bool StringFunctionsEnabled;
  268. extern bool DebugCodeEnabled;
  269. extern ABLModulePtr CurLibrary;
  270. long (*ABLFile::createCB) (void** file, char* fName) = NULL;
  271. long (*ABLFile::openCB) (void** file, char* fName) = NULL;
  272. long (*ABLFile::closeCB) (void** file) = NULL;
  273. bool (*ABLFile::eofCB) (void* file) = NULL;
  274. long (*ABLFile::readCB) (void* file, unsigned char* buffer, long length) = NULL;
  275. long (*ABLFile::readLongCB) (void* file) = NULL;
  276. long (*ABLFile::readStringCB) (void* file, unsigned char* buffer) = NULL;
  277. long (*ABLFile::readLineExCB) (void* file, unsigned char* buffer, long maxLength) = NULL;
  278. long (*ABLFile::writeCB) (void* file, unsigned char* buffer, long length) = NULL;
  279. long (*ABLFile::writeByteCB) (void* file, unsigned char byte) = NULL;
  280. long (*ABLFile::writeLongCB) (void* file, long value) = NULL;
  281. long (*ABLFile::writeStringCB) (void* file, char* buffer) = NULL;
  282. //***************************************************************************
  283. // ABL FILE routines
  284. //***************************************************************************
  285. void* ABLFile::operator new (size_t ourSize) {
  286. void* result = ABLSystemMallocCallback(ourSize);
  287. return(result);
  288. }
  289. //---------------------------------------------------------------------------
  290. void ABLFile::operator delete (void* us) {
  291. ABLSystemFreeCallback(us);
  292. }
  293. //---------------------------------------------------------------------------
  294. void ABLFile::init (void) {
  295. fileName = 0;
  296. file = NULL;
  297. }
  298. //-----------------------------------------------------------------------------
  299. void ABLFile::destroy (void) {
  300. if (fileName) {
  301. ABLSystemFreeCallback(fileName);
  302. fileName = NULL;
  303. }
  304. file = NULL;
  305. }
  306. //---------------------------------------------------------------------------
  307. long ABLFile::create (char* fName) {
  308. if (fName) {
  309. fileName = (char*)ABLSystemMallocCallback(strlen(fName)+1);
  310. strcpy(fileName,fName);
  311. return(createCB(&file, fileName));
  312. }
  313. return(-1);
  314. }
  315. //---------------------------------------------------------------------------
  316. long ABLFile::open (char* fName) {
  317. if (fName) {
  318. fileName = (char*)ABLSystemMallocCallback(strlen(fName)+1);
  319. strcpy(fileName,fName);
  320. return(openCB(&file, fileName));
  321. }
  322. return(-1);
  323. }
  324. //---------------------------------------------------------------------------
  325. long ABLFile::close (void) {
  326. if (file)
  327. return(closeCB(&file));
  328. return(-1);
  329. }
  330. //-----------------------------------------------------------------------------
  331. bool ABLFile::eof (void) {
  332. if (file)
  333. return(eofCB(file));
  334. return(true);
  335. }
  336. //-----------------------------------------------------------------------------
  337. long ABLFile::read (unsigned char* buffer, long length) {
  338. if (file)
  339. return(readCB(file, buffer, length));
  340. return(0);
  341. }
  342. //-----------------------------------------------------------------------------
  343. long ABLFile::readLong (void) {
  344. if (file)
  345. return(readLongCB(file));
  346. return(-1);
  347. }
  348. //-----------------------------------------------------------------------------
  349. long ABLFile::readString (unsigned char* buffer) {
  350. if (file)
  351. return(readStringCB(file, buffer));
  352. return(0);
  353. }
  354. //-----------------------------------------------------------------------------
  355. long ABLFile::readLineEx (unsigned char* buffer, long maxLength) {
  356. if (file)
  357. return(readLineExCB(file, buffer, maxLength));
  358. return(0);
  359. }
  360. //-----------------------------------------------------------------------------
  361. long ABLFile::write (unsigned char* buffer, long length) {
  362. if (file)
  363. return(writeCB(file, buffer, length));
  364. return(0);
  365. }
  366. //-----------------------------------------------------------------------------
  367. long ABLFile::writeByte (unsigned char val) {
  368. if (file)
  369. return(writeByteCB(file, val));
  370. return(0);
  371. }
  372. //-----------------------------------------------------------------------------
  373. long ABLFile::writeLong (long val) {
  374. if (file)
  375. return(writeLongCB(file, val));
  376. return(0);
  377. }
  378. //-----------------------------------------------------------------------------
  379. long ABLFile::writeString (char* buffer) {
  380. if (file)
  381. return(writeStringCB(file, buffer));
  382. return(0);
  383. }
  384. //***************************************************************************
  385. // MISC routines
  386. //***************************************************************************
  387. inline CharCodeType calcCharCode (long ch) {
  388. return(charTable[ch]);
  389. }
  390. //***************************************************************************
  391. long isReservedWord (void)
  392. {
  393. long wordLength = strlen(wordString);
  394. if ((wordLength >= MINLEN_RESERVED_WORD) && (wordLength <= MAXLEN_RESERVED_WORD) && reservedWordTable[wordLength])
  395. {
  396. for (ReservedWord* rwPtr = reservedWordTable[wordLength]; rwPtr->string != NULL; rwPtr++)
  397. {
  398. if (strcmp(wordString, rwPtr->string) == 0)
  399. {
  400. curToken = rwPtr->tokenCode;
  401. return(1);
  402. }
  403. }
  404. }
  405. return(0);
  406. }
  407. //***************************************************************************
  408. // INITIALIZATION routines
  409. //***************************************************************************
  410. void getChar();
  411. void initScanner (char* fileName) {
  412. //----------------------------------
  413. // Initialize the character table...
  414. for (long curCh = 0; curCh < 256; curCh++)
  415. charTable[curCh] = CHR_SPECIAL;
  416. for (curCh = '0'; curCh <= '9'; curCh++)
  417. charTable[curCh] = CHR_DIGIT;
  418. for (curCh = 'A'; curCh <= 'Z'; curCh++)
  419. charTable[curCh] = CHR_LETTER;
  420. for (curCh = 'a'; curCh <= 'z'; curCh++)
  421. charTable[curCh] = CHR_LETTER;
  422. charTable['\"'] = CHR_DQUOTE;
  423. charTable[CHAR_EOF] = CHR_EOF;
  424. //---------------------------------------
  425. // Now, let's open the ABL source file...
  426. if (fileName)
  427. {
  428. sourceFile = new ABLFile;
  429. if (sourceFile->open(fileName) != ABL_NO_ERR)
  430. {
  431. syntaxError(ABL_ERR_SYNTAX_SOURCE_FILE_OPEN);
  432. curToken = TKN_ERROR;
  433. }
  434. sourceBuffer[0] = NULL;
  435. bufferp = sourceBuffer;
  436. getChar();
  437. }
  438. }
  439. //***************************************************************************
  440. void quitScanner (void) {
  441. sourceFile->close();
  442. delete sourceFile;
  443. sourceFile = NULL;
  444. }
  445. //***************************************************************************
  446. // CHARACTER routines
  447. //***************************************************************************
  448. void skipLineComment (void) {
  449. //-------------------------------------------------------------------
  450. // Just blow off the rest of the current source line we've read in...
  451. *bufferp = NULL;
  452. curChar = ' ';
  453. }
  454. //***************************************************************************
  455. void skipBlockComment (void) {
  456. //----------------------------------------------------
  457. // Snag the asterisk, then continue until we encounter
  458. // the closing "*/"...
  459. DumbGetCharOn = true;
  460. getChar();
  461. getChar();
  462. do {
  463. while ((curChar != '*') && (curChar != CHR_EOF))
  464. getChar();
  465. if (curChar == CHR_EOF) {
  466. syntaxError(ABL_ERR_SYNTAX_UNEXPECTED_EOF);
  467. curToken = TKN_ERROR;
  468. }
  469. getChar();
  470. } while (curChar != '/');
  471. curChar = ' ';
  472. DumbGetCharOn = false;
  473. }
  474. //***************************************************************************
  475. void skipBlanks (void) {
  476. while (curChar == ' ')
  477. getChar();
  478. }
  479. //***************************************************************************
  480. void languageDirective (void) {
  481. DumbGetCharOn = true;
  482. getChar();
  483. char directive[32];
  484. long directiveLength = 0;
  485. while ((curChar != ' ') && (curChar != '\n') && (curChar != '\r') && (directiveLength < 31)) {
  486. directive[directiveLength++] = curChar;
  487. getChar();
  488. }
  489. directive[directiveLength] = NULL;
  490. _strlwr(directive);
  491. if (strcmp(directive, "include") == 0) {
  492. //---------------------
  493. // INCLUDE directive...
  494. getChar();
  495. if (curChar == '"') {
  496. getChar();
  497. char fileName[128];
  498. long fileNameLength = 0;
  499. while ((curChar != '"') && (fileNameLength < 127)) {
  500. fileName[fileNameLength++] = curChar;
  501. getChar();
  502. }
  503. fileName[fileNameLength] = NULL;
  504. //-----------------------------------------------------------------------
  505. // The language directive should be on a line by itself, since everything
  506. // after the directive on this line is ignored...
  507. DumbGetCharOn = false;
  508. //----------------------------------------------------
  509. // Now that we have the file name, let's include it...
  510. long openErr = ABL_NO_ERR;
  511. if ((openErr = openSourceFile(fileName)) != ABL_NO_ERR) {
  512. syntaxError(ABL_ERR_SYNTAX_SOURCE_FILE_OPEN);
  513. curToken = TKN_ERROR;
  514. }
  515. }
  516. else {
  517. syntaxError(ABL_ERR_SYNTAX_BAD_LANGUAGE_DIRECTIVE_USAGE);
  518. curToken = TKN_ERROR;
  519. }
  520. }
  521. else if (strcmp(directive, "include_") == 0) {
  522. //---------------------
  523. // INCLUDE directive...
  524. getChar();
  525. if (curChar == '"') {
  526. getChar();
  527. char fileName[128];
  528. long fileNameLength = 0;
  529. while ((curChar != '"') && (fileNameLength < 127)) {
  530. fileName[fileNameLength++] = curChar;
  531. getChar();
  532. }
  533. fileName[fileNameLength] = NULL;
  534. //-----------------------------------------------------------------------
  535. // The language directive should be on a line by itself, since everything
  536. // after the directive on this line is ignored...
  537. DumbGetCharOn = false;
  538. //----------------------------------------------------
  539. // Now that we have the file name, let's include it...
  540. long openErr = ABL_NO_ERR;
  541. //---------------------------------------
  542. // What's the current module's directory?
  543. char fullPath[255];
  544. long curChar = strlen(SourceFiles[0]);
  545. while ((curChar > -1) && (SourceFiles[0][curChar] != '\\'))
  546. curChar--;
  547. if (curChar == -1)
  548. strcpy(fullPath, fileName);
  549. else {
  550. strcpy(fullPath, SourceFiles[0]);
  551. fullPath[curChar + 1] = NULL;
  552. strcat(fullPath, fileName);
  553. }
  554. if ((openErr = openSourceFile(fullPath)) != ABL_NO_ERR) {
  555. syntaxError(ABL_ERR_SYNTAX_SOURCE_FILE_OPEN);
  556. curToken = TKN_ERROR;
  557. }
  558. }
  559. else {
  560. syntaxError(ABL_ERR_SYNTAX_BAD_LANGUAGE_DIRECTIVE_USAGE);
  561. curToken = TKN_ERROR;
  562. }
  563. }
  564. else if (strcmp(directive, "assert_on") == 0) {
  565. DumbGetCharOn = false;
  566. curChar = ' ';
  567. AssertEnabled = true;
  568. }
  569. else if (strcmp(directive, "assert_off") == 0) {
  570. DumbGetCharOn = false;
  571. curChar = ' ';
  572. AssertEnabled = false;
  573. }
  574. else if (strcmp(directive, "print_on") == 0) {
  575. DumbGetCharOn = false;
  576. curChar = ' ';
  577. PrintEnabled = true;
  578. }
  579. else if (strcmp(directive, "print_off") == 0) {
  580. DumbGetCharOn = false;
  581. curChar = ' ';
  582. PrintEnabled = false;
  583. }
  584. else if (strcmp(directive, "stringfuncs_on") == 0) {
  585. DumbGetCharOn = false;
  586. curChar = ' ';
  587. StringFunctionsEnabled = true;
  588. }
  589. else if (strcmp(directive, "stringfuncs_off") == 0) {
  590. DumbGetCharOn = false;
  591. curChar = ' ';
  592. StringFunctionsEnabled = false;
  593. }
  594. else if (strcmp(directive, "debug_on") == 0) {
  595. DumbGetCharOn = false;
  596. curChar = ' ';
  597. DebugCodeEnabled = true;
  598. }
  599. else if (strcmp(directive, "debug_off") == 0) {
  600. DumbGetCharOn = false;
  601. curChar = ' ';
  602. DebugCodeEnabled = false;
  603. }
  604. else if (strcmp(directive, "debug_start") == 0) {
  605. bool stillCutting = true;
  606. if (!DebugCodeEnabled) {
  607. long nestedLevel = 1;
  608. getChar();
  609. // getChar();
  610. do {
  611. while ((curChar != '#') && (curChar != CHR_EOF))
  612. getChar();
  613. if (curChar == '#') {
  614. char directive2[32];
  615. long directiveLength = 0;
  616. while ((curChar != ' ') && (curChar != '\n') && (curChar != '\r') && (directiveLength < 31)) {
  617. directive2[directiveLength++] = curChar;
  618. getChar();
  619. }
  620. directive2[directiveLength] = NULL;
  621. _strlwr(directive2);
  622. if (strcmp(directive2, "#debug_start") == 0)
  623. nestedLevel++;
  624. else if (strcmp(directive2, "#debug_end") == 0) {
  625. nestedLevel--;
  626. if (nestedLevel == 0)
  627. stillCutting = false;
  628. }
  629. }
  630. else if (curChar == CHR_EOF) {
  631. syntaxError(ABL_ERR_SYNTAX_UNEXPECTED_EOF);
  632. curToken = TKN_ERROR;
  633. }
  634. else
  635. getChar();
  636. } while (stillCutting);
  637. }
  638. curChar = ' ';
  639. DumbGetCharOn = false;
  640. }
  641. else if (strcmp(directive, "debug_end") == 0) {
  642. curChar = ' ';
  643. DumbGetCharOn = false;
  644. }
  645. else {
  646. syntaxError(ABL_ERR_SYNTAX_UNKNOWN_LANGUAGE_DIRECTIVE);
  647. curToken = TKN_ERROR;
  648. }
  649. }
  650. //***************************************************************************
  651. void getChar (void) {
  652. if (*bufferp == NULL) {
  653. if (!getSourceLine()) {
  654. if (NumOpenFiles > 1) {
  655. closeSourceFile();
  656. return;
  657. }
  658. else {
  659. curChar = CHAR_EOF;
  660. return;
  661. }
  662. }
  663. bufferp = sourceBuffer;
  664. bufferOffset = 0;
  665. }
  666. curChar = *bufferp;
  667. bufferp++;
  668. if (DumbGetCharOn) {
  669. bufferOffset++;
  670. return;
  671. }
  672. //-------------------
  673. // Special Characters
  674. switch (curChar) {
  675. case '\t':
  676. // TAB
  677. bufferOffset += TAB_SIZE - bufferOffset % TAB_SIZE;
  678. curChar = ' ';
  679. break;
  680. case '\n':
  681. case '\r':
  682. // NEWLINE
  683. bufferOffset++;
  684. curChar = ' ';
  685. break;
  686. case '/':
  687. if (*bufferp == '/')
  688. skipLineComment();
  689. else if (*bufferp == '*')
  690. skipBlockComment();
  691. else
  692. bufferOffset++;
  693. break;
  694. case '#':
  695. languageDirective();
  696. break;
  697. default:
  698. bufferOffset++;
  699. }
  700. }
  701. //***************************************************************************
  702. // TOKEN routines
  703. //***************************************************************************
  704. void downShiftWord (void) {
  705. long offset = 'a' - 'A';
  706. char* wp = wordString;
  707. char* tp = tokenString;
  708. long checkLengthWord = strlen(wordString);
  709. long checkLengthToken = strlen(tokenString);
  710. if ((checkLengthWord >= MAXLEN_TOKENSTRING) || (checkLengthToken >= MAXLEN_TOKENSTRING))
  711. ABL_Fatal(-1," Boy did Glenn screw the pooch here!! ");
  712. do {
  713. *wp = ((*tp >= 'A') && (*tp <= 'Z')) ? (*tp + (char)offset) : *tp;
  714. wp++;
  715. tp++;
  716. } while (*tp != NULL);
  717. *wp = NULL;
  718. }
  719. //***************************************************************************
  720. void getToken(void) {
  721. skipBlanks();
  722. tokenp = tokenString;
  723. switch (calcCharCode(curChar)) {
  724. case CHR_LETTER:
  725. getWord();
  726. break;
  727. case CHR_DIGIT:
  728. getNumber();
  729. break;
  730. case CHR_DQUOTE:
  731. getString();
  732. break;
  733. case CHR_EOF:
  734. curToken = TKN_EOF;
  735. break;
  736. default:
  737. getSpecial();
  738. break;
  739. }
  740. if (blockFlag)
  741. crunchToken();
  742. }
  743. //***************************************************************************
  744. void getWord (void) {
  745. while ((calcCharCode(curChar) == CHR_LETTER) || (calcCharCode(curChar) == CHR_DIGIT) || (curChar == '_')) {
  746. *tokenp = curChar;
  747. tokenp++;
  748. getChar();
  749. }
  750. *tokenp = NULL;
  751. downShiftWord();
  752. if (curChar == '.') {
  753. TokenCodeType endToken = TKN_END_MODULE;
  754. if (CurLibrary)
  755. endToken = TKN_END_LIBRARY;
  756. else if (CurModuleIdPtr->defn.info.routine.flags & ROUTINE_FLAG_FSM)
  757. endToken = TKN_END_FSM;
  758. //-------------------------------------------------------------------
  759. // If we have an "endmodule" string, stop. Otherwise, keep reading...
  760. if (strcmp(wordString, TokenStrings[endToken])) {
  761. *tokenp = curChar;
  762. tokenp++;
  763. getChar();
  764. while ((calcCharCode(curChar) == CHR_LETTER) || (calcCharCode(curChar) == CHR_DIGIT) || (curChar == '_')) {
  765. *tokenp = curChar;
  766. tokenp++;
  767. getChar();
  768. }
  769. *tokenp = NULL;
  770. downShiftWord();
  771. }
  772. }
  773. if (!isReservedWord())
  774. curToken = TKN_IDENTIFIER;
  775. }
  776. //***************************************************************************
  777. void accumulateValue (float* valuePtr, SyntaxErrorType errCode) {
  778. float value = *valuePtr;
  779. //--------------------------------------------
  780. // Make sure the first character is a digit...
  781. if (calcCharCode(curChar) != CHR_DIGIT) {
  782. syntaxError(errCode);
  783. curToken = TKN_ERROR;
  784. return;
  785. }
  786. do {
  787. *tokenp = curChar;
  788. tokenp++;
  789. if (++digitCount <= MAX_DIGIT_COUNT)
  790. value = 10 * value + (curChar - '0');
  791. else
  792. countError = true;
  793. getChar();
  794. } while (calcCharCode(curChar) == CHR_DIGIT);
  795. *valuePtr = value;
  796. }
  797. //***************************************************************************
  798. void getNumber (void) {
  799. long wholeCount = 0;
  800. long decimalOffset = 0;
  801. char exponentSign = '+';
  802. long exponent = 0;
  803. float numberValue = (float)0.0;
  804. float exponentValue = (float)0.0;
  805. digitCount = 0;
  806. countError = false;
  807. curToken = TKN_NONE;
  808. //------------------------------------
  809. // Assume it's an integer, at first...
  810. curLiteral.type = LIT_INTEGER;
  811. accumulateValue(&numberValue, ABL_ERR_SYNTAX_INVALID_NUMBER);
  812. if (curToken == TKN_ERROR)
  813. return;
  814. wholeCount = digitCount;
  815. if (curChar == '.') {
  816. getChar();
  817. curLiteral.type = LIT_REAL;
  818. *tokenp = '.';
  819. tokenp++;
  820. accumulateValue(&numberValue, ABL_ERR_SYNTAX_INVALID_FRACTION);
  821. if (curToken == TKN_ERROR)
  822. return;
  823. decimalOffset = wholeCount - digitCount;
  824. }
  825. if ((curChar == 'E') || (curChar == 'e')) {
  826. curLiteral.type = LIT_REAL;
  827. *tokenp = curChar;
  828. tokenp++;
  829. //-------------------
  830. // Any exponent sign?
  831. if ((curChar == '+') || (curChar == '-')) {
  832. *tokenp = exponentSign = curChar;
  833. tokenp++;
  834. getChar();
  835. }
  836. accumulateValue(&exponentValue, ABL_ERR_SYNTAX_INVALID_EXPONENT);
  837. if (curToken == TKN_ERROR)
  838. return;
  839. if (exponentSign == '-')
  840. exponentValue = -exponentValue;
  841. }
  842. //-----------------
  843. // Too many digits?
  844. if (countError) {
  845. syntaxError(ABL_ERR_SYNTAX_TOO_MANY_DIGITS);
  846. curToken = TKN_ERROR;
  847. return;
  848. }
  849. //------------------------------------------------------------
  850. // Adjust number's value using decimal offset and the exponent
  851. exponent = exponentValue + decimalOffset;
  852. if ((exponent + wholeCount < -MAX_EXPONENT) || (exponent + wholeCount > MAX_EXPONENT)) {
  853. syntaxError(ABL_ERR_SYNTAX_REAL_OUT_OF_RANGE);
  854. curToken = TKN_ERROR;
  855. return;
  856. }
  857. if (exponent != 0)
  858. numberValue *= (float)pow(10.0, (double)exponent);
  859. //---------------------------
  860. // Set the literal's value...
  861. if (curLiteral.type == LIT_INTEGER)
  862. {
  863. // This line can never be true, right?
  864. // If I cast to long it can't be outside that range!!
  865. // if (((long)numberValue < -MAX_INTEGER) || ((long)numberValue > MAX_INTEGER))
  866. // {
  867. // syntaxError(ABL_ERR_SYNTAX_INTEGER_OUT_OF_RANGE);
  868. // curToken = TKN_ERROR;
  869. // return;
  870. // }
  871. curLiteral.value.integer = (long)numberValue;
  872. }
  873. else
  874. curLiteral.value.real = numberValue;
  875. *tokenp = NULL;
  876. curToken = TKN_NUMBER;
  877. }
  878. //***************************************************************************
  879. //---------------------------------------------------
  880. // NOTE: Currently, ABL does not have STRING types...
  881. void getString (void) {
  882. char* stringPtr = curLiteral.value.string;
  883. *tokenp = '\"';
  884. getChar();
  885. while (curChar != CHAR_EOF) {
  886. if (curChar == '\"')
  887. break;
  888. *tokenp = curChar;
  889. tokenp++;
  890. *stringPtr = curChar;
  891. stringPtr++;
  892. getChar();
  893. }
  894. curChar = ' ';
  895. *tokenp = NULL;
  896. *stringPtr = NULL;
  897. curToken = TKN_STRING;
  898. curLiteral.type = LIT_STRING;
  899. }
  900. //***************************************************************************
  901. void getSpecial (void) {
  902. *tokenp = curChar;
  903. tokenp++;
  904. switch (curChar) {
  905. // case '^':
  906. // curToken = TKN_UPARROW;
  907. // getChar();
  908. // break;
  909. case '*':
  910. curToken = TKN_STAR;
  911. getChar();
  912. break;
  913. case '(':
  914. curToken = TKN_LPAREN;
  915. getChar();
  916. break;
  917. case ')':
  918. curToken = TKN_RPAREN;
  919. getChar();
  920. break;
  921. case '-':
  922. curToken = TKN_MINUS;
  923. getChar();
  924. break;
  925. case '+':
  926. curToken = TKN_PLUS;
  927. getChar();
  928. break;
  929. case '[':
  930. curToken = TKN_LBRACKET;
  931. getChar();
  932. break;
  933. case ']':
  934. curToken = TKN_RBRACKET;
  935. getChar();
  936. break;
  937. case ';':
  938. curToken = TKN_SEMICOLON;
  939. getChar();
  940. break;
  941. case '@':
  942. curToken = TKN_REF;
  943. getChar();
  944. break;
  945. case '#':
  946. curToken = TKN_POUND;
  947. getChar();
  948. break;
  949. // NOTE: For now, let's use the BEGIN and END keywords instead of braces.
  950. // If popular demand is to get rid of the begin/end keywords and switch
  951. // to braces, we can do so...
  952. // case '{':
  953. // curToken = TKN_BEGIN;
  954. // getChar();
  955. // break;
  956. // case '}':
  957. // curToken = TKN_END;
  958. // getChar();
  959. // break;
  960. case ',':
  961. curToken = TKN_COMMA;
  962. getChar();
  963. break;
  964. case '/':
  965. //-----------------------------------------------
  966. // In theory :), we shouldn't have to worry about
  967. // comments here, as getChar syphons them out...
  968. curToken = TKN_FSLASH;
  969. getChar();
  970. break;
  971. case '=':
  972. getChar();
  973. if (curChar == '=') {
  974. *tokenp = '=';
  975. tokenp++;
  976. curToken = TKN_EQUALEQUAL;
  977. getChar();
  978. }
  979. else
  980. curToken = TKN_EQUAL;
  981. break;
  982. case '<':
  983. getChar();
  984. if (curChar == '=') {
  985. *tokenp = '=';
  986. tokenp++;
  987. curToken = TKN_LE;
  988. getChar();
  989. }
  990. else if (curChar == '>') {
  991. *tokenp = '>';
  992. tokenp++;
  993. curToken = TKN_NE;
  994. getChar();
  995. }
  996. else
  997. curToken = TKN_LT;
  998. break;
  999. case '>':
  1000. getChar();
  1001. if (curChar == '=') {
  1002. *tokenp = '=';
  1003. tokenp++;
  1004. curToken = TKN_GE;
  1005. getChar();
  1006. }
  1007. else
  1008. curToken = TKN_GT;
  1009. break;
  1010. case '.':
  1011. curToken = TKN_PERIOD;
  1012. getChar();
  1013. break;
  1014. case ':':
  1015. curToken = TKN_COLON;
  1016. getChar();
  1017. break;
  1018. default:
  1019. curToken = TKN_ERROR;
  1020. getChar();
  1021. break;
  1022. }
  1023. *tokenp = NULL;
  1024. }
  1025. //***************************************************************************
  1026. // TOKEN TESTER routines
  1027. //***************************************************************************
  1028. bool tokenIn (TokenCodeType* tokenList) {
  1029. if (!tokenList)
  1030. return(false);
  1031. for (TokenCodeType* tp = &tokenList[0]; *tp; tp++)
  1032. if (curToken == *tp)
  1033. return(true);
  1034. return(false);
  1035. }
  1036. //***************************************************************************
  1037. void synchronize (TokenCodeType* tokenList1,
  1038. TokenCodeType* tokenList2,
  1039. TokenCodeType* tokenList3) {
  1040. bool badLists = (!tokenIn(tokenList1) && !tokenIn(tokenList2) && !tokenIn(tokenList3));
  1041. if (badLists) {
  1042. syntaxError((curToken == TKN_EOF) ? ABL_ERR_SYNTAX_UNEXPECTED_EOF : ABL_ERR_SYNTAX_UNEXPECTED_TOKEN);
  1043. //----------------------------------------------
  1044. // Now, we need to re-sync by skipping tokens...
  1045. while (!tokenIn(tokenList1) &&
  1046. !tokenIn(tokenList2) &&
  1047. !tokenIn(tokenList3) &&
  1048. (curToken != TKN_EOF))
  1049. getToken();
  1050. }
  1051. }
  1052. //***************************************************************************
  1053. // SOURCE FILE routines
  1054. //***************************************************************************
  1055. bool getSourceLine (void) {
  1056. if (!sourceFile->eof())
  1057. {
  1058. long numChars = sourceFile->readLineEx((unsigned char*)sourceBuffer, MAXLEN_SOURCELINE);
  1059. if (numChars == 0)
  1060. return(false);
  1061. lineNumber++;
  1062. if (printFlag)
  1063. {
  1064. char printBuffer[MAXLEN_SOURCELINE + 9];
  1065. sprintf(printBuffer, "%4d %d: %s", lineNumber, level, sourceBuffer);
  1066. printLine(printBuffer);
  1067. }
  1068. return(true);
  1069. }
  1070. else
  1071. return(false);
  1072. }
  1073. //---------------------------------------------------------------------------
  1074. long openSourceFile (char* sourceFileName) {
  1075. //---------------------------------------
  1076. // Now, let's open the ABL source file...
  1077. if (!sourceFileName)
  1078. return(-1);
  1079. if (NumOpenFiles == MAX_INCLUDE_DEPTH)
  1080. return(-2);
  1081. if (NumSourceFiles == MAX_SOURCE_FILES)
  1082. return(-3);
  1083. ABLFile* sFile = NULL;
  1084. sFile = new ABLFile;
  1085. if (sFile->open(sourceFileName) != ABL_NO_ERR)
  1086. return(-3);
  1087. strcpy(SourceFiles[NumSourceFiles], sourceFileName);
  1088. FileNumber = NumSourceFiles++;
  1089. sourceFile = sFile;
  1090. strcpy(openFiles[NumOpenFiles].fileName, sourceFileName);
  1091. openFiles[NumOpenFiles].filePtr = sFile;
  1092. openFiles[NumOpenFiles].fileNumber = (unsigned char)FileNumber;
  1093. openFiles[NumOpenFiles].lineNumber = 0;
  1094. if (NumOpenFiles > 0)
  1095. openFiles[NumOpenFiles - 1].lineNumber = lineNumber;
  1096. NumOpenFiles++;
  1097. lineNumber = 0;
  1098. sourceBuffer[0] = NULL;
  1099. bufferp = sourceBuffer;
  1100. getChar();
  1101. return(ABL_NO_ERR);
  1102. }
  1103. //---------------------------------------------------------------------------
  1104. long closeSourceFile (void) {
  1105. if (NumOpenFiles == 0)
  1106. return(-1);
  1107. sourceFile->close();
  1108. delete sourceFile;
  1109. sourceFile = NULL;
  1110. openFiles[NumOpenFiles].filePtr = NULL;
  1111. NumOpenFiles--;
  1112. if (NumOpenFiles > 0) {
  1113. sourceFile = openFiles[NumOpenFiles - 1].filePtr;
  1114. FileNumber = openFiles[NumOpenFiles - 1].fileNumber;
  1115. lineNumber = openFiles[NumOpenFiles - 1].lineNumber;
  1116. }
  1117. return(ABL_NO_ERR);
  1118. }
  1119. //***************************************************************************
  1120. // PRINTOUT routines
  1121. //***************************************************************************
  1122. void printLine (char* line) {
  1123. if (++lineCount > MAX_LINES_PER_PAGE) {
  1124. printPageHeader();
  1125. lineCount = 1;
  1126. }
  1127. char* saveChPtr = NULL;
  1128. char saveCh = ' ';
  1129. if (strlen(line) > MAXLEN_PRINTLINE) {
  1130. saveCh = line[MAXLEN_PRINTLINE];
  1131. saveChPtr = &line[MAXLEN_PRINTLINE];
  1132. *saveChPtr = NULL;
  1133. }
  1134. printf("%s", line);
  1135. if (saveChPtr)
  1136. *saveChPtr = saveCh;
  1137. }
  1138. //***************************************************************************
  1139. void initPageHeader (char* fileName) {
  1140. //--------------------------
  1141. // Save the source file name
  1142. strncpy(sourceName, fileName, MAXLEN_FILENAME - 1);
  1143. //-------------------------------
  1144. // Save the current time and date
  1145. time_t timer;
  1146. time(&timer);
  1147. strcpy(date, asctime(localtime(&timer)));
  1148. }
  1149. //***************************************************************************
  1150. void printPageHeader (void) {
  1151. //putchar(CHAR_FORMFEED);
  1152. printf("Page %d %s %s\n\n", ++pageNumber, sourceName, date);
  1153. }
  1154. //***************************************************************************