Add script/function arrays to ACC

- Script arrays are semantically identical to map arrays: They have fixed
  sizes and can be multidimensional. They can also be initialized, although
  this is just syntactic sugar. e.g.
    int init_array[2] = { 10, 20 }
  produces code identical to:
    int init_array[2];
    init_array[0] = 10;
    init_array[1] = 20;
  Script arrays are also implicitly initialized to 0, just like any other
  variable in ACS.
- Unlike map arrays, they only exist for the life of the script, and each
  script gets its own copy of the array.
- Script arrays exists in a separate space from script variables. I did
  not repeat the bullshittery of map arrays here. (I still have no idea what I
  was thinking when I designed them that way.)
- Each script and function that uses local arrays is recorded with a new
  chunk: SARY for scripts and FARY for functions. The first two bytes are the
  script/function number, and the rest of the chunk consists of four-byte
  integers describing the size (in ints) of each array used by that
  script/function. To determine how many arrays a script/function uses,
  take the chunk length, subtract two, and divide by four.
This commit is contained in:
Randy Heit 2014-07-24 14:41:39 -05:00
parent bede8930a8
commit ac678ff7b8
8 changed files with 371 additions and 97 deletions

View file

@ -56,6 +56,8 @@
#define MAX_IMPORTS 256
#define MAX_SCRIPT_ARRAYS 255
// Max number of include paths the user can specify
// This includes the "working directory"!
#define MAX_INCLUDE_PATHS 16

View file

@ -80,6 +80,8 @@ static struct
{ ERR_TOO_MANY_MAP_VARS, "Too many map variables." },
{ ERR_TOO_MANY_SCRIPT_VARS, "Too many script variables." },
{ ERR_TOO_MANY_FUNCTION_VARS, "Too many function variables." },
{ ERR_TOO_MANY_SCRIPT_ARRAYS, "Too many script arrays." },
{ ERR_TOO_MANY_FUNCTION_ARRAYS, "Too many function arrays." },
{ ERR_MISSING_WVAR_INDEX, "Missing index in world variable declaration." },
{ ERR_MISSING_GVAR_INDEX, "Missing index in global variable declaration." },
{ ERR_BAD_WVAR_INDEX, "World variable index out of range." },

View file

@ -60,6 +60,8 @@ typedef enum
ERR_STRING_LIT_NOT_FOUND,
ERR_TOO_MANY_SCRIPT_VARS,
ERR_TOO_MANY_FUNCTION_VARS,
ERR_TOO_MANY_SCRIPT_ARRAYS,
ERR_TOO_MANY_FUNCTION_ARRAYS,
ERR_INVALID_DECLARATOR,
ERR_BAD_LSPEC_ARG_COUNT,
ERR_BAD_ARG_COUNT,

358
parse.c
View file

