Files
firestorm/Gameleap/code/mw4/Code/MW4/Ablscan.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1230 lines
28 KiB
C++

//***************************************************************************
//
// ABLSCAN.CPP
//
//***************************************************************************
#include "MW4Headers.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#ifndef ABLGEN_H
#include "ablgen.h"
#endif
#ifndef ABLERR_H
#include "ablerr.h"
#endif
#ifndef ABLSCAN_H
#include "ablscan.h"
#endif
#ifndef ABLPARSE_H
#include "ablparse.h"
#endif
#ifndef ABLENV_H
#include "ablenv.h"
#endif
#ifndef ABLHEAP_H
#include "ablheap.h"
#endif
#ifndef ABLFILE_H
#include "ablfile.h"
#endif
//***************************************************************************
namespace ABL
{
//---------------------
// RESERVED WORD tables
#define MINLEN_RESERVED_WORD 2
#define MAXLEN_RESERVED_WORD 11
ReservedWord reservedWord2[] = {
{"if", TKN_IF},
{"or", TKN_OR},
{"do", TKN_DO},
{"to", TKN_TO},
{NULL, TKN_NONE}
};
ReservedWord reservedWord3[] = {
{"and", TKN_AND},
{"for", TKN_FOR},
{"mod", TKN_MOD},
{"not", TKN_NOT},
{"var", TKN_VAR},
{"fsm", TKN_FSM},
{NULL, TKN_NONE}
};
ReservedWord reservedWord4[] = {
{"else", TKN_ELSE},
{"then", TKN_THEN},
{"case", TKN_CASE},
{"code", TKN_CODE},
{"type", TKN_TYPE},
{NULL, TKN_NONE}
};
ReservedWord reservedWord5[] = {
{"const", TKN_CONST},
{"until", TKN_UNTIL},
{"while", TKN_WHILE},
{"endif", TKN_END_IF},
{"trans", TKN_TRANS},
{"state", TKN_STATE},
{NULL, TKN_NONE}
};
ReservedWord reservedWord6[] = {
{"module", TKN_MODULE},
{"repeat", TKN_REPEAT},
{"endfor", TKN_END_FOR},
{"switch", TKN_SWITCH},
{"static", TKN_STATIC},
{"endfsm", TKN_END_FSM},
{NULL, TKN_NONE}
};
ReservedWord reservedWord7[] = {
{"endcase", TKN_END_CASE},
{"eternal", TKN_ETERNAL},
{"library", TKN_LIBRARY},
{NULL, TKN_NONE}
};
ReservedWord reservedWord8[] = {
{"function", TKN_FUNCTION},
{"endwhile", TKN_END_WHILE},
{"endstate", TKN_END_STATE},
{NULL, TKN_NONE}
};
ReservedWord reservedWord9[] = {
{"endswitch", TKN_END_SWITCH},
{"endmodule", TKN_END_MODULE},
{NULL, TKN_NONE} //This was missing. Thank You Symantec!!!! 1/24/97 -fs
};
ReservedWord reservedWord10[] = {
{"endlibrary", TKN_END_LIBRARY},
{NULL, TKN_NONE}
};
ReservedWord reservedWord11[] = {
{"endfunction", TKN_END_FUNCTION},
{NULL, TKN_NONE}
};
ReservedWord* reservedWordTable[] = {
NULL,
NULL,
reservedWord2,
reservedWord3,
reservedWord4,
reservedWord5,
reservedWord6,
reservedWord7,
reservedWord8,
reservedWord9,
reservedWord10,
reservedWord11
};
//------------
// TOKEN lists
TokenCodeType statementStartList[] = {
TKN_FOR,
TKN_IF,
TKN_REPEAT,
TKN_WHILE,
TKN_SWITCH,
TKN_IDENTIFIER,
TKN_TRANS,
TKN_STATE,
TKN_NONE
};
TokenCodeType statementEndList[] = {
TKN_SEMICOLON,
TKN_END_IF,
TKN_END_WHILE,
TKN_END_FOR,
TKN_END_SWITCH,
TKN_END_FUNCTION,
TKN_ELSE,
TKN_ELSIF,
TKN_UNTIL,
TKN_EOF,
TKN_NONE
};
TokenCodeType declarationStartList[] = {
TKN_CONST,
TKN_VAR,
TKN_FUNCTION,
TKN_NONE
};
char* TokenStrings[NUM_TOKENS] = {
"{BAD TOKEN}",
"{IDENTIFIER}",
"{NUMBER}",
"{TYPE}",
"{STRING}",
"*",
"(",
")",
"-",
"+",
"=",
"[",
"]",
":",
";",
"<",
">",
",",
".",
"/",
"==",
"<=",
">=",
"<>",
"{EOF}",
"{ERROR}",
"code",
"orders",
"and",
"switch",
"case",
"const",
"div",
"do",
"of",
"else",
"endif",
"endwhile",
"endfor",
"endfunction",
"endmodule",
"endlibrary",
"endvar",
"endcode",
"endcase",
"endswitch",
"for",
"function",
"if",
"mod",
"not",
"or",
"repeat",
"then",
"to",
"until",
"var",
"@",
"while",
"elsif",
"return",
"module",
"library",
"eternal",
"static",
"fsm",
"endfsm",
"state",
"endstate",
"trans",
"#",
"{UNEXPECTED TOKEN}",
"{STATEMENT MARKER}",
"{ADDRESS MARKER}"
};
//--------
// GLOBALS
UserHeapPtr AblSymTableHeap = NULL;
UserHeapPtr AblStackHeap = NULL;
UserHeapPtr AblCodeHeap = NULL;
char curChar;
TokenCodeType curToken;
Literal curLiteral;
long level = 0;
long FSMLevel = 0;
long lineNumber = 0;
long FileNumber = 0;
FilePtr sourceFile = NULL;
bool printFlag = true;
bool blockFlag = false;
BlockType blockType = BLOCK_MODULE;
SymTableNodePtr CurModuleIdPtr = NULL;
SymTableNodePtr CurRoutineIdPtr = NULL;
bool DumbGetCharOn = false;
long NumOpenFiles = 0;
long NumSourceFiles = 0;
char SourceFiles[MAX_SOURCE_FILES][MAXLEN_FILENAME];
SourceFile openFiles[MAX_INCLUDE_DEPTH];
char sourceBuffer[MAXLEN_SOURCELINE];
char tokenString[MAXLEN_TOKENSTRING];
char wordString[MAXLEN_TOKENSTRING];
long bufferOffset = 0;
char* bufferp = sourceBuffer;
char* tokenp = tokenString;
bool parsingFSM = false;
long digitCount = 0;
bool countError = false;
long pageNumber = 0;
long lineCount = MAX_LINES_PER_PAGE;
char sourceName[MAXLEN_FILENAME];
char date[LEN_DATESTRING];
CharCodeType charTable[256];
extern bool AssertEnabled;
extern bool PrintEnabled;
extern bool StringFunctionsEnabled;
extern bool DebugCodeEnabled;
extern ABLModulePtr CurLibrary;
//***************************************************************************
// MISC routines
//***************************************************************************
inline CharCodeType calcCharCode (long ch) {
return(charTable[ch]);
}
//***************************************************************************
long isReservedWord (void)
{
long wordLength = strlen(wordString);
if ((wordLength >= MINLEN_RESERVED_WORD) && (wordLength <= MAXLEN_RESERVED_WORD) && reservedWordTable[wordLength])
{
for (ReservedWord* rwPtr = reservedWordTable[wordLength]; rwPtr->string != NULL; rwPtr++)
{
if (strcmp(wordString, rwPtr->string) == 0)
{
curToken = rwPtr->tokenCode;
return(1);
}
}
}
return(0);
}
//***************************************************************************
// INITIALIZATION routines
//***************************************************************************
void getChar();
void initScanner (char* fileName) {
//----------------------------------
// Initialize the character table...
for (long curCh = 0; curCh < 256; curCh++)
charTable[curCh] = CHR_SPECIAL;
for (curCh = '0'; curCh <= '9'; curCh++)
charTable[curCh] = CHR_DIGIT;
for (curCh = 'A'; curCh <= 'Z'; curCh++)
charTable[curCh] = CHR_LETTER;
for (curCh = 'a'; curCh <= 'z'; curCh++)
charTable[curCh] = CHR_LETTER;
charTable['\"'] = CHR_DQUOTE;
charTable[CHAR_EOF] = CHR_EOF;
//---------------------------------------
// Now, let's open the ABL source file...
if (fileName)
{
sourceFile = new File;
if (sourceFile->open(fileName) != NO_ERR)
{
syntaxError(ABL_ERR_SYNTAX_SOURCE_FILE_OPEN);
curToken = TKN_ERROR;
}
sourceBuffer[0] = NULL;
bufferp = sourceBuffer;
getChar();
}
}
//***************************************************************************
void quitScanner (void) {
sourceFile->close();
delete sourceFile;
sourceFile = NULL;
}
//***************************************************************************
// CHARACTER routines
//***************************************************************************
void skipLineComment (void) {
//-------------------------------------------------------------------
// Just blow off the rest of the current source line we've read in...
*bufferp = NULL;
curChar = ' ';
}
//***************************************************************************
void skipBlockComment (void) {
//----------------------------------------------------
// Snag the asterisk, then continue until we encounter
// the closing "*/"...
DumbGetCharOn = true;
getChar();
getChar();
do {
while ((curChar != '*') && (curChar != CHR_EOF) && (curChar != CHAR_EOF))
getChar();
if ((curChar == CHAR_EOF) || (curChar == CHR_EOF)){
syntaxError(ABL_ERR_SYNTAX_UNEXPECTED_EOF);
curToken = TKN_ERROR;
}
getChar();
} while (curChar != '/');
curChar = ' ';
DumbGetCharOn = false;
}
//***************************************************************************
void skipBlanks (void) {
while (curChar == ' ')
getChar();
}
//***************************************************************************
void languageDirective (void) {
DumbGetCharOn = true;
getChar();
char directive[32];
long directiveLength = 0;
while ((curChar != ' ') && (curChar != '\n') && (curChar != '\r') && (directiveLength < 31)) {
directive[directiveLength++] = curChar;
getChar();
}
directive[directiveLength] = NULL;
_strlwr(directive);
if (strcmp(directive, "include") == 0) {
//---------------------
// INCLUDE directive...
getChar();
if (curChar == '"') {
getChar();
char fileName[128];
long fileNameLength = 0;
while ((curChar != '"') && (fileNameLength < 127)) {
fileName[fileNameLength++] = curChar;
getChar();
}
fileName[fileNameLength] = NULL;
//-----------------------------------------------------------------------
// The language directive should be on a line by itself, since everything
// after the directive on this line is ignored...
DumbGetCharOn = false;
//----------------------------------------------------
// Now that we have the file name, let's include it...
long openErr = NO_ERR;
if ((openErr = openSourceFile(fileName)) != NO_ERR) {
syntaxError(ABL_ERR_SYNTAX_SOURCE_FILE_OPEN);
curToken = TKN_ERROR;
}
}
else {
syntaxError(ABL_ERR_SYNTAX_BAD_LANGUAGE_DIRECTIVE_USAGE);
curToken = TKN_ERROR;
}
}
else if (strcmp(directive, "include_") == 0) {
//---------------------
// INCLUDE directive...
getChar();
if (curChar == '"') {
getChar();
char fileName[128];
long fileNameLength = 0;
while ((curChar != '"') && (fileNameLength < 127)) {
fileName[fileNameLength++] = curChar;
getChar();
}
fileName[fileNameLength] = NULL;
//-----------------------------------------------------------------------
// The language directive should be on a line by itself, since everything
// after the directive on this line is ignored...
DumbGetCharOn = false;
//----------------------------------------------------
// Now that we have the file name, let's include it...
long openErr = NO_ERR;
//---------------------------------------
// What's the current module's directory?
char fullPath[255];
long curChar = strlen(SourceFiles[0]);
while ((curChar > -1) && (SourceFiles[0][curChar] != '\\'))
curChar--;
if (curChar == -1)
strcpy(fullPath, fileName);
else {
strcpy(fullPath, SourceFiles[0]);
fullPath[curChar + 1] = NULL;
strcat(fullPath, fileName);
}
if ((openErr = openSourceFile(fullPath)) != NO_ERR) {
syntaxError(ABL_ERR_SYNTAX_SOURCE_FILE_OPEN);
curToken = TKN_ERROR;
}
}
else if (curChar == '<') {
getChar();
char fileName[128];
long fileNameLength = 0;
while ((curChar != '>') && (fileNameLength < 127)) {
fileName[fileNameLength++] = curChar;
getChar();
}
fileName[fileNameLength] = NULL;
//-----------------------------------------------------------------------
// The language directive should be on a line by itself, since everything
// after the directive on this line is ignored...
DumbGetCharOn = false;
//----------------------------------------------------
// Now that we have the file name, let's include it...
long openErr = NO_ERR;
//---------------------------------------
// Ignore the modules directory, since the path should be relative to working directory
if ((openErr = openSourceFile(fileName)) != NO_ERR) {
syntaxError(ABL_ERR_SYNTAX_SOURCE_FILE_OPEN);
curToken = TKN_ERROR;
}
}
else {
syntaxError(ABL_ERR_SYNTAX_BAD_LANGUAGE_DIRECTIVE_USAGE);
curToken = TKN_ERROR;
}
}
else if (strcmp(directive, "assert_on") == 0) {
DumbGetCharOn = false;
curChar = ' ';
AssertEnabled = true;
}
else if (strcmp(directive, "assert_off") == 0) {
DumbGetCharOn = false;
curChar = ' ';
AssertEnabled = false;
}
else if (strcmp(directive, "print_on") == 0) {
DumbGetCharOn = false;
curChar = ' ';
PrintEnabled = true;
}
else if (strcmp(directive, "print_off") == 0) {
DumbGetCharOn = false;
curChar = ' ';
PrintEnabled = false;
}
else if (strcmp(directive, "stringfuncs_on") == 0) {
DumbGetCharOn = false;
curChar = ' ';
StringFunctionsEnabled = true;
}
else if (strcmp(directive, "stringfuncs_off") == 0) {
DumbGetCharOn = false;
curChar = ' ';
StringFunctionsEnabled = false;
}
else if (strcmp(directive, "debug_on") == 0) {
DumbGetCharOn = false;
curChar = ' ';
DebugCodeEnabled = true;
}
else if (strcmp(directive, "debug_off") == 0) {
DumbGetCharOn = false;
curChar = ' ';
DebugCodeEnabled = false;
}
else if (strcmp(directive, "debug_start") == 0) {
bool stillCutting = true;
if (!DebugCodeEnabled) {
long nestedLevel = 1;
getChar();
// getChar();
do {
while ((curChar != '#') && (curChar != CHR_EOF))
getChar();
if (curChar == '#') {
char directive2[32];
long directiveLength = 0;
while ((curChar != ' ') && (curChar != '\n') && (curChar != '\r') && (directiveLength < 31)) {
directive2[directiveLength++] = curChar;
getChar();
}
directive2[directiveLength] = NULL;
_strlwr(directive2);
if (strcmp(directive2, "#debug_start") == 0)
nestedLevel++;
else if (strcmp(directive2, "#debug_end") == 0) {
nestedLevel--;
if (nestedLevel == 0)
stillCutting = false;
}
}
else if (curChar == CHR_EOF) {
syntaxError(ABL_ERR_SYNTAX_UNEXPECTED_EOF);
curToken = TKN_ERROR;
}
else
getChar();
} while (stillCutting);
}
curChar = ' ';
DumbGetCharOn = false;
}
else if (strcmp(directive, "debug_end") == 0) {
curChar = ' ';
DumbGetCharOn = false;
}
else {
syntaxError(ABL_ERR_SYNTAX_UNKNOWN_LANGUAGE_DIRECTIVE);
curToken = TKN_ERROR;
}
}
//***************************************************************************
void getChar (void) {
if (*bufferp == NULL) {
if (!getSourceLine()) {
if (NumOpenFiles > 1) {
closeSourceFile();
return;
}
else {
curChar = CHAR_EOF;
return;
}
}
bufferp = sourceBuffer;
bufferOffset = 0;
}
curChar = *bufferp;
bufferp++;
if (DumbGetCharOn) {
bufferOffset++;
return;
}
//-------------------
// Special Characters
switch (curChar) {
case '\t':
// TAB
bufferOffset += TAB_SIZE - bufferOffset % TAB_SIZE;
curChar = ' ';
break;
case '\n':
case '\r':
// NEWLINE
bufferOffset++;
curChar = ' ';
break;
case '/':
if (*bufferp == '/')
skipLineComment();
else if (*bufferp == '*')
skipBlockComment();
else
bufferOffset++;
break;
case '#':
languageDirective();
break;
default:
bufferOffset++;
}
}
//***************************************************************************
// TOKEN routines
//***************************************************************************
#pragma warning (disable : 4244)
void downShiftWord (void) {
long offset = 'a' - 'A';
char* wp = wordString;
char* tp = tokenString;
long checkLengthWord = strlen(wordString);
long checkLengthToken = strlen(tokenString);
if ((checkLengthWord >= MAXLEN_TOKENSTRING) || (checkLengthToken >= MAXLEN_TOKENSTRING))
ABL_Fatal(-1," Boy did Glenn screw the pooch here!! ");
do {
*wp = (char) ((*tp >= 'A') && (*tp <= 'Z')) ? (*tp + (char)offset) : *tp;
wp++;
tp++;
} while (*tp != NULL);
*wp = NULL;
}
#pragma warning (default: 4244)
//***************************************************************************
void getToken(void) {
skipBlanks();
tokenp = tokenString;
switch (calcCharCode(curChar)) {
case CHR_LETTER:
getWord();
break;
case CHR_DIGIT:
getNumber();
break;
case CHR_DQUOTE:
getString();
break;
case CHR_EOF:
curToken = TKN_EOF;
break;
default:
getSpecial();
break;
}
if (blockFlag)
crunchToken();
}
//***************************************************************************
void getWord (void) {
while ((calcCharCode(curChar) == CHR_LETTER) || (calcCharCode(curChar) == CHR_DIGIT) || (curChar == '_')) {
*tokenp = curChar;
tokenp++;
getChar();
}
*tokenp = NULL;
downShiftWord();
TokenCodeType endToken;
if (parsingFSM)
endToken = TKN_END_FSM;
else
endToken = ((CurLibrary == NULL) ? TKN_END_MODULE : TKN_END_LIBRARY);
if (curChar == '.') {
//-------------------------------------------------------------------
// If we have an "endmodule" string, stop. Otherwise, keep reading...
if (strcmp(wordString, TokenStrings[endToken])) {
*tokenp = curChar;
tokenp++;
getChar();
while ((calcCharCode(curChar) == CHR_LETTER) || (calcCharCode(curChar) == CHR_DIGIT) || (curChar == '_')) {
*tokenp = curChar;
tokenp++;
getChar();
}
*tokenp = NULL;
downShiftWord();
}
}
if (!isReservedWord())
curToken = TKN_IDENTIFIER;
}
//***************************************************************************
void accumulateValue (float* valuePtr, SyntaxErrorType errCode) {
float value = *valuePtr;
//--------------------------------------------
// Make sure the first character is a digit...
if (calcCharCode(curChar) != CHR_DIGIT) {
syntaxError(errCode);
curToken = TKN_ERROR;
return;
}
do {
*tokenp = curChar;
tokenp++;
if (++digitCount <= MAX_DIGIT_COUNT)
value = 10 * value + (curChar - '0');
else
countError = true;
getChar();
} while (calcCharCode(curChar) == CHR_DIGIT);
*valuePtr = value;
}
//***************************************************************************
void getNumber (void) {
long wholeCount = 0;
long decimalOffset = 0;
char exponentSign = '+';
long exponent = 0;
float numberValue = (float)0.0;
float exponentValue = (float)0.0;
digitCount = 0;
countError = false;
curToken = TKN_NONE;
//------------------------------------
// Assume it's an integer, at first...
curLiteral.type = LIT_INTEGER;
accumulateValue(&numberValue, ABL_ERR_SYNTAX_INVALID_NUMBER);
if (curToken == TKN_ERROR)
return;
wholeCount = digitCount;
if (curChar == '.') {
getChar();
curLiteral.type = LIT_REAL;
*tokenp = '.';
tokenp++;
accumulateValue(&numberValue, ABL_ERR_SYNTAX_INVALID_FRACTION);
if (curToken == TKN_ERROR)
return;
decimalOffset = wholeCount - digitCount;
}
if ((curChar == 'E') || (curChar == 'e')) {
curLiteral.type = LIT_REAL;
*tokenp = curChar;
tokenp++;
//-------------------
// Any exponent sign?
if ((curChar == '+') || (curChar == '-')) {
*tokenp = exponentSign = curChar;
tokenp++;
getChar();
}
accumulateValue(&exponentValue, ABL_ERR_SYNTAX_INVALID_EXPONENT);
if (curToken == TKN_ERROR)
return;
if (exponentSign == '-')
exponentValue = -exponentValue;
}
//-----------------
// Too many digits?
if (countError) {
syntaxError(ABL_ERR_SYNTAX_TOO_MANY_DIGITS);
curToken = TKN_ERROR;
return;
}
//------------------------------------------------------------
// Adjust number's value using decimal offset and the exponent
exponent = (long) (exponentValue + ((float) decimalOffset));
if ((exponent + wholeCount < -MAX_EXPONENT) || (exponent + wholeCount > MAX_EXPONENT)) {
syntaxError(ABL_ERR_SYNTAX_REAL_OUT_OF_RANGE);
curToken = TKN_ERROR;
return;
}
if (exponent != 0)
numberValue *= (float) pow(10.0, (double)exponent);
//---------------------------
// Set the literal's value...
if (curLiteral.type == LIT_INTEGER) {
if (((long)numberValue < -MAX_INTEGER) || ((long)numberValue > MAX_INTEGER)) {
syntaxError(ABL_ERR_SYNTAX_INTEGER_OUT_OF_RANGE);
curToken = TKN_ERROR;
return;
}
curLiteral.value.integer = (long)numberValue;
}
else
curLiteral.value.real = numberValue;
*tokenp = NULL;
curToken = TKN_NUMBER;
}
//***************************************************************************
//---------------------------------------------------
// NOTE: Currently, ABL does not have STRING types...
void getString (void) {
char* stringPtr = curLiteral.value.string;
*tokenp = '\"';
getChar();
while (curChar != CHAR_EOF) {
if (curChar == '\"')
break;
*tokenp = curChar;
tokenp++;
*stringPtr = curChar;
stringPtr++;
getChar();
}
curChar = ' ';
*tokenp = NULL;
*stringPtr = NULL;
curToken = TKN_STRING;
curLiteral.type = LIT_STRING;
}
//***************************************************************************
void getSpecial (void) {
*tokenp = curChar;
tokenp++;
switch (curChar) {
// case '^':
// curToken = TKN_UPARROW;
// getChar();
// break;
case '*':
curToken = TKN_STAR;
getChar();
break;
case '(':
curToken = TKN_LPAREN;
getChar();
break;
case ')':
curToken = TKN_RPAREN;
getChar();
break;
case '-':
curToken = TKN_MINUS;
getChar();
break;
case '+':
curToken = TKN_PLUS;
getChar();
break;
case '[':
curToken = TKN_LBRACKET;
getChar();
break;
case ']':
curToken = TKN_RBRACKET;
getChar();
break;
case ';':
curToken = TKN_SEMICOLON;
getChar();
break;
case '@':
curToken = TKN_REF;
getChar();
break;
case '#':
curToken = TKN_POUND;
getChar();
break;
// NOTE: For now, let's use the BEGIN and END keywords instead of braces.
// If popular demand is to get rid of the begin/end keywords and switch
// to braces, we can do so...
// case '{':
// curToken = TKN_BEGIN;
// getChar();
// break;
// case '}':
// curToken = TKN_END;
// getChar();
// break;
case ',':
curToken = TKN_COMMA;
getChar();
break;
case '/':
//-----------------------------------------------
// In theory :), we shouldn't have to worry about
// comments here, as getChar syphons them out...
curToken = TKN_FSLASH;
getChar();
break;
case '=':
getChar();
if (curChar == '=') {
*tokenp = '=';
tokenp++;
curToken = TKN_EQUALEQUAL;
getChar();
}
else
curToken = TKN_EQUAL;
break;
case '<':
getChar();
if (curChar == '=') {
*tokenp = '=';
tokenp++;
curToken = TKN_LE;
getChar();
}
else if (curChar == '>') {
*tokenp = '>';
tokenp++;
curToken = TKN_NE;
getChar();
}
else
curToken = TKN_LT;
break;
case '>':
getChar();
if (curChar == '=') {
*tokenp = '=';
tokenp++;
curToken = TKN_GE;
getChar();
}
else
curToken = TKN_GT;
break;
case '.':
curToken = TKN_PERIOD;
getChar();
break;
case ':':
curToken = TKN_COLON;
getChar();
break;
default:
curToken = TKN_ERROR;
getChar();
break;
}
*tokenp = NULL;
}
//***************************************************************************
// TOKEN TESTER routines
//***************************************************************************
bool tokenIn (TokenCodeType* tokenList) {
if (!tokenList)
return(false);
for (TokenCodeType* tp = &tokenList[0]; *tp; tp++)
if (curToken == *tp)
return(true);
return(false);
}
//***************************************************************************
void synchronize (TokenCodeType* tokenList1,
TokenCodeType* tokenList2,
TokenCodeType* tokenList3) {
bool badLists = (!tokenIn(tokenList1) && !tokenIn(tokenList2) && !tokenIn(tokenList3));
if (badLists) {
syntaxError((curToken == TKN_EOF) ? ABL_ERR_SYNTAX_UNEXPECTED_EOF : ABL_ERR_SYNTAX_UNEXPECTED_TOKEN);
//----------------------------------------------
// Now, we need to re-sync by skipping tokens...
while (!tokenIn(tokenList1) &&
!tokenIn(tokenList2) &&
!tokenIn(tokenList3) &&
(curToken != TKN_EOF))
getToken();
}
}
//***************************************************************************
// SOURCE FILE routines
//***************************************************************************
bool getSourceLine (void) {
if (!sourceFile->eof())
{
long numChars = sourceFile->readLineEx((MemoryPtr)sourceBuffer, MAXLEN_SOURCELINE);
if (numChars == 0)
return(false);
lineNumber++;
if (printFlag)
{
char printBuffer[MAXLEN_SOURCELINE + 9];
sprintf(printBuffer, "%4d %d: %s", lineNumber, level, sourceBuffer);
printLine(printBuffer);
}
return(true);
}
else
return(false);
}
//---------------------------------------------------------------------------
long openSourceFile (char* sourceFileName) {
//---------------------------------------
// Now, let's open the ABL source file...
if (!sourceFileName)
return(-1);
if (NumOpenFiles == MAX_INCLUDE_DEPTH)
return(-2);
if (NumSourceFiles == MAX_SOURCE_FILES)
return(-3);
FilePtr sFile = NULL;
sFile = new File;
sFile->open(sourceFileName);
strcpy(SourceFiles[NumSourceFiles], sourceFileName);
FileNumber = NumSourceFiles++;
sourceFile = sFile;
strcpy(openFiles[NumOpenFiles].fileName, sourceFileName);
openFiles[NumOpenFiles].filePtr = sFile;
openFiles[NumOpenFiles].fileNumber = (unsigned char) FileNumber;
openFiles[NumOpenFiles].lineNumber = 0;
if (NumOpenFiles > 0)
openFiles[NumOpenFiles - 1].lineNumber = lineNumber;
NumOpenFiles++;
lineNumber = 0;
sourceBuffer[0] = NULL;
bufferp = sourceBuffer;
getChar();
return(NO_ERR);
}
//---------------------------------------------------------------------------
long closeSourceFile (void) {
if (NumOpenFiles == 0)
return(-1);
sourceFile->close();
delete sourceFile;
sourceFile = NULL;
openFiles[NumOpenFiles].filePtr = NULL;
NumOpenFiles--;
if (NumOpenFiles > 0) {
sourceFile = openFiles[NumOpenFiles - 1].filePtr;
FileNumber = openFiles[NumOpenFiles - 1].fileNumber;
lineNumber = openFiles[NumOpenFiles - 1].lineNumber;
}
return(NO_ERR);
}
//***************************************************************************
// PRINTOUT routines
//***************************************************************************
void printLine (char* line) {
if (++lineCount > MAX_LINES_PER_PAGE) {
printPageHeader();
lineCount = 1;
}
char* saveChPtr = NULL;
char saveCh = ' ';
if (strlen(line) > MAXLEN_PRINTLINE) {
saveCh = line[MAXLEN_PRINTLINE];
saveChPtr = &line[MAXLEN_PRINTLINE];
*saveChPtr = NULL;
}
printf("%s", line);
if (saveChPtr)
*saveChPtr = saveCh;
}
//***************************************************************************
void initPageHeader (char* fileName) {
//--------------------------
// Save the source file name
strncpy(sourceName, fileName, MAXLEN_FILENAME - 1);
//-------------------------------
// Save the current time and date
time_t timer;
time(&timer);
strcpy(date, asctime(localtime(&timer)));
}
//***************************************************************************
void printPageHeader (void) {
//putchar(CHAR_FORMFEED);
printf("Page %d %s %s\n\n", ++pageNumber, sourceName, date);
}
//***************************************************************************
}