M32Script cleanup. Fixes at least one non-minor and one minor bug.

git-svn-id: https://svn.eduke32.com/eduke32@4798 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2014-12-06 19:09:50 +00:00
parent 5e574436e2
commit 74d99fe2e1
4 changed files with 148 additions and 125 deletions

View file

@ -46,7 +46,7 @@ extern void VM_ScriptInfo(void);
extern void VM_Disasm(ofstype beg, int32_t size);
extern int32_t Gv_NewVar(const char *pszLabel, intptr_t lValue, uint32_t dwFlags);
extern int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32_t dwFlags);
extern int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, int32_t asize, uint32_t dwFlags);
extern void Gv_Init(void);
extern int32_t __fastcall Gv_GetVarX(register int32_t id);
@ -124,7 +124,7 @@ enum GamevarFlags_t {
};
enum GamearrayFlags_t {
MAXGAMEARRAYS = (MAXGAMEVARS>>2), // must be lower than MAXGAMEVARS
MAXGAMEARRAYS = (MAXGAMEVARS>>2), // must be strictly smaller than MAXGAMEVARS
MAXARRAYLABEL = MAXVARLABEL,
GAMEARRAY_READONLY = 0x00001000,
@ -136,9 +136,9 @@ enum GamearrayFlags_t {
GAMEARRAY_OFINT = 0x00000004,
GAMEARRAY_TYPE_MASK = GAMEARRAY_OFCHAR|GAMEARRAY_OFSHORT|GAMEARRAY_OFINT,
GAMEARRAY_VARSIZE = 0x00000020,
GAMEARRAY_RESET = 0x00000008,
GAMEARRAY_VARSIZE = 0x00000020,
};
typedef struct {
@ -235,17 +235,21 @@ extern int32_t mousyplc;
// uncomment if variable-length arrays are available
//#define M32_LOCALS_VARARRAY
// uncomment if alloca() is available
//#define M32_LOCALS_ALLOCA
// if neither is there, use a constant number of them
#define M32_LOCALS_FIXEDNUM 64
#if defined M32_LOCALS_VARARRAY || defined M32_LOCALS_ALLOCA
#if defined M32_LOCALS_VARARRAY
# define M32_MAX_LOCALS MAXGAMEVARS
#else
# define M32_MAX_LOCALS M32_LOCALS_FIXEDNUM
#endif
static inline int32_t Gv_GetArraySize(int32_t id)
{
if (aGameArrays[id].dwFlags & GAMEARRAY_VARSIZE)
return Gv_GetVarN(aGameArrays[id].size);
return aGameArrays[id].size;
}
#endif

View file

@ -1128,7 +1128,7 @@ static void C_GetNextVarType(int32_t type)
{
if (!m32_script_expertmode && (type&GV_WRITABLE))
{
int32_t flags = aGameArrays[id].dwFlags;
const int32_t flags = aGameArrays[id].dwFlags;
if (flags & GAMEARRAY_READONLY)
{
@ -1978,11 +1978,8 @@ static int32_t C_ParseCommand(void)
}
if (aGameArrays[i].dwFlags & GAMEARRAY_TYPE_MASK)
{
C_CUSTOMERROR("Array for %s must be user-defined.",
tw==CON_SORT?"sorting":"collecting sectors");
g_numCompilerErrors++;
}
}
else
{
@ -2543,7 +2540,8 @@ repeatcase:
C_GetNextValue(LABEL_DEFINE);
{
int32_t asize = *(g_scriptPtr-1);
const int32_t asize = *(g_scriptPtr-1);
if (cs.currentStateIdx < 0 && cs.currentEvent < 0)
Gv_NewArray(tlabel, NULL, asize, GAMEARRAY_NORMAL);
else // local array

View file

@ -138,13 +138,11 @@ void VM_OnEvent(register int32_t iEventID, register int32_t iActor)
}
{
instype *oinsptr=insptr;
instype *const oinsptr=insptr;
vmstate_t vm_backup;
void *olocalvars = aGameArrays[M32_LOCAL_ARRAY_ID].vals;
void *const olocalvars = aGameArrays[M32_LOCAL_ARRAY_ID].vals;
#ifdef M32_LOCALS_VARARRAY
int32_t localvars[aEventNumLocals[iEventID]];
#elif defined M32_LOCALS_ALLOCA
int32_t *localvars = alloca(aEventNumLocals[iEventID] * sizeof(int32_t));
#else
int32_t localvars[M32_LOCALS_FIXEDNUM];
#endif
@ -300,6 +298,14 @@ static char *GetMaybeInlineQuote(int32_t quotei)
return quotetext;
}
static int CheckArray(int aidx)
{
if (!(aidx >= 0 && aidx < g_gameArrayCount))
M32_ERROR("Invalid array %d!", aidx);
return (vm.flags&VMFLAG_ERROR);
}
int32_t VM_Execute(int32_t once)
{
register int32_t tw = *insptr;
@ -330,13 +336,11 @@ skip_check:
case CON_STATE:
{
instype *tempscrptr = insptr+2;
int32_t stateidx = *(insptr+1), o_g_st = vm.g_st, oret=vm.flags&VMFLAG_RETURN;
void *olocalvars = aGameArrays[M32_LOCAL_ARRAY_ID].vals;
instype *const tempscrptr = insptr+2;
const int32_t stateidx = *(insptr+1), o_g_st = vm.g_st, oret=vm.flags&VMFLAG_RETURN;
void *const olocalvars = aGameArrays[M32_LOCAL_ARRAY_ID].vals;
#ifdef M32_LOCALS_VARARRAY
int32_t localvars[statesinfo[stateidx].numlocals];
#elif defined M32_LOCALS_ALLOCA
int32_t *localvars = alloca(statesinfo[stateidx].numlocals * sizeof(int32_t));
#else
int32_t localvars[M32_LOCALS_FIXEDNUM];
#endif
@ -475,47 +479,54 @@ skip_check:
case CON_SETARRAY:
insptr++;
{
int32_t j=*insptr++;
int32_t index = Gv_GetVarX(*insptr++);
int32_t value = Gv_GetVarX(*insptr++);
const int32_t j=*insptr++;
const int32_t index = Gv_GetVarX(*insptr++);
const int32_t value = Gv_GetVarX(*insptr++);
CheckArray(j);
if (j<0 || j >= g_gameArrayCount)
{
M32_ERROR("Tried to set invalid array ID (%d)", j);
}
if (aGameArrays[j].dwFlags & GAMEARRAY_READONLY)
{
M32_ERROR("Tried to set on read-only array `%s'", aGameArrays[j].szLabel);
}
if (index >= aGameArrays[j].size || index < 0)
{
if (!(index >= 0 && index < aGameArrays[j].size))
M32_ERROR("Array index %d out of bounds", index);
}
if (vm.flags&VMFLAG_ERROR) continue;
((int32_t *)aGameArrays[j].vals)[index]=value; // REM: other array types not implemented, since they're read-only
if (vm.flags&VMFLAG_ERROR)
continue;
// NOTE: Other array types not implemented, since they're read-only.
((int32_t *)aGameArrays[j].vals)[index] = value;
continue;
}
case CON_GETARRAYSIZE:
insptr++;
{
int32_t j=*insptr++;
Gv_SetVarX(*insptr++, (aGameArrays[j].dwFlags&GAMEARRAY_VARSIZE) ?
Gv_GetVarN(aGameArrays[j].size) : aGameArrays[j].size);
const int32_t j=*insptr++;
if (CheckArray(j))
continue;
Gv_SetVarX(*insptr++, Gv_GetArraySize(j));
}
continue;
case CON_RESIZEARRAY:
insptr++;
{
int32_t j=*insptr++;
int32_t asize = Gv_GetVarX(*insptr++);
const int32_t j=*insptr++;
const int32_t asize = Gv_GetVarX(*insptr++);
if (asize<=0 || asize>65536)
{
CheckArray(j);
if (aGameArrays[j].dwFlags & GAMEARRAY_READONLY)
M32_ERROR("Tried to resize read-only array `%s'", aGameArrays[j].szLabel);
if (!(asize >= 1 && asize <= 65536))
M32_ERROR("Invalid array size %d (must be between 1 and 65536)", asize);
if (vm.flags&VMFLAG_ERROR)
continue;
}
// OSD_Printf(OSDTEXT_GREEN "CON_RESIZEARRAY: resizing array %s from %d to %d\n", aGameArrays[j].szLabel, aGameArrays[j].size, asize);
aGameArrays[j].vals = Xrealloc(aGameArrays[j].vals, sizeof(int32_t) * asize);
@ -527,34 +538,30 @@ skip_check:
case CON_COPY:
insptr++;
{
int32_t si=*insptr++, ssiz;
int32_t sidx = Gv_GetVarX(*insptr++); //, vm.g_i, vm.g_p);
int32_t di=*insptr++, dsiz;
const int32_t si=*insptr++;
int32_t sidx = Gv_GetVarX(*insptr++);
const int32_t di=*insptr++;
int32_t didx = Gv_GetVarX(*insptr++);
int32_t numelts = Gv_GetVarX(*insptr++);
if (si<0 || si>=g_gameArrayCount)
{
M32_ERROR("Invalid array %d!", si);
}
if (di<0 || di>=g_gameArrayCount)
{
M32_ERROR("Invalid array %d!", di);
}
CheckArray(si);
CheckArray(di);
if (aGameArrays[di].dwFlags & GAMEARRAY_READONLY)
{
M32_ERROR("Array %d is read-only!", di);
}
if (vm.flags&VMFLAG_ERROR) continue;
ssiz = (aGameArrays[si].dwFlags&GAMEARRAY_VARSIZE) ?
Gv_GetVarN(aGameArrays[si].size) : aGameArrays[si].size;
dsiz = (aGameArrays[di].dwFlags&GAMEARRAY_VARSIZE) ?
Gv_GetVarN(aGameArrays[si].size) : aGameArrays[di].size;
if (vm.flags&VMFLAG_ERROR)
continue;
if (sidx > ssiz || didx > dsiz) continue;
if ((sidx+numelts) > ssiz) numelts = ssiz-sidx;
if ((didx+numelts) > dsiz) numelts = dsiz-didx;
const int32_t ssiz = Gv_GetArraySize(si);
const int32_t dsiz = Gv_GetArraySize(di);
if (sidx > ssiz || didx > dsiz)
continue;
if (numelts > ssiz-sidx)
numelts = ssiz-sidx;
if (numelts > dsiz-didx)
numelts = dsiz-didx;
switch (aGameArrays[si].dwFlags & GAMEARRAY_TYPE_MASK)
{
@ -1142,14 +1149,23 @@ skip_check:
case CON_COLLECTSECTORS:
insptr++;
{
int32_t aridx=*insptr++, startsectnum=Gv_GetVarX(*insptr++);
int32_t numsectsVar=*insptr++, state=*insptr++;
const int32_t aridx=*insptr++, startsectnum=Gv_GetVarX(*insptr++);
const int32_t numsectsVar=*insptr++, state=*insptr++;
int32_t o_g_st=vm.g_st, arsize = aGameArrays[aridx].size;
instype *end=insptr;
if (CheckArray(aridx))
continue;
gamearray_t *const gar = &aGameArrays[aridx];
Bassert((gar->dwFlags & (GAMEARRAY_READONLY|GAMEARRAY_VARSIZE)) == 0);
const int32_t o_g_st=vm.g_st, arsize = gar->size;
instype *const end=insptr;
int32_t sectcnt, numsects=0;
int16_t *sectlist = (int16_t *)aGameArrays[aridx].vals; // actually an int32_t array
int32_t *sectlist32 = (int32_t *)sectlist;
// XXX: relies on -fno-strict-aliasing
int16_t *const sectlist = (int16_t *)gar->vals; // actually an int32_t array
int32_t *const sectlist32 = (int32_t *)sectlist;
int32_t j, startwall, endwall, ns;
static uint8_t sectbitmap[MAXSECTORS>>3];
@ -1194,26 +1210,35 @@ skip_check:
case CON_SORT:
insptr++;
{
int32_t aridx=*insptr++, count=Gv_GetVarX(*insptr++), state=*insptr++;
int32_t o_g_st=vm.g_st;
instype *end=insptr;
const int32_t aridx=*insptr++, count=Gv_GetVarX(*insptr++), state=*insptr++;
const int32_t o_g_st = vm.g_st;
instype *const end = insptr;
if (count<=0) continue;
if (count > aGameArrays[aridx].size)
if (CheckArray(aridx))
continue;
if (count <= 0)
continue;
gamearray_t *const gar = &aGameArrays[aridx];
Bassert((gar->dwFlags & (GAMEARRAY_READONLY|GAMEARRAY_VARSIZE)) == 0);
if (count > gar->size)
{
M32_ERROR("Count of elements to sort (%d) exceeds array size (%d)!", count,aGameArrays[aridx].size);
M32_ERROR("Count of elements to sort (%d) exceeds array size (%d)!",
count, gar->size);
continue;
}
if (state < 0)
{
qsort(aGameArrays[aridx].vals, count, sizeof(int32_t), X_DoSortDefault);
qsort(gar->vals, count, sizeof(int32_t), X_DoSortDefault);
}
else
{
x_sortingstateptr = script + statesinfo[state].ofs;
vm.g_st = 1+MAXEVENTS+state;
qsort(aGameArrays[aridx].vals, count, sizeof(int32_t), X_DoSort);
qsort(gar->vals, count, sizeof(int32_t), X_DoSort);
vm.g_st = o_g_st;
insptr = end;
}

View file

@ -57,18 +57,18 @@ static void Gv_Clear(void)
if (i >= MAXGAMEARRAYS)
continue;
if (aGameArrays[i].szLabel)
Bfree(aGameArrays[i].szLabel);
gamearray_t *const gar = &aGameArrays[i];
aGameArrays[i].szLabel = NULL;
Bfree(gar->szLabel);
gar->szLabel = NULL;
if ((aGameArrays[i].dwFlags & GAMEARRAY_NORMAL) && aGameArrays[i].vals)
if ((gar->dwFlags & GAMEARRAY_NORMAL) && gar->vals)
{
Bfree(aGameArrays[i].vals);
aGameArrays[i].vals=NULL;
Bfree(gar->vals);
gar->vals = NULL;
}
aGameArrays[i].dwFlags |= GAMEARRAY_RESET;
gar->dwFlags |= GAMEARRAY_RESET;
}
g_gameVarCount = g_gameArrayCount = 0;
@ -79,9 +79,9 @@ static void Gv_Clear(void)
return;
}
int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32_t dwFlags)
int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, int32_t asize, uint32_t dwFlags)
{
int32_t i;
Bassert(!(dwFlags&GAMEARRAY_VARSIZE) || (dwFlags&GAMEARRAY_READONLY));
if (g_gameArrayCount >= MAXGAMEARRAYS)
{
@ -95,15 +95,15 @@ int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32
return 0;
}
i = hash_find(&h_arrays, pszLabel);
const int32_t i = hash_find(&h_arrays, pszLabel);
if (i>=0 && !(aGameArrays[i].dwFlags & GAMEARRAY_RESET))
{
// found it it's a duplicate in error
if (aGameArrays[i].dwFlags&GAMEARRAY_TYPE_MASK)
{
C_CUSTOMWARNING("ignored redefining system array `%s'.", pszLabel);
}
// C_ReportError(WARNING_DUPLICATEDEFINITION);
return 0;
}
@ -112,27 +112,28 @@ int32_t Gv_NewArray(const char *pszLabel, void *arrayptr, intptr_t asize, uint32
{
// the dummy array with index 0 sets the size to 0 so that accidental accesses as array
// will complain.
C_CUSTOMERROR("invalid array size %d. Must be between 1 and 65536", (int32_t)asize);
C_CUSTOMERROR("invalid array size %d. Must be between 1 and 65536", asize);
return 0;
}
i = g_gameArrayCount;
gamearray_t *const gar = &aGameArrays[g_gameArrayCount];
if (aGameArrays[i].szLabel == NULL)
aGameArrays[i].szLabel = (char *)Xcalloc(MAXARRAYLABEL, sizeof(char));
if (aGameArrays[i].szLabel != pszLabel)
Bstrcpy(aGameArrays[i].szLabel, pszLabel);
if (gar->szLabel == NULL)
gar->szLabel = (char *)Xcalloc(MAXARRAYLABEL, sizeof(char));
if (gar->szLabel != pszLabel)
Bstrcpy(gar->szLabel, pszLabel);
if (!(dwFlags & GAMEARRAY_TYPE_MASK))
aGameArrays[i].vals = (int32_t *)Xcalloc(asize, sizeof(int32_t));
gar->vals = (int32_t *)Xcalloc(asize, sizeof(int32_t));
else
aGameArrays[i].vals = arrayptr;
gar->vals = arrayptr;
aGameArrays[i].size = asize;
aGameArrays[i].dwFlags = dwFlags & ~GAMEARRAY_RESET;
gar->size = asize;
gar->dwFlags = dwFlags & ~GAMEARRAY_RESET;
hash_add(&h_arrays, gar->szLabel, g_gameArrayCount, 1);
g_gameArrayCount++;
hash_add(&h_arrays, aGameArrays[i].szLabel, i, 1);
return 1;
}
@ -290,7 +291,6 @@ int32_t __fastcall Gv_GetVarX(register int32_t id)
case M32_FLAG_ARRAY:
{
register int32_t index;
int32_t siz;
index = (int32_t)((id>>16)&0xffff);
if (!(id&M32_FLAG_CONSTANTINDEX))
@ -298,26 +298,24 @@ int32_t __fastcall Gv_GetVarX(register int32_t id)
id &= (MAXGAMEARRAYS-1);
if (aGameArrays[id].dwFlags & GAMEARRAY_VARSIZE)
siz = Gv_GetVarN(aGameArrays[id].size);
else
siz = aGameArrays[id].size;
const int32_t siz = Gv_GetArraySize(id);
const gamearray_t *const gar = &aGameArrays[id];
if (index < 0 || index >= siz)
{
M32_ERROR("Gv_GetVarX(): invalid array index (%s[%d])", aGameArrays[id].szLabel, index);
M32_ERROR("Gv_GetVarX(): invalid array index (%s[%d])", gar->szLabel, index);
return -1;
}
switch (aGameArrays[id].dwFlags & GAMEARRAY_TYPE_MASK)
switch (gar->dwFlags & GAMEARRAY_TYPE_MASK)
{
case 0:
case GAMEARRAY_OFINT:
return (((int32_t *)aGameArrays[id].vals)[index] ^ -negateResult) + negateResult;
return (((int32_t *)gar->vals)[index] ^ -negateResult) + negateResult;
case GAMEARRAY_OFSHORT:
return (((int16_t *)aGameArrays[id].vals)[index] ^ -negateResult) + negateResult;
return (((int16_t *)gar->vals)[index] ^ -negateResult) + negateResult;
case GAMEARRAY_OFCHAR:
return (((uint8_t *)aGameArrays[id].vals)[index] ^ -negateResult) + negateResult;
return (((uint8_t *)gar->vals)[index] ^ -negateResult) + negateResult;
default:
M32_ERROR("Gv_GetVarX() (array): WTF??");
return -1;
@ -392,7 +390,6 @@ void __fastcall Gv_SetVarX(register int32_t id, register int32_t lValue)
case M32_FLAG_ARRAY:
{
register int32_t index;
int32_t siz;
index = (id>>16)&0xffff;
if (!(id&M32_FLAG_CONSTANTINDEX))
@ -400,27 +397,26 @@ void __fastcall Gv_SetVarX(register int32_t id, register int32_t lValue)
id &= (MAXGAMEARRAYS-1);
if (aGameArrays[id].dwFlags & GAMEARRAY_VARSIZE)
siz = Gv_GetVarN(aGameArrays[id].size);
else siz = aGameArrays[id].size;
const int32_t siz = Gv_GetArraySize(id);
gamearray_t *const gar = &aGameArrays[id];
if (index < 0 || index >= siz)
{
M32_ERROR("Gv_SetVarX(): invalid array index %s[%d], size=%d", aGameArrays[id].szLabel, index, siz);
M32_ERROR("Gv_SetVarX(): invalid array index %s[%d], size=%d", gar->szLabel, index, siz);
return;
}
switch (aGameArrays[id].dwFlags & GAMEARRAY_TYPE_MASK)
switch (gar->dwFlags & GAMEARRAY_TYPE_MASK)
{
case 0:
case GAMEARRAY_OFINT:
((int32_t *)aGameArrays[id].vals)[index] = lValue;
((int32_t *)gar->vals)[index] = lValue;
return;
case GAMEARRAY_OFSHORT:
((int16_t *)aGameArrays[id].vals)[index] = (int16_t)lValue;
((int16_t *)gar->vals)[index] = (int16_t)lValue;
return;
case GAMEARRAY_OFCHAR:
((uint8_t *)aGameArrays[id].vals)[index] = (uint8_t)lValue;
((uint8_t *)gar->vals)[index] = (uint8_t)lValue;
return;
default:
M32_ERROR("Gv_SetVarX() (array): WTF??");