diff --git a/polymer/eduke32/build/include/m32script.h b/polymer/eduke32/build/include/m32script.h index a19ac1645..5f1fb1022 100644 --- a/polymer/eduke32/build/include/m32script.h +++ b/polymer/eduke32/build/include/m32script.h @@ -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,11 +124,11 @@ 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, - GAMEARRAY_WARN = 0x00002000, + GAMEARRAY_WARN = 0x00002000, GAMEARRAY_NORMAL = 0x00004000, GAMEARRAY_OFCHAR = 0x00000001, @@ -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 diff --git a/polymer/eduke32/source/m32def.c b/polymer/eduke32/source/m32def.c index c94dd9c82..88f1fcdba 100644 --- a/polymer/eduke32/source/m32def.c +++ b/polymer/eduke32/source/m32def.c @@ -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 diff --git a/polymer/eduke32/source/m32exec.c b/polymer/eduke32/source/m32exec.c index 2180c3f43..67729cdf7 100644 --- a/polymer/eduke32/source/m32exec.c +++ b/polymer/eduke32/source/m32exec.c @@ -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 @@ -299,7 +297,15 @@ 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) - { - 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 + M32_ERROR("Tried to set on read-only array `%s'", aGameArrays[j].szLabel); + + if (!(index >= 0 && index < aGameArrays[j].size)) + M32_ERROR("Array index %d out of bounds", index); + + 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; } diff --git a/polymer/eduke32/source/m32vars.c b/polymer/eduke32/source/m32vars.c index b55b9ca9d..fac263870 100644 --- a/polymer/eduke32/source/m32vars.c +++ b/polymer/eduke32/source/m32vars.c @@ -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??");