Files
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

924 lines
26 KiB
C++

//***************************************************************************
//
// ABLDECL.CPP
//
//***************************************************************************
#include "MW4Headers.hpp"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef ABLHEAP_H
#include "ablheap.h"
#endif
#ifndef ABLGEN_H
#include "ablgen.h"
#endif
#ifndef ABLERR_H
#include "ablerr.h"
#endif
#ifndef ABLSCAN_H
#include "ablscan.h"
#endif
#ifndef ABLSYMT_H
#include "ablsymt.h"
#endif
#ifndef ABLPARSE_H
#include "ablparse.h"
#endif
#ifndef ABLEXEC_H
#include "ablexec.h"
#endif
#ifdef USE_IFACE
#ifndef IFACE_H
#include <iface.h>
#endif
#endif
namespace ABL
{
//***************************************************************************
extern TokenCodeType curToken;
extern char wordString[];
extern Literal curLiteral;
extern SymTableNodePtr SymTableDisplay[];
extern long level;
extern TypePtr IntegerTypePtr;
extern TypePtr CharTypePtr;
extern TypePtr RealTypePtr;
extern TypePtr BooleanTypePtr;
extern TokenCodeType declarationStartList[];
extern TokenCodeType statementStartList[];
extern UserHeapPtr AblSymTableHeap;
extern UserHeapPtr AblStackHeap;
extern long eternalOffset;
extern long NumStaticVariables;
extern long MaxStaticVariables;
extern long* StaticVariablesSizes;
extern long* EternalVariablesSizes;
extern ABLModulePtr CurLibrary;
//***************************************************************************
TokenCodeType followRoutineList[] = {
TKN_SEMICOLON,
TKN_EOF,
TKN_NONE
};
TokenCodeType followDeclarationList[] = {
TKN_SEMICOLON,
TKN_IDENTIFIER,
TKN_EOF,
TKN_NONE
};
TokenCodeType followVariablesList[] = {
TKN_SEMICOLON,
TKN_IDENTIFIER,
TKN_EOF,
TKN_NONE
};
//-------------------------------------
// If we support record/struct types...
#if 0
TokenCodeType followFieldsList[] = {
TKN_SEMICOLON,
TKN_END,
TKN_IDENTIFIER,
TKN_EOF,
TKN_NONE
};
#endif
TokenCodeType followVarBlockList[] = {
TKN_FUNCTION,
TKN_CODE,
TKN_EOF,
TKN_NONE
};
TokenCodeType followDimensionList[] = {
TKN_COMMA,
TKN_RBRACKET,
//TKN_OF,
//TKN_SEMICOLON,
TKN_EOF,
TKN_NONE
};
TokenCodeType indexTypeStartList[] = {
TKN_IDENTIFIER,
TKN_NUMBER,
//TKN_STAR,
//TKN_STRING,
//TKN_LPAREN,
//TKN_MINUS,
//TKN_PLUS,
TKN_NONE
};
TokenCodeType followIndexesList[] = {
TKN_OF,
TKN_IDENTIFIER,
TKN_LPAREN,
//TKN_RECORD,
TKN_PLUS,
TKN_MINUS,
TKN_NUMBER,
//TKN_STRING,
TKN_SEMICOLON,
TKN_EOF,
TKN_NONE
};
//***************************************************************************
// MISC. routines
//***************************************************************************
/*inline*/
void ifTokenGet(TokenCodeType tokenCode)
{
if (curToken == tokenCode)
getToken();
}
//***************************************************************************
/*inline*/ void ifTokenGetElseError (TokenCodeType tokenCode, SyntaxErrorType errorCode)
{
if (curToken == tokenCode)
getToken();
else
syntaxError(errorCode);
}
//***************************************************************************
// DECLARATIONS routines
//***************************************************************************
void declarations (SymTableNodePtr routineIdPtr, long allowFunctions, long allowStates)
{
if (curToken == TKN_CONST)
{
getToken();
constDefinitions();
}
if (curToken == TKN_TYPE)
{
getToken();
typeDefinitions();
}
if (curToken == TKN_VAR)
{
getToken();
varDeclarations(routineIdPtr);
}
//---------------------------------------------------
// Loop to process all of the function definitions...
if (allowFunctions)
while (curToken == TKN_FUNCTION)
{
routine();
//---------------------
// Error synchronize...
synchronize(followRoutineList, declarationStartList, statementStartList);
if (curToken == TKN_SEMICOLON)
getToken();
else if (tokenIn(declarationStartList) || tokenIn(statementStartList))
syntaxError(ABL_ERR_SYNTAX_MISSING_SEMICOLON);
}
else if (curToken == TKN_FUNCTION)
syntaxError(ABL_ERR_SYNTAX_NO_FUNCTION_NESTING);
//---------------------------------------------------
// Loop to process all of the state definitions...
if (allowStates)
while (curToken == TKN_STATE)
{
state();
//---------------------
// Error synchronize...
synchronize(followRoutineList, declarationStartList, statementStartList);
if (curToken == TKN_SEMICOLON)
getToken();
else if (tokenIn(declarationStartList) || tokenIn(statementStartList))
syntaxError(ABL_ERR_SYNTAX_MISSING_SEMICOLON);
}
else if (curToken == TKN_STATE)
syntaxError(ABL_ERR_SYNTAX_NO_STATE_NESTING);
}
//***************************************************************************
// CONST routines
//***************************************************************************
void constDefinitions (void)
{
//-------------------------------------------------------
// Loop to process definitions separated by semicolons...
while (curToken == TKN_IDENTIFIER)
{
SymTableNodePtr constantIdPtr;
searchAndEnterLocalSymTable(constantIdPtr);
constantIdPtr->defn.key = DFN_CONST;
constantIdPtr->library = CurLibrary;
getToken();
ifTokenGetElseError(TKN_EQUAL, ABL_ERR_SYNTAX_MISSING_EQUAL);
doConst(constantIdPtr);
analyzeConstDefn(constantIdPtr);
//---------------------------------
// Error synchronize: should be a ;
synchronize(followDeclarationList, declarationStartList, statementStartList);
if (curToken == TKN_SEMICOLON)
getToken();
else if (tokenIn(declarationStartList) || tokenIn(statementStartList))
syntaxError(ABL_ERR_SYNTAX_MISSING_SEMICOLON);
}
}
//***************************************************************************
TypePtr makeStringType (long length)
{
TypePtr stringTypePtr = createType();
if (!stringTypePtr)
ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc stringType ");
stringTypePtr->form = FRM_ARRAY;
stringTypePtr->size = length;
stringTypePtr->typeIdPtr = NULL;
stringTypePtr->info.array.indexTypePtr = IntegerTypePtr;
stringTypePtr->info.array.elementTypePtr = CharTypePtr;
stringTypePtr->info.array.elementCount = length + 1;
return(stringTypePtr);
}
//***************************************************************************
void doConst (SymTableNodePtr constantIdPtr)
{
TokenCodeType sign = TKN_PLUS;
bool sawSign = false;
if ((curToken == TKN_PLUS) || (curToken == TKN_MINUS))
{
sign = curToken;
sawSign = true;
getToken();
}
//----------------------------------
// Numeric constant: real or integer
if (curToken == TKN_NUMBER)
{
if (curLiteral.type == LIT_INTEGER)
{
if (sign == TKN_PLUS)
constantIdPtr->defn.info.constant.value.integer = curLiteral.value.integer;
else
constantIdPtr->defn.info.constant.value.integer = -(curLiteral.value.integer);
constantIdPtr->typePtr = setType(IntegerTypePtr);
}
else
{
if (sign == TKN_PLUS)
constantIdPtr->defn.info.constant.value.real = curLiteral.value.real;
else
constantIdPtr->defn.info.constant.value.real = -(curLiteral.value.real);
constantIdPtr->typePtr = setType(RealTypePtr);
}
}
else if (curToken == TKN_IDENTIFIER)
{
SymTableNodePtr idPtr = NULL;
searchAllSymTables(idPtr);
if (!idPtr)
syntaxError(ABL_ERR_SYNTAX_UNDEFINED_IDENTIFIER);
else if (idPtr->defn.key != DFN_CONST)
syntaxError(ABL_ERR_SYNTAX_NOT_A_CONSTANT_IDENTIFIER);
else if (idPtr->typePtr == IntegerTypePtr)
{
if (sign == TKN_PLUS)
constantIdPtr->defn.info.constant.value.integer = idPtr->defn.info.constant.value.integer;
else
constantIdPtr->defn.info.constant.value.integer = -(idPtr->defn.info.constant.value.integer);
constantIdPtr->typePtr = setType(IntegerTypePtr);
}
else if (idPtr->typePtr == CharTypePtr)
{
if (sawSign)
syntaxError(ABL_ERR_SYNTAX_INVALID_CONSTANT);
//if (sign == TKN_PLUS)
constantIdPtr->defn.info.constant.value.character = idPtr->defn.info.constant.value.character;
//else
// constantIdPtr->defn.info.constant.value.character = -(idPtr->defn.info.constant.value.character);
constantIdPtr->typePtr = setType(CharTypePtr);
}
else if (idPtr->typePtr == RealTypePtr)
{
if (sign == TKN_PLUS)
constantIdPtr->defn.info.constant.value.real = idPtr->defn.info.constant.value.real;
else
constantIdPtr->defn.info.constant.value.real = -(idPtr->defn.info.constant.value.real);
constantIdPtr->typePtr = setType(RealTypePtr);
}
else if (((Type*)(idPtr->typePtr))->form == FRM_ENUM)
{
if (sawSign)
syntaxError(ABL_ERR_SYNTAX_INVALID_CONSTANT);
constantIdPtr->defn.info.constant.value.integer = idPtr->defn.info.constant.value.integer;
constantIdPtr->typePtr = setType(idPtr->typePtr);
}
else if (((TypePtr)(idPtr->typePtr))->form == FRM_ARRAY)
{
if (sawSign)
syntaxError(ABL_ERR_SYNTAX_INVALID_CONSTANT);
constantIdPtr->defn.info.constant.value.stringPtr = idPtr->defn.info.constant.value.stringPtr;
constantIdPtr->typePtr = setType(idPtr->typePtr);
}
}
else if (curToken == TKN_STRING)
{
if (sawSign)
syntaxError(ABL_ERR_SYNTAX_INVALID_CONSTANT);
if (strlen(curLiteral.value.string) == 1)
{
constantIdPtr->defn.info.constant.value.character = curLiteral.value.string[0];
constantIdPtr->typePtr = setType(CharTypePtr);
}
else
{
long length = strlen(curLiteral.value.string);
constantIdPtr->defn.info.constant.value.stringPtr = (char*)AblSymTableHeap->Malloc(length + 1);
if (!constantIdPtr->defn.info.constant.value.stringPtr)
ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc array string constant ");
strcpy(constantIdPtr->defn.info.constant.value.stringPtr, curLiteral.value.string);
constantIdPtr->typePtr = makeStringType(length);
}
}
else
{
constantIdPtr->typePtr = NULL;
syntaxError(ABL_ERR_SYNTAX_INVALID_CONSTANT);
}
getToken();
}
//***************************************************************************
// TYPE routines
//***************************************************************************
//---------------------------------------------------------------------------
// Need to implement type routines if we allow user-defined types, and/or the
// PASCAL style array types (otherwise, arrays should be implemented in the
// var routines...
void typeDefinitions (void)
{
while (curToken == TKN_IDENTIFIER)
{
SymTableNodePtr typeIdPtr;
searchAndEnterLocalSymTable(typeIdPtr);
typeIdPtr->defn.key = DFN_TYPE;
typeIdPtr->library = CurLibrary;
getToken();
ifTokenGetElseError(TKN_EQUAL, ABL_ERR_SYNTAX_MISSING_EQUAL);
//----------------------------------
// Process the type specification...
typeIdPtr->typePtr = doType();
if (typeIdPtr->typePtr->typeIdPtr == NULL)
typeIdPtr->typePtr->typeIdPtr = typeIdPtr;
analyzeTypeDefn(typeIdPtr);
//---------------
// Error synch...
synchronize(followDeclarationList, declarationStartList, statementStartList);
if (curToken == TKN_SEMICOLON)
getToken();
else if (tokenIn(declarationStartList) || tokenIn(statementStartList))
syntaxError(ABL_ERR_SYNTAX_MISSING_SEMICOLON);
}
}
//***************************************************************************
TypePtr doType (void)
{
switch (curToken)
{
case TKN_IDENTIFIER: {
SymTableNodePtr idPtr;
searchAllSymTables(idPtr);
if (!idPtr)
{
syntaxError(ABL_ERR_SYNTAX_UNDEFINED_IDENTIFIER);
return(NULL);
}
else if (idPtr->defn.key == DFN_TYPE)
{
//----------------------------------------------------------
// NOTE: Array types should be parsed in this case if a left
// bracket follows the type identifier.
TypePtr elementType = setType(identifierType(idPtr));
if (curToken == TKN_LBRACKET)
{
//--------------
// Array type...
TypePtr typePtr = createType();
if (!typePtr)
ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc array type ");
TypePtr elementTypePtr = typePtr;
//bool openArray = false;
do
{
getToken();
if (tokenIn(indexTypeStartList))
{
elementTypePtr->form = FRM_ARRAY;
elementTypePtr->size = 0;
elementTypePtr->typeIdPtr = NULL;
//----------------------------------------------
// All array indices must be integer, for now...
elementTypePtr->info.array.indexTypePtr = setType(IntegerTypePtr);
//------------------------
// Read the index count...
switch (curToken)
{
case TKN_NUMBER:
if (curLiteral.type == LIT_INTEGER)
elementTypePtr->info.array.elementCount = curLiteral.value.integer;
else
{
elementTypePtr->form = FRM_NONE;
elementTypePtr->size = 0;
elementTypePtr->typeIdPtr = NULL;
elementTypePtr->info.array.indexTypePtr = NULL;
syntaxError(ABL_ERR_SYNTAX_INVALID_INDEX_TYPE);
}
getToken();
break;
case TKN_IDENTIFIER: {
SymTableNodePtr idPtr;
searchAllSymTables(idPtr);
if (idPtr == NULL)
syntaxError(ABL_ERR_SYNTAX_UNDEFINED_IDENTIFIER);
else if (idPtr->defn.key == DFN_CONST)
{
if (idPtr->typePtr == IntegerTypePtr)
elementTypePtr->info.array.elementCount = idPtr->defn.info.constant.value.integer;
else
{
elementTypePtr->form = FRM_NONE;
elementTypePtr->size = 0;
elementTypePtr->typeIdPtr = NULL;
elementTypePtr->info.array.indexTypePtr = NULL;
syntaxError(ABL_ERR_SYNTAX_INVALID_INDEX_TYPE);
}
}
else
{
elementTypePtr->form = FRM_NONE;
elementTypePtr->size = 0;
elementTypePtr->typeIdPtr = NULL;
elementTypePtr->info.array.indexTypePtr = NULL;
syntaxError(ABL_ERR_SYNTAX_INVALID_INDEX_TYPE);
}
getToken();
}
break;
#if 0
case TKN_STAR: {
openArray = true;
elementTypePtr->info.array.elementCount = -1;
getToken();
if (curToken != TKN_RBRACKET)
{
elementTypePtr->form = FRM_NONE;
elementTypePtr->size = 0;
elementTypePtr->typeIdPtr = NULL;
elementTypePtr->info.array.indexTypePtr = NULL;
syntaxError(ABL_ERR_SYNTAX_MISSING_RBRACKET);
}
}
break;
#endif
default:
elementTypePtr->form = FRM_NONE;
elementTypePtr->size = 0;
elementTypePtr->typeIdPtr = NULL;
elementTypePtr->info.array.indexTypePtr = NULL;
syntaxError(ABL_ERR_SYNTAX_INVALID_INDEX_TYPE);
getToken();
}
}
else
{
elementTypePtr->form = FRM_NONE;
elementTypePtr->size = 0;
elementTypePtr->typeIdPtr = NULL;
elementTypePtr->info.array.indexTypePtr = NULL;
syntaxError(ABL_ERR_SYNTAX_INVALID_INDEX_TYPE);
getToken();
}
synchronize(followDimensionList, NULL, NULL);
//--------------------------------
// Create an array element type...
if (curToken == TKN_COMMA)
{
elementTypePtr = elementTypePtr->info.array.elementTypePtr = createType();
if (!elementTypePtr)
ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc array element Type ");
}
} while (curToken == TKN_COMMA);
ifTokenGetElseError(TKN_RBRACKET, ABL_ERR_SYNTAX_MISSING_RBRACKET);
elementTypePtr->info.array.elementTypePtr = elementType;
typePtr->size = arraySize(typePtr);
elementType = typePtr;
}
return(elementType);
}
//---------------------
// NO SUBRANGES, YET...
//else if (idPtr->defn.key == DFN_CONST)
// return(subrangeType(idPtr));
else
{
syntaxError(ABL_ERR_SYNTAX_NOT_A_TYPE_IDENTIFIER);
return(NULL);
}
}
break;
case TKN_LPAREN:
return(enumerationType());
//case TKN_RECORD:
// STOP(("666???"));
//return(recordType());
case TKN_PLUS:
case TKN_MINUS:
case TKN_NUMBER:
case TKN_STRING:
STOP(("666???"));
//return(subrangeType(NULL));
default:
syntaxError(ABL_ERR_SYNTAX_INVALID_TYPE);
return(NULL);
}
}
//***************************************************************************
TypePtr identifierType (SymTableNodePtr idPtr)
{
TypePtr typePtr = (TypePtr)idPtr->typePtr;
getToken();
return(typePtr);
}
//***************************************************************************
TypePtr enumerationType (void)
{
SymTableNodePtr constantIdPtr = NULL;
SymTableNodePtr lastIdPtr = NULL;
TypePtr typePtr = createType();
if (!typePtr)
ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc enumeration type ");
long constantValue = -1;
typePtr->form = FRM_ENUM;
typePtr->size = sizeof(long);
typePtr->typeIdPtr = NULL;
getToken();
//------------------------------------------------------------
// Process list of identifiers in this new enumeration type...
while (curToken == TKN_IDENTIFIER)
{
searchAndEnterLocalSymTable(constantIdPtr);
constantIdPtr->defn.key = DFN_CONST;
constantIdPtr->defn.info.constant.value.integer = ++constantValue;
constantIdPtr->typePtr = typePtr;
constantIdPtr->library = CurLibrary;
if (lastIdPtr == NULL)
typePtr->info.enumeration.constIdPtr = lastIdPtr = constantIdPtr;
else
{
lastIdPtr->next = constantIdPtr;
lastIdPtr = constantIdPtr;
}
getToken();
ifTokenGet(TKN_COMMA);
}
ifTokenGetElseError(TKN_RPAREN, ABL_ERR_SYNTAX_MISSING_RPAREN);
typePtr->info.enumeration.max = constantValue;
return(typePtr);
}
//***************************************************************************
TypePtr subrangeType (void)
{
// NOT IMPLEMENTED...
return(NULL);
}
//***************************************************************************
long arraySize (TypePtr typePtr)
{
if (typePtr->info.array.elementTypePtr->size == 0)
typePtr->info.array.elementTypePtr->size = arraySize(typePtr->info.array.elementTypePtr);
if (typePtr->info.array.elementCount == -1)
{
//--------------------------------------------------------------
// Open array, so just return the size of its element. Remember,
// open arrays must be open at the end...
typePtr->size = typePtr->info.array.elementTypePtr->size;
}
else
typePtr->size = typePtr->info.array.elementCount * typePtr->info.array.elementTypePtr->size;
return(typePtr->size);
}
//***************************************************************************
// VAR routines
//***************************************************************************
void varDeclarations (SymTableNodePtr routineIdPtr)
{
varOrFieldDeclarations(routineIdPtr,
STACK_FRAME_HEADER_SIZE + routineIdPtr->defn.info.routine.paramCount);
}
//***************************************************************************
void varOrFieldDeclarations (SymTableNodePtr routineIdPtr, long offset)
{
bool varFlag = (routineIdPtr != NULL);
SymTableNodePtr idPtr = NULL;
SymTableNodePtr firstIdPtr = NULL;
SymTableNodePtr lastIdPtr = NULL;
SymTableNodePtr prevLastIdPtr = NULL;
long totalSize = 0;
while ((curToken == TKN_IDENTIFIER) || (curToken == TKN_ETERNAL) || (curToken == TKN_STATIC))
{
VariableType varType = VAR_TYPE_NORMAL;
if ((curToken == TKN_ETERNAL) || (curToken == TKN_STATIC))
{
if (curToken == TKN_ETERNAL)
varType = VAR_TYPE_ETERNAL;
else
varType = VAR_TYPE_STATIC;
getToken();
if (curToken != TKN_IDENTIFIER)
syntaxError(ABL_ERR_SYNTAX_MISSING_IDENTIFIER);
}
firstIdPtr = NULL;
//------------------------------
// Process the variable type...
TypePtr typePtr = doType();
//------------------------------------------------------------------
// Since we haven't really assigned it here, decrement its
// numInstances. Every variable in this list will set it properly...
typePtr->numInstances--;
long size = typePtr->size;
//-------------------------------------------------------
// Now that we've read the type, read in the variable (or
// possibly list of variables) declared of this type.
// Loop to process every variable (and field, if records
// are being implemented:) in sublist...
while (curToken == TKN_IDENTIFIER)
{
if (varFlag)
{
//---------------------------------------------
// We're working with a variable declaration...
if (varType == VAR_TYPE_ETERNAL)
{
long curLevel = level;
level = 0;
searchAndEnterThisTable (idPtr, SymTableDisplay[0]);
level = curLevel;
}
else
searchAndEnterLocalSymTable(idPtr);
idPtr->library = CurLibrary;
idPtr->defn.key = DFN_VAR;
}
else
{
syntaxError(ABL_ERR_SYNTAX_NO_RECORD_TYPES);
#if 0
//-------------------------------------------------
// We're dealing with a record field declaration...
searchAndEnterThisSymTable(idPtr, recordType->info.record.fieldSymTable);
idPtr->defn.key = DFN_FIELD;
#endif
}
idPtr->labelIndex = 0;
//------------------------------------------
// Now, link Id's together into a sublist...
if (!firstIdPtr)
{
firstIdPtr = lastIdPtr = idPtr;
if (varFlag && (varType != VAR_TYPE_ETERNAL) && (routineIdPtr->defn.info.routine.locals == NULL))
routineIdPtr->defn.info.routine.locals = idPtr;
}
else
{
lastIdPtr->next = idPtr;
lastIdPtr = idPtr;
}
getToken();
ifTokenGet(TKN_COMMA);
}
//--------------------------------------------------------------------------
// Assign the offset and the type to all variable or field Ids in sublist...
for (idPtr = firstIdPtr; idPtr != NULL; idPtr = idPtr->next)
{
idPtr->typePtr = setType(typePtr);
if (varFlag)
{
idPtr->defn.info.data.varType = varType;
switch (varType)
{
case VAR_TYPE_NORMAL:
totalSize += size;
idPtr->defn.info.data.offset = offset++;
break;
case VAR_TYPE_ETERNAL: {
idPtr->defn.info.data.offset = eternalOffset;
//-----------------------------------
// Initialize the variable to zero...
StackItemPtr dataPtr = (StackItemPtr)stack + eternalOffset;
if (typePtr->form == FRM_ARRAY)
{
dataPtr->address = (Address)AblStackHeap->Malloc((size_t)size);
if (!dataPtr->address)
ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc eternal array ");
memset(dataPtr->address, 0, size);
//NEW
EternalVariablesSizes[eternalOffset] = size;
}
else
{
dataPtr->integer = 0;
//NEW
EternalVariablesSizes[eternalOffset] = 0;
}
eternalOffset++;
}
break;
case VAR_TYPE_STATIC: {
if (NumStaticVariables == MaxStaticVariables)
syntaxError(ABL_ERR_SYNTAX_TOO_MANY_STATIC_VARS);
idPtr->defn.info.data.offset = NumStaticVariables;
// StackItemPtr dataPtr = (StackItemPtr)staticData + NumStaticVariables;
if (typePtr->form == FRM_ARRAY)
{
// dataPtr = (char*)AblStackHeap->malloc((size_t)size);
// memset(dataPtr, 0, size);
StaticVariablesSizes[NumStaticVariables] = size;
}
else
{
// *dataPtr = 0;
StaticVariablesSizes[NumStaticVariables] = 0;
}
NumStaticVariables++;
}
break;
}
analyzeVarDecl(idPtr);
}
else
{
//----------------
// record field...
idPtr->defn.info.data.varType = VAR_TYPE_NORMAL;
idPtr->defn.info.data.offset = offset;
offset += size;
}
}
//--------------------------------------------------
// Now, link this sublist to the previous sublist...
if (varType != VAR_TYPE_ETERNAL)
{
if (prevLastIdPtr != NULL)
prevLastIdPtr->next = firstIdPtr;
prevLastIdPtr = lastIdPtr;
}
//---------------------
// Error synchronize...
if (varFlag)
synchronize(followVariablesList, declarationStartList, statementStartList);
//------------------------------------------------------------------
// NOTE: When records are implemented, the following should be in...
//else
// synchronize(followFieldsList, declarationStartList, statementStartList);
if (curToken == TKN_SEMICOLON)
getToken();
else if (varFlag && (tokenIn(declarationStartList) || tokenIn(statementStartList)))
syntaxError(ABL_ERR_SYNTAX_MISSING_SEMICOLON);
}
synchronize(followVarBlockList, NULL, NULL);
if (varFlag)
{
//----------------------------------------------------------------
// If the following error occurs too frequently, simply make the
// totalLocalSize field an unsigned long instead, and dramatically
// increase the totalSize limit here...
if (totalSize > 32000)
syntaxError(ABL_ERR_SYNTAX_TOO_MANY_LOCAL_VARIABLES);
routineIdPtr->defn.info.routine.totalLocalSize = (unsigned short) totalSize;
}
// NOT CURRENTLY SUPPORTING RECORDS...
//else
// recordType->size = offset;
}
//***************************************************************************
}