@ -143,8 +143,11 @@ static pcd_t TokenToPCD(tokenType_t token);
static pcd_t GetPushVarPCD(symbolType_t symType);
static pcd_t GetIncDecPCD(tokenType_t token, symbolType_t symbol);
static int EvalConstExpression(void);
static void ParseArrayDims(int *size, int *ndim, int dims[MAX_ARRAY_DIMS]);
static void SymToArray(int symtype, symbolNode_t *sym, int index, int ndim, int size, int dims[MAX_ARRAY_DIMS]);
static void ParseArrayIndices(symbolNode_t *sym, int requiredIndices);
static void InitializeArray(symbolNode_t *sym, int dims[MAX_ARRAY_DIMS], int size);
static void InitializeScriptArray(symbolNode_t *sym, int dims[MAX_ARRAY_DIMS], int size);
static symbolNode_t *DemandSymbol(char *name);
static symbolNode_t *SpeculateSymbol(char *name, boolean hasReturn);
static symbolNode_t *SpeculateFunction(const char *name, boolean hasReturn);
@ -171,6 +174,8 @@ boolean pa_ConstExprIsString;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static int ScriptVarCount;
static int ScriptArrayCount;
static int ScriptArraySize[MAX_SCRIPT_ARRAYS];
static statement_t StatementHistory[MAX_STATEMENT_DEPTH];
static int StatementIndex;
static breakInfo_t BreakInfo[MAX_BREAK];
@ -533,6 +538,7 @@ static void OuterScript(void)
CaseIndex = 0;
StatementLevel = 0;
ScriptVarCount = 0;
ScriptArrayCount = 0;
SY_FreeLocals();
TK_NextToken();
@ -738,7 +744,7 @@ static void OuterScript(void)
{
PC_AppendCmd(PCD_TERMINATE);
}
PC_SetScriptVarCount(scriptNumber, scriptType, ScriptVarCount);
PC_SetScriptVarCount(scriptNumber, scriptType, ScriptVarCount, ScriptArrayCount, ScriptArraySize);
pa_ScriptCount++;
}
@ -761,6 +767,7 @@ static void OuterFunction(void)
CaseIndex = 0;
StatementLevel = 0;
ScriptVarCount = 0;
ScriptArrayCount = 0;
SY_FreeLocals();
TK_NextToken();
if(tk_Token != TK_STR && tk_Token != TK_INT &&
@ -911,7 +918,7 @@ static void OuterFunction(void)
sym->info.scriptFunc.predefined = NO;
sym->info.scriptFunc.varCount = ScriptVarCount -
sym->info.scriptFunc.argCount;
PC_AddFunction(sym);
PC_AddFunction(sym, ScriptArrayCount, ScriptArraySize);
UnspeculateFunction(sym);
InsideFunction = NULL;
}
@ -925,7 +932,7 @@ static void OuterFunction(void)
static void OuterMapVar(boolean local)
{
symbolNode_t *sym = NULL;
int index, i;
int index;
MS_Message(MSG_DEBUG, "---- %s ----\n", local ? "LeadingStaticVarDeclare" : "OuterMapVar");
do
@ -980,75 +987,17 @@ static void OuterMapVar(boolean local)
}
else if(tk_Token == TK_LBRACKET)
{
int size = 0;
int ndim = 0;
int dims[MAX_ARRAY_DIMS];
int size, ndim, dims[MAX_ARRAY_DIMS];
memset(dims, 0, sizeof(dims));
ParseArrayDims(&size, &ndim, dims);
while(tk_Token == TK_LBRACKET)
{
if(ndim == MAX_ARRAY_DIMS)
{
ERR_Error(ERR_TOO_MANY_ARRAY_DIMS, YES);
do
{
TK_NextToken();
} while(tk_Token != TK_COMMA && tk_Token != TK_SEMICOLON);
break;
}
TK_NextToken();
if (tk_Token == TK_RBRACKET)
{
ERR_Error(ERR_NEED_ARRAY_SIZE, YES);
}
else
{
dims[ndim] = EvalConstExpression();
if(dims[ndim] == 0)
{
ERR_Error(ERR_ZERO_DIMENSION, YES);
dims[ndim] = 1;
}
if(ndim == 0)
{
size = dims[ndim];
}
else
{
size *= dims[ndim];
}
}
ndim++;
TK_TokenMustBe(TK_RBRACKET, ERR_MISSING_RBRACKET);
TK_NextToken();
}
if(sym != NULL)
{
if(ImportMode != IMPORT_Importing)
{
PC_AddArray(index, size);
}
MS_Message(MSG_DEBUG, "%s changed to an array of size %d\n", sym->name, size);
sym->type = SY_MAPARRAY;
sym->info.array.index = index;
sym->info.array.ndim = ndim;
sym->info.array.size = size;
if(ndim > 0)
{
sym->info.array.dimensions[ndim-1] = 1;
for(i = ndim - 2; i >= 0; --i)
{
sym->info.array.dimensions[i] =
sym->info.array.dimensions[i+1] * dims[i+1];
}
}
MS_Message(MSG_DEBUG, " - with multipliers ");
for(i = 0; i < ndim; ++i)
{
MS_Message(MSG_DEBUG, "[%d]", sym->info.array.dimensions[i]);
}
MS_Message(MSG_DEBUG, "\n");
SymToArray(SY_MAPARRAY, sym, index, size, ndim, dims);
if(tk_Token == TK_ASSIGN)
{
InitializeArray(sym, dims, size);
@ -1519,8 +1468,26 @@ static void LeadingVarDeclare(void)
TK_NextToken();
if(tk_Token == TK_LBRACKET)
{
ERR_Error(ERR_ARRAY_MAPVAR_ONLY, YES);
do {} while(TK_NextToken() != TK_COMMA && tk_Token != TK_SEMICOLON);
int size, ndim, dims[MAX_ARRAY_DIMS];
ParseArrayDims(&size, &ndim, dims);
if(sym != NULL)
{
ScriptVarCount--;
if(ScriptArrayCount == MAX_SCRIPT_ARRAYS)
{
ERR_Error(InsideFunction ? ERR_TOO_MANY_FUNCTION_ARRAYS : ERR_TOO_MANY_SCRIPT_ARRAYS, YES, NULL);
}
if(ScriptArrayCount < MAX_SCRIPT_ARRAYS)
{
ScriptArraySize[ScriptArrayCount] = size;
}
SymToArray(SY_SCRIPTARRAY, sym, ScriptArrayCount++, size, ndim, dims);
if(tk_Token == TK_ASSIGN)
{
InitializeScriptArray(sym, dims, size);
}
}
}
else if(tk_Token == TK_ASSIGN)
{
@ -1785,6 +1752,7 @@ static void LeadingIdentifier(void)
case SY_MAPVAR:
case SY_WORLDVAR:
case SY_GLOBALVAR:
case SY_SCRIPTARRAY:
case SY_WORLDARRAY:
case SY_GLOBALARRAY:
LeadingVarAssign(sym);
@ -2257,7 +2225,7 @@ static void ActionOnCharRange(boolean write)
sym = SpeculateSymbol(tk_String, NO);
if((sym->type != SY_MAPARRAY) && (sym->type != SY_WORLDARRAY)
&& (sym->type != SY_GLOBALARRAY))
&& (sym->type != SY_GLOBALARRAY) && (sym->type != SY_SCRIPTARRAY))
{
ERR_Error(ERR_NOT_AN_ARRAY, YES, sym->name);
}
@ -2333,7 +2301,12 @@ static void ActionOnCharRange(boolean write)
}
}
if(sym->type == SY_MAPARRAY)
if(sym->type == SY_SCRIPTARRAY)
{
if (write) PC_AppendCmd(PCD_STRCPYTOSCRIPTCHRANGE);
else PC_AppendCmd( rangeConstraints ? PCD_PRINTSCRIPTCHRANGE : PCD_PRINTSCRIPTCHARARRAY );
}
else if(sym->type == SY_MAPARRAY)
{
if (write) PC_AppendCmd(PCD_STRCPYTOMAPCHRANGE);
else PC_AppendCmd( rangeConstraints ? PCD_PRINTMAPCHRANGE : PCD_PRINTMAPCHARARRAY );
@ -3083,7 +3056,8 @@ static void LeadingIncDec(int token)
if(sym->type != SY_SCRIPTVAR && sym->type != SY_MAPVAR
&& sym->type != SY_WORLDVAR && sym->type != SY_GLOBALVAR
&& sym->type != SY_MAPARRAY && sym->type != SY_GLOBALARRAY
&& sym->type != SY_WORLDARRAY && sym->type != SY_SCRIPTALIAS)
&& sym->type != SY_WORLDARRAY && sym->type != SY_SCRIPTALIAS
&& sym->type != SY_SCRIPTARRAY)
{
ERR_Error(ERR_INCDEC_OP_ON_NON_VAR, YES);
TK_SkipPast(TK_SEMICOLON);
@ -3091,7 +3065,7 @@ static void LeadingIncDec(int token)
}
TK_NextToken();
if(sym->type == SY_MAPARRAY || sym->type == SY_WORLDARRAY
|| sym->type == SY_GLOBALARRAY)
|| sym->type == SY_GLOBALARRAY || sym->type == SY_SCRIPTARRAY)
{
ParseArrayIndices(sym, sym->info.array.ndim);
}
@ -3133,7 +3107,7 @@ static void LeadingVarAssign(symbolNode_t *sym)
{
TK_NextToken(); // Fetch assignment operator
if(sym->type == SY_MAPARRAY || sym->type == SY_WORLDARRAY
|| sym->type == SY_GLOBALARRAY)
|| sym->type == SY_GLOBALARRAY || sym->type == SY_SCRIPTARRAY)
{
ParseArrayIndices(sym, sym->info.array.ndim);
}
@ -3214,21 +3188,21 @@ static pcd_t GetAssignPCD(tokenType_t token, symbolType_t symbol)
static symbolType_t symbolLookup[] =
{
SY_SCRIPTVAR, SY_MAPVAR, SY_WORLDVAR, SY_GLOBALVAR, SY_MAPARRAY,
SY_WORLDARRAY, SY_GLOBALARRAY
SY_WORLDARRAY, SY_GLOBALARRAY, SY_SCRIPTARRAY
};
static pcd_t assignmentLookup[11][7] =
static pcd_t assignmentLookup[11][8] =
{
{ PCD_ASSIGNSCRIPTVAR, PCD_ASSIGNMAPVAR, PCD_ASSIGNWORLDVAR, PCD_ASSIGNGLOBALVAR, PCD_ASSIGNMAPARRAY, PCD_ASSIGNWORLDARRAY, PCD_ASSIGNGLOBALARRAY },
{ PCD_ADDSCRIPTVAR, PCD_ADDMAPVAR, PCD_ADDWORLDVAR, PCD_ADDGLOBALVAR, PCD_ADDMAPARRAY, PCD_ADDWORLDARRAY, PCD_ADDGLOBALARRAY },
{ PCD_SUBSCRIPTVAR, PCD_SUBMAPVAR, PCD_SUBWORLDVAR, PCD_SUBGLOBALVAR, PCD_SUBMAPARRAY, PCD_SUBWORLDARRAY, PCD_SUBGLOBALARRAY },
{ PCD_MULSCRIPTVAR, PCD_MULMAPVAR, PCD_MULWORLDVAR, PCD_MULGLOBALVAR, PCD_MULMAPARRAY, PCD_MULWORLDARRAY, PCD_MULGLOBALARRAY },
{ PCD_DIVSCRIPTVAR, PCD_DIVMAPVAR, PCD_DIVWORLDVAR, PCD_DIVGLOBALVAR, PCD_DIVMAPARRAY, PCD_DIVWORLDARRAY, PCD_DIVGLOBALARRAY },
{ PCD_MODSCRIPTVAR, PCD_MODMAPVAR, PCD_MODWORLDVAR, PCD_MODGLOBALVAR, PCD_MODMAPARRAY, PCD_MODWORLDARRAY, PCD_MODGLOBALARRAY },
{ PCD_ANDSCRIPTVAR, PCD_ANDMAPVAR, PCD_ANDWORLDVAR, PCD_ANDGLOBALVAR, PCD_ANDMAPARRAY, PCD_ANDWORLDARRAY, PCD_ANDGLOBALARRAY },
{ PCD_EORSCRIPTVAR, PCD_EORMAPVAR, PCD_EORWORLDVAR, PCD_EORGLOBALVAR, PCD_EORMAPARRAY, PCD_EORWORLDARRAY, PCD_EORGLOBALARRAY },
{ PCD_ORSCRIPTVAR, PCD_ORMAPVAR, PCD_ORWORLDVAR, PCD_ORGLOBALVAR, PCD_ORMAPARRAY, PCD_ORWORLDARRAY, PCD_ORGLOBALARRAY },
{ PCD_LSSCRIPTVAR, PCD_LSMAPVAR, PCD_LSWORLDVAR, PCD_LSGLOBALVAR, PCD_LSMAPARRAY, PCD_LSWORLDARRAY, PCD_LSGLOBALARRAY },
{ PCD_RSSCRIPTVAR, PCD_RSMAPVAR, PCD_RSWORLDVAR, PCD_RSGLOBALVAR, PCD_RSMAPARRAY, PCD_RSWORLDARRAY, PCD_RSGLOBALARRAY }
{ PCD_ASSIGNSCRIPTVAR, PCD_ASSIGNMAPVAR, PCD_ASSIGNWORLDVAR, PCD_ASSIGNGLOBALVAR, PCD_ASSIGNMAPARRAY, PCD_ASSIGNWORLDARRAY, PCD_ASSIGNGLOBALARRAY, PCD_ASSIGNSCRIPTARRAY },
{ PCD_ADDSCRIPTVAR, PCD_ADDMAPVAR, PCD_ADDWORLDVAR, PCD_ADDGLOBALVAR, PCD_ADDMAPARRAY, PCD_ADDWORLDARRAY, PCD_ADDGLOBALARRAY, PCD_ANDSCRIPTARRAY },
{ PCD_SUBSCRIPTVAR, PCD_SUBMAPVAR, PCD_SUBWORLDVAR, PCD_SUBGLOBALVAR, PCD_SUBMAPARRAY, PCD_SUBWORLDARRAY, PCD_SUBGLOBALARRAY, PCD_SUBSCRIPTARRAY },
{ PCD_MULSCRIPTVAR, PCD_MULMAPVAR, PCD_MULWORLDVAR, PCD_MULGLOBALVAR, PCD_MULMAPARRAY, PCD_MULWORLDARRAY, PCD_MULGLOBALARRAY, PCD_MULSCRIPTARRAY },
{ PCD_DIVSCRIPTVAR, PCD_DIVMAPVAR, PCD_DIVWORLDVAR, PCD_DIVGLOBALVAR, PCD_DIVMAPARRAY, PCD_DIVWORLDARRAY, PCD_DIVGLOBALARRAY, PCD_DIVSCRIPTARRAY },
{ PCD_MODSCRIPTVAR, PCD_MODMAPVAR, PCD_MODWORLDVAR, PCD_MODGLOBALVAR, PCD_MODMAPARRAY, PCD_MODWORLDARRAY, PCD_MODGLOBALARRAY, PCD_MODSCRIPTARRAY },
{ PCD_ANDSCRIPTVAR, PCD_ANDMAPVAR, PCD_ANDWORLDVAR, PCD_ANDGLOBALVAR, PCD_ANDMAPARRAY, PCD_ANDWORLDARRAY, PCD_ANDGLOBALARRAY, PCD_ANDSCRIPTARRAY },
{ PCD_EORSCRIPTVAR, PCD_EORMAPVAR, PCD_EORWORLDVAR, PCD_EORGLOBALVAR, PCD_EORMAPARRAY, PCD_EORWORLDARRAY, PCD_EORGLOBALARRAY, PCD_EORSCRIPTARRAY },
{ PCD_ORSCRIPTVAR, PCD_ORMAPVAR, PCD_ORWORLDVAR, PCD_ORGLOBALVAR, PCD_ORMAPARRAY, PCD_ORWORLDARRAY, PCD_ORGLOBALARRAY, PCD_ORSCRIPTARRAY },
{ PCD_LSSCRIPTVAR, PCD_LSMAPVAR, PCD_LSWORLDVAR, PCD_LSGLOBALVAR, PCD_LSMAPARRAY, PCD_LSWORLDARRAY, PCD_LSGLOBALARRAY, PCD_LSSCRIPTARRAY },
{ PCD_RSSCRIPTVAR, PCD_RSMAPVAR, PCD_RSWORLDVAR, PCD_RSGLOBALVAR, PCD_RSMAPARRAY, PCD_RSWORLDARRAY, PCD_RSGLOBALARRAY, PCD_RSSCRIPTARRAY }
};
for(i = 0; i < ARRAY_SIZE(tokenLookup); ++i)
@ -3593,7 +3567,7 @@ static void ExprFactor(void)
if(sym->type != SY_SCRIPTVAR && sym->type != SY_MAPVAR
&& sym->type != SY_WORLDVAR && sym->type != SY_GLOBALVAR
&& sym->type != SY_MAPARRAY && sym->type != SY_WORLDARRAY
&& sym->type != SY_GLOBALARRAY)
&& sym->type != SY_GLOBALARRAY && sym->type != SY_SCRIPTARRAY)
{
ERR_Error(ERR_INCDEC_OP_ON_NON_VAR, YES);
}
@ -3601,7 +3575,7 @@ static void ExprFactor(void)
{
TK_NextToken();
if(sym->type == SY_MAPARRAY || sym->type == SY_WORLDARRAY
|| sym->type == SY_GLOBALARRAY)
|| sym->type == SY_GLOBALARRAY || sym->type == SY_SCRIPTARRAY)
{
ParseArrayIndices(sym, sym->info.array.ndim);
PC_AppendCmd(PCD_DUP);
@ -3627,6 +3601,7 @@ static void ExprFactor(void)
case SY_SCRIPTALIAS:
// FIXME
break;
case SY_SCRIPTARRAY:
case SY_MAPARRAY:
case SY_WORLDARRAY:
case SY_GLOBALARRAY:
@ -3638,7 +3613,7 @@ static void ExprFactor(void)
case SY_WORLDVAR:
case SY_GLOBALVAR:
if(sym->type != SY_MAPARRAY && sym->type != SY_WORLDARRAY
&& sym->type != SY_GLOBALARRAY)
&& sym->type != SY_GLOBALARRAY && sym->type != SY_SCRIPTARRAY)
{
TK_NextToken();
if(tk_Token == TK_LBRACKET)
@ -3652,7 +3627,7 @@ static void ExprFactor(void)
}
if((tk_Token == TK_INC || tk_Token == TK_DEC)
&& (sym->type == SY_MAPARRAY || sym->type == SY_WORLDARRAY
|| sym->type == SY_GLOBALARRAY))
|| sym->type == SY_GLOBALARRAY || sym->type == SY_SCRIPTARRAY))
{
PC_AppendCmd(PCD_DUP);
}
@ -3661,7 +3636,7 @@ static void ExprFactor(void)
if(tk_Token == TK_INC || tk_Token == TK_DEC)
{
if(sym->type == SY_MAPARRAY || sym->type == SY_WORLDARRAY
|| sym->type == SY_GLOBALARRAY)
|| sym->type == SY_GLOBALARRAY || sym->type == SY_SCRIPTARRAY)
{
PC_AppendCmd(PCD_SWAP);
}
@ -3967,6 +3942,8 @@ static pcd_t GetPushVarPCD(symbolType_t symType)
return PCD_PUSHWORLDVAR;
case SY_GLOBALVAR:
return PCD_PUSHGLOBALVAR;
case SY_SCRIPTARRAY:
return PCD_PUSHSCRIPTARRAY;
case SY_MAPARRAY:
return PCD_PUSHMAPARRAY;
case SY_WORLDARRAY:
@ -3999,6 +3976,7 @@ static pcd_t GetIncDecPCD(tokenType_t token, symbolType_t symbol)
{ TK_INC, SY_MAPVAR, PCD_INCMAPVAR },
{ TK_INC, SY_WORLDVAR, PCD_INCWORLDVAR },
{ TK_INC, SY_GLOBALVAR, PCD_INCGLOBALVAR },
{ TK_INC, SY_SCRIPTARRAY, PCD_INCSCRIPTARRAY },
{ TK_INC, SY_MAPARRAY, PCD_INCMAPARRAY },
{ TK_INC, SY_WORLDARRAY, PCD_INCWORLDARRAY },
{ TK_INC, SY_GLOBALARRAY, PCD_INCGLOBALARRAY },
@ -4007,6 +3985,7 @@ static pcd_t GetIncDecPCD(tokenType_t token, symbolType_t symbol)
{ TK_DEC, SY_MAPVAR, PCD_DECMAPVAR },
{ TK_DEC, SY_WORLDVAR, PCD_DECWORLDVAR },
{ TK_DEC, SY_GLOBALVAR, PCD_DECGLOBALVAR },
{ TK_DEC, SY_SCRIPTARRAY, PCD_DECSCRIPTARRAY },
{ TK_DEC, SY_MAPARRAY, PCD_DECMAPARRAY },
{ TK_DEC, SY_WORLDARRAY, PCD_DECWORLDARRAY },
{ TK_DEC, SY_GLOBALARRAY, PCD_DECGLOBALARRAY },
@ -4025,6 +4004,91 @@ static pcd_t GetIncDecPCD(tokenType_t token, symbolType_t symbol)
return PCD_NOP;
}
//==========================================================================
//
// ParseArrayDims
//
//==========================================================================
static void ParseArrayDims(int *size_p, int *ndim_p, int dims[MAX_ARRAY_DIMS])
{
int size = 0;
int ndim = 0;
memset(dims, 0, sizeof(dims));
while(tk_Token == TK_LBRACKET)
{
if(ndim == MAX_ARRAY_DIMS)
{
ERR_Error(ERR_TOO_MANY_ARRAY_DIMS, YES);
do
{
TK_NextToken();
} while(tk_Token != TK_COMMA && tk_Token != TK_SEMICOLON);
break;
}
TK_NextToken();
if (tk_Token == TK_RBRACKET)
{
ERR_Error(ERR_NEED_ARRAY_SIZE, YES);
}
else
{
dims[ndim] = EvalConstExpression();
if(dims[ndim] == 0)
{
ERR_Error(ERR_ZERO_DIMENSION, YES);
dims[ndim] = 1;
}
if(ndim == 0)
{
size = dims[ndim];
}
else
{
size *= dims[ndim];
}
}
ndim++;
TK_TokenMustBe(TK_RBRACKET, ERR_MISSING_RBRACKET);
TK_NextToken();
}
if(pc_EnforceHexen)
{
TK_Undo(); // backup so error pointer is on last bracket instead of following token
ERR_Error(ERR_HEXEN_COMPAT, YES);
TK_NextToken();
}
*size_p = size;
*ndim_p = ndim;
}
static void SymToArray(int symtype, symbolNode_t *sym, int index, int size, int ndim, int dims[MAX_ARRAY_DIMS])
{
int i;
MS_Message(MSG_DEBUG, "%s changed to an array of size %d\n", sym->name, size);
sym->type = symtype;
sym->info.array.index = index;
sym->info.array.ndim = ndim;
sym->info.array.size = size;
if(ndim > 0)
{
sym->info.array.dimensions[ndim-1] = 1;
for(i = ndim - 2; i >= 0; --i)
{
sym->info.array.dimensions[i] =
sym->info.array.dimensions[i+1] * dims[i+1];
}
}
MS_Message(MSG_DEBUG, " - with multipliers ");
for(i = 0; i < ndim; ++i)
{
MS_Message(MSG_DEBUG, "[%d]", sym->info.array.dimensions[i]);
}
MS_Message(MSG_DEBUG, "\n");
}
//==========================================================================
//
// ParseArrayIndices
@ -4044,8 +4108,8 @@ static void ParseArrayIndices(symbolNode_t *sym, int requiredIndices)
while(tk_Token == TK_LBRACKET)
{
TK_NextToken();
if((sym->type == SY_MAPARRAY && i == requiredIndices) ||
(sym->type != SY_MAPARRAY && i > 0))
if(((sym->type == SY_MAPARRAY || sym->type == SY_SCRIPTARRAY) && i == requiredIndices) ||
(sym->type != SY_MAPARRAY && sym->type != SY_SCRIPTARRAY && i > 0))
{
if (!warned)
{
@ -4097,6 +4161,12 @@ static void ParseArrayIndices(symbolNode_t *sym, int requiredIndices)
}
}
//==========================================================================
//
// ProcessArrayLevel
//
//==========================================================================
static void ProcessArrayLevel(int level, int *entry, int ndim,
int dims[MAX_ARRAY_DIMS], int muls[MAX_ARRAY_DIMS], char *name)
{
@ -4216,6 +4286,112 @@ static void InitializeArray(symbolNode_t *sym, int dims[MAX_ARRAY_DIMS], int siz
}
}
//==========================================================================
//
// ProcessScriptArrayLevel
//
//==========================================================================
static void ProcessScriptArrayLevel(int level, symbolNode_t *sym, int ndim,
int dims[MAX_ARRAY_DIMS], int muls[MAX_ARRAY_DIMS], char *name)
{
int warned_too_many = NO;
int i;
int loc = 0;
for(i = 0; ; ++i)
{
if(tk_Token == TK_COMMA)
{
loc += muls[level-1];
TK_NextToken();
}
else if(tk_Token == TK_RBRACE)
{
TK_NextToken();
return;
}
else
{
if(level == ndim)
{
if(tk_Token == TK_LBRACE)
{
ERR_Error(ERR_TOO_MANY_DIM_USED, YES, name, ndim);
SkipBraceBlock(0);
TK_NextToken();
loc++;
}
else
{
if(i >= dims[level - 1] && !warned_too_many)
{
warned_too_many = YES;
ERR_Error(ERR_TOO_MANY_ARRAY_INIT, YES);
}
PC_AppendPushVal(loc + i);
EvalExpression();
PC_AppendCmd(PCD_ASSIGNSCRIPTARRAY);
PC_AppendShrink(sym->info.array.index);
}
}
else
{
//Bugfix for r3226 by Zom-B
if (i >= dims[level - 1])
{
if (!warned_too_many)
{
warned_too_many = YES;
ERR_Error(ERR_TOO_MANY_ARRAY_INIT, YES);
}
}
TK_TokenMustBe(TK_LBRACE, ERR_MISSING_LBRACE_ARR);
TK_NextToken();
ProcessScriptArrayLevel(level+1, sym, ndim, dims, muls, name);
assert(level > 0);
loc += muls[level-1];
}
if(i < dims[level-1]-1)
{
if(tk_Token != TK_RBRACE)
{
TK_TokenMustBe(TK_COMMA, ERR_MISSING_COMMA);
TK_NextToken();
}
}
else
{
if(tk_Token != TK_COMMA)
{
TK_TokenMustBe(TK_RBRACE, ERR_MISSING_RBRACE_ARR);
}
else
{
TK_NextToken();
}
}
}
}
TK_TokenMustBe(TK_RBRACE, ERR_MISSING_RBRACE_ARR);
TK_NextToken();
}
//==========================================================================
//
// InitializeScriptArray
//
//==========================================================================
static void InitializeScriptArray(symbolNode_t *sym, int dims[MAX_ARRAY_DIMS], int size)
{
TK_NextTokenMustBe(TK_LBRACE, ERR_MISSING_LBRACE_ARR);
TK_NextToken();
ArrayHasStrings = NO;
ProcessScriptArrayLevel(1, sym, sym->info.array.ndim, dims,
sym->info.array.dimensions, sym->name);
}
//==========================================================================
//
// DemandSymbol

78
pcode.c
View file

@ -28,11 +28,13 @@ typedef struct scriptInfo_s
S_WORD number;
U_BYTE type;
U_BYTE argCount;
U_BYTE arrayCount;
U_WORD varCount;
U_WORD flags;
int address;
int srcLine;
boolean imported;
int arraySizes[MAX_SCRIPT_ARRAYS];
} scriptInfo_t;
typedef struct functionInfo_s
@ -40,8 +42,10 @@ typedef struct functionInfo_s
U_BYTE hasReturnValue;
U_BYTE argCount;
U_BYTE localCount;
U_BYTE arrayCount;
int address;
int name;
int arraySizes[MAX_SCRIPT_ARRAYS];
} functionInfo_t;
typedef struct mapVarInfo_s
@ -103,6 +107,7 @@ static int PushByteAddr;
static char Imports[MAX_IMPORTS][9];
static int NumImports;
static boolean HaveExtendedScripts;
static boolean HaveScriptArrays;
static char *PCDNames[PCODE_COMMAND_COUNT] =
{
@ -476,6 +481,23 @@ static char *PCDNames[PCODE_COMMAND_COUNT] =
"PCD_CALLSTACK", // from Eternity
"PCD_SCRIPTWAITNAMED",
"PCD_TRANSLATIONRANGE3",
"PCD_ASSIGNSCRIPTARRAY",
"PCD_PUSHSCRIPTARRAY",
"PCD_ADDSCRIPTARRAY",
"PCD_SUBSCRIPTARRAY",
"PCD_MULSCRIPTARRAY",
"PCD_DIVSCRIPTARRAY",
"PCD_MODSCRIPTARRAY",
"PCD_INCSCRIPTARRAY",
"PCD_DECSCRIPTARRAY",
"PCD_ANDSCRIPTARRAY",
"PCD_EORSCRIPTARRAY",
"PCD_ORSCRIPTARRAY",
"PCD_LSSCRIPTARRAY",
"PCD_RSSCRIPTARRAY",
"PCD_PRINTSCRIPTCHARARRAY",
"PCD_PRINTSCRIPTCHRANGE",
"PCD_STRCPYTOSCRIPTCHRANGE",
};
// CODE --------------------------------------------------------------------
@ -523,7 +545,8 @@ void PC_CloseObject(void)
}
if(!pc_NoShrink || (NumLanguages > 1) || (NumStringLists > 0) ||
(pc_FunctionCount > 0) || MapVariablesInit || NumArrays != 0 ||
pc_EncryptStrings || NumImports != 0 || HaveExtendedScripts)
pc_EncryptStrings || NumImports != 0 || HaveExtendedScripts ||
HaveScriptArrays)
{
if(pc_EnforceHexen)
{
@ -672,9 +695,25 @@ static void CloseNew(void)
}
}
// Add chunks for scripts with arrays
for(i = 0; i < pc_ScriptCount; ++i)
{
if(ScriptInfo[i].arrayCount)
{
PC_Append("SARY", 4);
PC_AppendInt(2 + ScriptInfo[i].arrayCount * 4);
PC_AppendWord(ScriptInfo[i].number);
for(j = 0; j < ScriptInfo[i].arrayCount; ++j)
{
PC_AppendInt(ScriptInfo[i].arraySizes[j]);
}
}
}
// Write the string table for named scripts.
STR_WriteListChunk(STRLIST_NAMEDSCRIPTS, MAKE4CC('S','N','A','M'), NO);
// Write the functions provided by this file.
if(pc_FunctionCount > 0)
{
PC_Append("FUNC", 4);
@ -694,6 +733,22 @@ static void CloseNew(void)
STR_WriteListChunk(STRLIST_FUNCTIONS, MAKE4CC('F','N','A','M'), NO);
}
// Add chunks for functions with arrays
for(i = 0; i < pc_FunctionCount; ++i)
{
if(FunctionInfo[i].arrayCount)
{
PC_Append("FARY", 4);
PC_AppendInt(2 + FunctionInfo[i].arrayCount * 4);
PC_AppendWord(i);
for(j = 0; j < FunctionInfo[i].arrayCount; ++j)
{
PC_AppendInt(FunctionInfo[i].arraySizes[j]);
}
}
}
if(NumLanguages > 1)
{
for(i = 0; i < NumLanguages; i++)
@ -1426,6 +1481,7 @@ void PC_AddScript(int number, int type, int flags, int argCount)
script->flags = flags;
script->srcLine = tk_Line;
script->imported = (ImportMode == IMPORT_Importing) ? YES : NO;
script->arrayCount = 0;
pc_ScriptCount++;
}
}
@ -1439,7 +1495,7 @@ void PC_AddScript(int number, int type, int flags, int argCount)
//
//==========================================================================
void PC_SetScriptVarCount(int number, int type, int varCount)
void PC_SetScriptVarCount(int number, int type, int varCount, int arrayCount, int *arraySizes)
{
int i;
@ -1448,6 +1504,12 @@ void PC_SetScriptVarCount(int number, int type, int varCount)
if(ScriptInfo[i].number == number && ScriptInfo[i].type == type)
{
ScriptInfo[i].varCount = varCount;
if (arrayCount > 0 && arrayCount < MAX_SCRIPT_ARRAYS)
{
ScriptInfo[i].arrayCount = (U_BYTE)arrayCount;
memcpy(ScriptInfo[i].arraySizes, arraySizes, arrayCount * sizeof(int));
HaveScriptArrays = YES;
}
break;
}
}
@ -1459,7 +1521,7 @@ void PC_SetScriptVarCount(int number, int type, int varCount)
//
//==========================================================================
void PC_AddFunction(symbolNode_t *sym)
void PC_AddFunction(symbolNode_t *sym, int arrayCount, int *arraySizes)
{
functionInfo_t *function;
@ -1479,6 +1541,16 @@ void PC_AddFunction(symbolNode_t *sym)
function->name = STR_AppendToList (STRLIST_FUNCTIONS, sym->name);
function->address = sym->info.scriptFunc.address;
sym->info.scriptFunc.funcNumber = pc_FunctionCount;
if (arrayCount > 0 && arrayCount < MAX_SCRIPT_ARRAYS)
{
function->arrayCount = (U_BYTE)arrayCount;
memcpy(function->arraySizes, arraySizes, arrayCount * sizeof(int));
HaveScriptArrays = YES;
}
else
{
function->arrayCount = 0;
}
pc_FunctionCount++;
}

22
pcode.h
View file

@ -426,6 +426,24 @@ typedef enum
PCD_SCRIPTWAITNAMED,
PCD_TRANSLATIONRANGE3,
PCD_ASSIGNSCRIPTARRAY,
PCD_PUSHSCRIPTARRAY,
PCD_ADDSCRIPTARRAY,
PCD_SUBSCRIPTARRAY,
PCD_MULSCRIPTARRAY,
PCD_DIVSCRIPTARRAY,
PCD_MODSCRIPTARRAY,
PCD_INCSCRIPTARRAY,
PCD_DECSCRIPTARRAY,
PCD_ANDSCRIPTARRAY,
PCD_EORSCRIPTARRAY,
PCD_ORSCRIPTARRAY,
PCD_LSSCRIPTARRAY,
PCD_RSSCRIPTARRAY,
PCD_PRINTSCRIPTCHARARRAY,
PCD_PRINTSCRIPTCHRANGE,
PCD_STRCPYTOSCRIPTCHRANGE,
PCODE_COMMAND_COUNT
} pcd_t;
@ -452,8 +470,8 @@ void PC_Skip(size_t size);
//void PC_SkipWord(void);
void PC_SkipInt(void);
void PC_AddScript(int number, int type, int flags, int argCount);
void PC_SetScriptVarCount(int number, int type, int varCount);
void PC_AddFunction(struct symbolNode_s *sym);
void PC_SetScriptVarCount(int number, int type, int varCount, int arrayCount, int *arraySizes);
void PC_AddFunction(struct symbolNode_s *sym, int arrayCount, int *sizes);
void PC_PutMapVariable(int index, int value);
void PC_NameMapVariable(int index, struct symbolNode_s *sym);
void PC_AddArray(int index, int size);

View file

@ -210,6 +210,7 @@ static char *SymbolTypeNames[] =
"SY_MAPVAR",
"SY_WORLDVAR",
"SY_GLOBALVAR",
"SY_SCRIPTARRAY",
"SY_MAPARRAY",
"SY_WORLDARRAY",
"SY_GLOBALARRAY",
@ -279,7 +280,7 @@ symbolNode_t *SY_FindGlobal(char *name)
sym->unused = NO;
if(sym->type == SY_SCRIPTFUNC)
{
PC_AddFunction(sym);
PC_AddFunction(sym, 0, NULL);
}
else if(sym->type == SY_MAPVAR)
{

View file

@ -28,6 +28,7 @@ typedef enum
SY_MAPVAR,
SY_WORLDVAR,
SY_GLOBALVAR,
SY_SCRIPTARRAY,
SY_MAPARRAY,
SY_WORLDARRAY,
SY_GLOBALARRAY,