diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/lscript/lscript_byteconvert.h |
Print done when done.
Diffstat (limited to 'indra/lscript/lscript_byteconvert.h')
-rw-r--r-- | indra/lscript/lscript_byteconvert.h | 1087 |
1 files changed, 1087 insertions, 0 deletions
diff --git a/indra/lscript/lscript_byteconvert.h b/indra/lscript/lscript_byteconvert.h new file mode 100644 index 0000000000..d30c84b28c --- /dev/null +++ b/indra/lscript/lscript_byteconvert.h @@ -0,0 +1,1087 @@ +/** + * @file lscript_byteconvert.h + * @brief Shared code for compiler and assembler for LSL + * + * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +// data shared between compiler/assembler +// used to convert data between byte stream and outside data types + +#ifndef LL_LSCRIPT_BYTECONVERT_H +#define LL_LSCRIPT_BYTECONVERT_H + +#include "stdtypes.h" +#include "v3math.h" +#include "llquaternion.h" +#include "lscript_byteformat.h" +#include "lluuid.h" + +void reset_hp_to_safe_spot(const U8 *buffer); + +// remember that LScript byte stream is BigEndian +void set_fault(const U8 *stream, LSCRIPTRunTimeFaults fault); + +inline S32 bytestream2integer(const U8 *stream, S32 &offset) +{ + stream += offset; + offset += 4; + return (*stream<<24) | (*(stream + 1)<<16) | (*(stream + 2)<<8) | *(stream + 3); +} + +inline U32 bytestream2unsigned_integer(const U8 *stream, S32 &offset) +{ + stream += offset; + offset += 4; + return (*stream<<24) | (*(stream + 1)<<16) | (*(stream + 2)<<8) | *(stream + 3); +} + +inline U64 bytestream2u64(const U8 *stream, S32 &offset) +{ + stream += offset; + offset += 8; + return ((U64)(*stream)<<56)| ((U64)(*(stream + 1))<<48) | ((U64)(*(stream + 2))<<40) | ((U64)(*(stream + 3))<<32) | + ((U64)(*(stream + 4))<<24) | ((U64)(*(stream + 5))<<16) | ((U64)(*(stream + 6))<<8) | (U64)(*(stream + 7)); +} + +inline void integer2bytestream(U8 *stream, S32 &offset, S32 integer) +{ + stream += offset; + offset += 4; + *(stream) = (integer >> 24); + *(stream + 1) = (integer >> 16) & 0xff; + *(stream + 2) = (integer >> 8) & 0xff; + *(stream + 3) = (integer) & 0xff; +} + +inline void unsigned_integer2bytestream(U8 *stream, S32 &offset, U32 integer) +{ + stream += offset; + offset += 4; + *(stream) = (integer >> 24); + *(stream + 1) = (integer >> 16) & 0xff; + *(stream + 2) = (integer >> 8) & 0xff; + *(stream + 3) = (integer) & 0xff; +} +inline void u642bytestream(U8 *stream, S32 &offset, U64 integer) +{ + stream += offset; + offset += 8; + *(stream) = (U8)(integer >> 56); + *(stream + 1) = (U8)((integer >> 48) & 0xff); + *(stream + 2) = (U8)((integer >> 40) & 0xff); + *(stream + 3) = (U8)((integer >> 32) & 0xff); + *(stream + 4) = (U8)((integer >> 24) & 0xff); + *(stream + 5) = (U8)((integer >> 16) & 0xff); + *(stream + 6) = (U8)((integer >> 8) & 0xff); + *(stream + 7) = (U8)((integer) & 0xff); +} + +inline S16 bytestream2s16(const U8 *stream, S32 &offset) +{ + stream += offset; + offset += 2; + return (*stream<<8) | *(stream + 1); +} + +inline void s162bytestream(U8 *stream, S32 &offset, S16 integer) +{ + stream += offset; + offset += 2; + *(stream) = (integer >> 8); + *(stream + 1) = (integer) & 0xff; +} + +inline U16 bytestream2u16(const U8 *stream, S32 &offset) +{ + stream += offset; + offset += 2; + return (*stream<<8) | *(stream + 1); +} + +inline void u162bytestream(U8 *stream, S32 &offset, U16 integer) +{ + stream += offset; + offset += 2; + *(stream) = (integer >> 8); + *(stream + 1) = (integer) & 0xff; +} + +inline F32 bytestream2float(const U8 *stream, S32 &offset) +{ + S32 value = bytestream2integer(stream, offset); + F32 fpvalue = *(F32 *)&value; + if (!llfinite(fpvalue)) + { + fpvalue = 0; + set_fault(stream, LSRF_MATH); + } + return fpvalue; +} + +inline void float2bytestream(U8 *stream, S32 &offset, F32 floatingpoint) +{ + S32 value = *(S32 *)&floatingpoint; + integer2bytestream(stream, offset, value); +} + +inline void bytestream_int2float(U8 *stream, S32 &offset) +{ + S32 value = bytestream2integer(stream, offset); + offset -= 4; + F32 fpvalue = (F32)value; + if (!llfinite(fpvalue)) + { + fpvalue = 0; + set_fault(stream, LSRF_MATH); + } + float2bytestream(stream, offset, fpvalue); +} + +inline void bytestream2char(char *buffer, const U8 *stream, S32 &offset) +{ + while ((*buffer++ = *(stream + offset++))) + ; +} + +inline void char2bytestream(U8 *stream, S32 &offset, char *buffer) +{ + while ((*(stream + offset++) = *buffer++)) + ; +} + +inline U8 bytestream2byte(const U8 *stream, S32 &offset) +{ + return *(stream + offset++); +} + +inline void byte2bytestream(U8 *stream, S32 &offset, U8 byte) +{ + *(stream + offset++) = byte; +} + +inline void bytestream2bytestream(U8 *dest, S32 &dest_offset, const U8 *src, S32 &src_offset, S32 count) +{ + while (count) + { + (*(dest + dest_offset++)) = (*(src + src_offset++)); + count--; + } +} + +inline void uuid2bytestream(U8 *stream, S32 &offset, const LLUUID &uuid) +{ + S32 i; + for (i = 0; i < UUID_BYTES; i++) + { + *(stream + offset++) = uuid.mData[i]; + } +} + +inline void bytestream2uuid(U8 *stream, S32 &offset, LLUUID &uuid) +{ + S32 i; + for (i = 0; i < UUID_BYTES; i++) + { + uuid.mData[i] = *(stream + offset++); + } +} + +// vectors and quaternions and encoded in backwards order to match the way in which they are stored on the stack +inline void bytestream2vector(LLVector3 &vector, const U8 *stream, S32 &offset) +{ + S32 value = bytestream2integer(stream, offset); + vector.mV[VZ] = *(F32 *)&value; + if (!llfinite(vector.mV[VZ])) + { + vector.mV[VZ] = 0; + set_fault(stream, LSRF_MATH); + } + value = bytestream2integer(stream, offset); + vector.mV[VY] = *(F32 *)&value; + if (!llfinite(vector.mV[VY])) + { + vector.mV[VY] = 0; + set_fault(stream, LSRF_MATH); + } + value = bytestream2integer(stream, offset); + vector.mV[VX] = *(F32 *)&value; + if (!llfinite(vector.mV[VX])) + { + vector.mV[VX] = 0; + set_fault(stream, LSRF_MATH); + } +} + +inline void vector2bytestream(U8 *stream, S32 &offset, LLVector3 &vector) +{ + S32 value = *(S32 *)&vector.mV[VZ]; + integer2bytestream(stream, offset, value); + value = *(S32 *)&vector.mV[VY]; + integer2bytestream(stream, offset, value); + value = *(S32 *)&vector.mV[VX]; + integer2bytestream(stream, offset, value); +} + +inline void bytestream2quaternion(LLQuaternion &quat, const U8 *stream, S32 &offset) +{ + S32 value = bytestream2integer(stream, offset); + quat.mQ[VS] = *(F32 *)&value; + if (!llfinite(quat.mQ[VS])) + { + quat.mQ[VS] = 0; + set_fault(stream, LSRF_MATH); + } + value = bytestream2integer(stream, offset); + quat.mQ[VZ] = *(F32 *)&value; + if (!llfinite(quat.mQ[VZ])) + { + quat.mQ[VZ] = 0; + set_fault(stream, LSRF_MATH); + } + value = bytestream2integer(stream, offset); + quat.mQ[VY] = *(F32 *)&value; + if (!llfinite(quat.mQ[VY])) + { + quat.mQ[VY] = 0; + set_fault(stream, LSRF_MATH); + } + value = bytestream2integer(stream, offset); + quat.mQ[VX] = *(F32 *)&value; + if (!llfinite(quat.mQ[VX])) + { + quat.mQ[VX] = 0; + set_fault(stream, LSRF_MATH); + } +} + +inline void quaternion2bytestream(U8 *stream, S32 &offset, LLQuaternion &quat) +{ + S32 value = *(S32 *)&quat.mQ[VS]; + integer2bytestream(stream, offset, value); + value = *(S32 *)&quat.mQ[VZ]; + integer2bytestream(stream, offset, value); + value = *(S32 *)&quat.mQ[VY]; + integer2bytestream(stream, offset, value); + value = *(S32 *)&quat.mQ[VX]; + integer2bytestream(stream, offset, value); +} + +inline S32 get_register(const U8 *stream, LSCRIPTRegisters reg) +{ + S32 offset = gLSCRIPTRegisterAddresses[reg]; + return bytestream2integer(stream, offset); +} + +inline F32 get_register_fp(U8 *stream, LSCRIPTRegisters reg) +{ + S32 offset = gLSCRIPTRegisterAddresses[reg]; + F32 value = bytestream2float(stream, offset); + if (!llfinite(value)) + { + value = 0; + set_fault(stream, LSRF_MATH); + } + return value; +} +inline U64 get_register_u64(U8 *stream, LSCRIPTRegisters reg) +{ + S32 offset = gLSCRIPTRegisterAddresses[reg]; + return bytestream2u64(stream, offset); +} + +inline U64 get_event_register(U8 *stream, LSCRIPTRegisters reg, S32 major_version) +{ + if (major_version == 1) + { + S32 offset = gLSCRIPTRegisterAddresses[reg]; + return (U64)bytestream2integer(stream, offset); + } + else if (major_version == 2) + { + S32 offset = gLSCRIPTRegisterAddresses[reg + (LREG_NCE - LREG_CE)]; + return bytestream2u64(stream, offset); + } + else + { + S32 offset = gLSCRIPTRegisterAddresses[reg]; + return (U64)bytestream2integer(stream, offset); + } +} + +inline void set_register(U8 *stream, LSCRIPTRegisters reg, S32 value) +{ + S32 offset = gLSCRIPTRegisterAddresses[reg]; + integer2bytestream(stream, offset, value); +} + +inline void set_register_fp(U8 *stream, LSCRIPTRegisters reg, F32 value) +{ + S32 offset = gLSCRIPTRegisterAddresses[reg]; + float2bytestream(stream, offset, value); +} + +inline void set_register_u64(U8 *stream, LSCRIPTRegisters reg, U64 value) +{ + S32 offset = gLSCRIPTRegisterAddresses[reg]; + u642bytestream(stream, offset, value); +} + +inline void set_event_register(U8 *stream, LSCRIPTRegisters reg, U64 value, S32 major_version) +{ + if (major_version == 1) + { + S32 offset = gLSCRIPTRegisterAddresses[reg]; + integer2bytestream(stream, offset, (S32)value); + } + else if (major_version == 2) + { + S32 offset = gLSCRIPTRegisterAddresses[reg + (LREG_NCE - LREG_CE)]; + u642bytestream(stream, offset, value); + } + else + { + S32 offset = gLSCRIPTRegisterAddresses[reg]; + integer2bytestream(stream, offset, (S32)value); + } +} + + +inline F32 add_register_fp(U8 *stream, LSCRIPTRegisters reg, F32 value) +{ + S32 offset = gLSCRIPTRegisterAddresses[reg]; + F32 newvalue = bytestream2float(stream, offset); + newvalue += value; + if (!llfinite(newvalue)) + { + newvalue = 0; + set_fault(stream, LSRF_MATH); + } + offset = gLSCRIPTRegisterAddresses[reg]; + float2bytestream(stream, offset, newvalue); + return newvalue; +} + +void lsa_print_heap(U8 *buffer); + + +inline void set_fault(const U8 *stream, LSCRIPTRunTimeFaults fault) +{ + S32 fr = get_register(stream, LREG_FR); + // record the first error + if (!fr) + { + if ( (fault == LSRF_HEAP_ERROR) + ||(fault == LSRF_STACK_HEAP_COLLISION) + ||(fault == LSRF_BOUND_CHECK_ERROR)) + { + reset_hp_to_safe_spot(stream); +// lsa_print_heap((U8 *)stream); + } + fr = LSCRIPTRunTimeFaultBits[fault]; + set_register((U8 *)stream, LREG_FR, fr); + } +} + +inline BOOL set_ip(U8 *stream, S32 ip) +{ + // Verify that the Instruction Pointer is in a valid + // code area (between the Global Function Register + // and Heap Register). + S32 gfr = get_register(stream, LREG_GFR); + if (ip == 0) + { + set_register(stream, LREG_IP, ip); + return TRUE; + } + if (ip < gfr) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + S32 hr = get_register(stream, LREG_HR); + if (ip >= hr) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + set_register(stream, LREG_IP, ip); + return TRUE; +} + +inline BOOL set_bp(U8 *stream, S32 bp) +{ + // Verify that the Base Pointer is in a valid + // data area (between the Heap Pointer and + // the Top of Memory, and below the + // Stack Pointer). + S32 hp = get_register(stream, LREG_HP); + if (bp <= hp) + { + set_fault(stream, LSRF_STACK_HEAP_COLLISION); + return FALSE; + } + S32 tm = get_register(stream, LREG_TM); + if (bp >= tm) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + S32 sp = get_register(stream, LREG_SP); + if (bp < sp) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + set_register(stream, LREG_BP, bp); + return TRUE; +} + +inline BOOL set_sp(U8 *stream, S32 sp) +{ + // Verify that the Stack Pointer is in a valid + // data area (between the Heap Pointer and + // the Top of Memory). + S32 hp = get_register(stream, LREG_HP); + if (sp <= hp) + { + set_fault(stream, LSRF_STACK_HEAP_COLLISION); + return FALSE; + } + S32 tm = get_register(stream, LREG_TM); + if (sp >= tm) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + set_register(stream, LREG_SP, sp); + return TRUE; +} + +inline void lscript_push(U8 *stream, U8 value) +{ + S32 sp = get_register(stream, LREG_SP); + sp -= 1; + + if (set_sp(stream, sp)) + { + *(stream + sp) = value; + } +} + +inline void lscript_push(U8 *stream, S32 value) +{ + S32 sp = get_register(stream, LREG_SP); + sp -= LSCRIPTDataSize[LST_INTEGER]; + + if (set_sp(stream, sp)) + { + integer2bytestream(stream, sp, value); + } +} + +inline void lscript_push(U8 *stream, F32 value) +{ + S32 sp = get_register(stream, LREG_SP); + sp -= LSCRIPTDataSize[LST_FLOATINGPOINT]; + + if (set_sp(stream, sp)) + { + float2bytestream(stream, sp, value); + } +} + +inline void lscript_push(U8 *stream, LLVector3 &value) +{ + S32 sp = get_register(stream, LREG_SP); + sp -= LSCRIPTDataSize[LST_VECTOR]; + + if (set_sp(stream, sp)) + { + vector2bytestream(stream, sp, value); + } +} + +inline void lscript_push(U8 *stream, LLQuaternion &value) +{ + S32 sp = get_register(stream, LREG_SP); + sp -= LSCRIPTDataSize[LST_QUATERNION]; + + if (set_sp(stream, sp)) + { + quaternion2bytestream(stream, sp, value); + } +} + +inline void lscript_pusharg(U8 *stream, S32 arg) +{ + S32 sp = get_register(stream, LREG_SP); + sp -= arg; + + set_sp(stream, sp); +} + +inline void lscript_poparg(U8 *stream, S32 arg) +{ + S32 sp = get_register(stream, LREG_SP); + sp += arg; + + set_sp(stream, sp); +} + +inline U8 lscript_pop_char(U8 *stream) +{ + S32 sp = get_register(stream, LREG_SP); + U8 value = *(stream + sp++); + set_sp(stream, sp); + return value; +} + +inline S32 lscript_pop_int(U8 *stream) +{ + S32 sp = get_register(stream, LREG_SP); + S32 value = bytestream2integer(stream, sp); + set_sp(stream, sp); + return value; +} + +inline F32 lscript_pop_float(U8 *stream) +{ + S32 sp = get_register(stream, LREG_SP); + F32 value = bytestream2float(stream, sp); + if (!llfinite(value)) + { + value = 0; + set_fault(stream, LSRF_MATH); + } + set_sp(stream, sp); + return value; +} + +inline void lscript_pop_vector(U8 *stream, LLVector3 &value) +{ + S32 sp = get_register(stream, LREG_SP); + bytestream2vector(value, stream, sp); + set_sp(stream, sp); +} + +inline void lscript_pop_quaternion(U8 *stream, LLQuaternion &value) +{ + S32 sp = get_register(stream, LREG_SP); + bytestream2quaternion(value, stream, sp); + set_sp(stream, sp); +} + +inline void lscript_pusharge(U8 *stream, S32 value) +{ + S32 sp = get_register(stream, LREG_SP); + sp -= value; + if (set_sp(stream, sp)) + { + S32 i; + for (i = 0; i < value; i++) + { + *(stream + sp++) = 0; + } + } +} + +inline BOOL lscript_check_local(U8 *stream, S32 &address, S32 size) +{ + S32 sp = get_register(stream, LREG_SP); + S32 bp = get_register(stream, LREG_BP); + + address += size; + address = bp - address; + + if (address < sp - size) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + S32 tm = get_register(stream, LREG_TM); + if (address + size > tm) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + return TRUE; +} + +inline BOOL lscript_check_global(U8 *stream, S32 &address, S32 size) +{ + S32 gvr = get_register(stream, LREG_GVR); + + // Possibility of overwriting registers? -- DK 09/07/04 + if (address < 0) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + + address += gvr; + S32 gfr = get_register(stream, LREG_GFR); + + if (address + size > gfr) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + return TRUE; +} + +inline void lscript_local_store(U8 *stream, S32 address, S32 value) +{ + if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_INTEGER])) + integer2bytestream(stream, address, value); +} + +inline void lscript_local_store(U8 *stream, S32 address, F32 value) +{ + if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_FLOATINGPOINT])) + float2bytestream(stream, address, value); +} + +inline void lscript_local_store(U8 *stream, S32 address, LLVector3 value) +{ + if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_VECTOR])) + vector2bytestream(stream, address, value); +} + +inline void lscript_local_store(U8 *stream, S32 address, LLQuaternion value) +{ + if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_QUATERNION])) + quaternion2bytestream(stream, address, value); +} + +inline void lscript_global_store(U8 *stream, S32 address, S32 value) +{ + if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_INTEGER])) + integer2bytestream(stream, address, value); +} + +inline void lscript_global_store(U8 *stream, S32 address, F32 value) +{ + if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_FLOATINGPOINT])) + float2bytestream(stream, address, value); +} + +inline void lscript_global_store(U8 *stream, S32 address, LLVector3 value) +{ + if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_VECTOR])) + vector2bytestream(stream, address, value); +} + +inline void lscript_global_store(U8 *stream, S32 address, LLQuaternion value) +{ + if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_QUATERNION])) + quaternion2bytestream(stream, address, value); +} + +inline S32 lscript_local_get(U8 *stream, S32 address) +{ + if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_INTEGER])) + return bytestream2integer(stream, address); + return 0; +} + +inline void lscript_local_get(U8 *stream, S32 address, F32 &value) +{ + if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_FLOATINGPOINT])) + value = bytestream2float(stream, address); + if (!llfinite(value)) + { + value = 0; + set_fault(stream, LSRF_MATH); + } +} + +inline void lscript_local_get(U8 *stream, S32 address, LLVector3 &value) +{ + if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_VECTOR])) + bytestream2vector(value, stream, address); +} + +inline void lscript_local_get(U8 *stream, S32 address, LLQuaternion &value) +{ + if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_QUATERNION])) + bytestream2quaternion(value, stream, address); +} + +inline S32 lscript_global_get(U8 *stream, S32 address) +{ + if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_INTEGER])) + return bytestream2integer(stream, address); + return 0; +} + +inline void lscript_global_get(U8 *stream, S32 address, F32 &value) +{ + if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_FLOATINGPOINT])) + value = bytestream2float(stream, address); + if (!llfinite(value)) + { + value = 0; + set_fault(stream, LSRF_MATH); + } +} + +inline void lscript_global_get(U8 *stream, S32 address, LLVector3 &value) +{ + if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_VECTOR])) + bytestream2vector(value, stream, address); +} + +inline void lscript_global_get(U8 *stream, S32 address, LLQuaternion &value) +{ + if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_QUATERNION])) + bytestream2quaternion(value, stream, address); +} + + + +inline S32 get_state_event_opcoode_start(U8 *stream, S32 state, LSCRIPTStateEventType event) +{ + // get the start of the state table + S32 sr = get_register(stream, LREG_SR); + + // get the position of the jump to the desired state + S32 value = get_register(stream, LREG_VN); + + S32 state_offset_offset = 0; + S32 major_version = 0; + if (value == LSL2_VERSION1_END_NUMBER) + { + major_version = LSL2_MAJOR_VERSION_ONE; + state_offset_offset = sr + LSCRIPTDataSize[LST_INTEGER] + LSCRIPTDataSize[LST_INTEGER]*2*state; + } + else if (value == LSL2_VERSION_NUMBER) + { + major_version = LSL2_MAJOR_VERSION_TWO; + state_offset_offset = sr + LSCRIPTDataSize[LST_INTEGER] + LSCRIPTDataSize[LST_INTEGER]*3*state; + } + + // get the actual position in memory of the desired state + S32 state_offset = sr + bytestream2integer(stream, state_offset_offset); + + // save that value + S32 state_offset_base = state_offset; + + // jump past the state name + S32 event_jump_offset = state_offset_base + bytestream2integer(stream, state_offset); + + // get the location of the event offset + S32 event_offset = event_jump_offset + LSCRIPTDataSize[LST_INTEGER]*2*get_event_handler_jump_position(get_event_register(stream, LREG_ER, major_version), event); + + // now, jump to the event + S32 event_start = bytestream2integer(stream, event_offset); + event_start += event_jump_offset; + + S32 event_start_original = event_start; + + // now skip past the parameters + S32 opcode_offset = bytestream2integer(stream, event_start); + return opcode_offset + event_start_original; +} + +inline U64 get_handled_events(U8 *stream, S32 state) +{ + U64 retvalue = 0; + // get the start of the state table + S32 sr = get_register(stream, LREG_SR); + + // get the position of the jump to the desired state + S32 value = get_register(stream, LREG_VN); + S32 state_handled_offset = 0; + if (value == LSL2_VERSION1_END_NUMBER) + { + state_handled_offset = sr + LSCRIPTDataSize[LST_INTEGER]*2*state + 2*LSCRIPTDataSize[LST_INTEGER]; + retvalue = bytestream2integer(stream, state_handled_offset); + } + else if (value == LSL2_VERSION_NUMBER) + { + state_handled_offset = sr + LSCRIPTDataSize[LST_INTEGER]*3*state + 2*LSCRIPTDataSize[LST_INTEGER]; + retvalue = bytestream2u64(stream, state_handled_offset); + } + + // get the handled events + return retvalue; +} + +inline S32 get_event_stack_size(U8 *stream, S32 state, LSCRIPTStateEventType event) +{ + // get the start of the state table + S32 sr = get_register(stream, LREG_SR); + + // get state offset + S32 value = get_register(stream, LREG_VN); + S32 state_offset_offset = 0; + S32 major_version = 0; + if (value == LSL2_VERSION1_END_NUMBER) + { + major_version = LSL2_MAJOR_VERSION_ONE; + state_offset_offset = sr + LSCRIPTDataSize[LST_INTEGER] + LSCRIPTDataSize[LST_INTEGER]*2*state; + } + else if (value == LSL2_VERSION_NUMBER) + { + major_version = LSL2_MAJOR_VERSION_TWO; + state_offset_offset = sr + LSCRIPTDataSize[LST_INTEGER] + LSCRIPTDataSize[LST_INTEGER]*3*state; + } + + S32 state_offset = bytestream2integer(stream, state_offset_offset); + state_offset += sr; + + state_offset_offset = state_offset; + + // skip to jump table + S32 jump_table = bytestream2integer(stream, state_offset_offset); + + jump_table += state_offset; + + // get the position of the jump to the desired state + S32 stack_size_offset = jump_table + LSCRIPTDataSize[LST_INTEGER]*2*get_event_handler_jump_position(get_event_register(stream, LREG_ER, major_version), event) + LSCRIPTDataSize[LST_INTEGER]; + + // get the handled events + S32 stack_size = bytestream2integer(stream, stack_size_offset); + return stack_size; +} + +inline LSCRIPTStateEventType return_first_event(S32 event) +{ + S32 count = 1; + while (count < LSTT_EOF) + { + if (event & 0x1) + { + return (LSCRIPTStateEventType) count; + } + else + { + event >>= 1; + count++; + } + } + return LSTT_NULL; +} + + +// the safe instruction versions of these commands will only work if offset is between +// GFR and HR, meaning that it is an instruction (more or less) in global functions or event handlers + +inline BOOL safe_instruction_check_address(U8 *stream, S32 offset, S32 size) +{ + S32 gfr = get_register(stream, LREG_GFR); + if (offset < gfr) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + else + { + S32 hr = get_register(stream, LREG_HR); + if (offset + size > hr) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + else + { + return TRUE; + } + } +} + +inline BOOL safe_heap_check_address(U8 *stream, S32 offset, S32 size) +{ + S32 hr = get_register(stream, LREG_HR); + if (offset < hr) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + else + { + S32 hp = get_register(stream, LREG_HP); + if (offset + size > hp) + { + set_fault(stream, LSRF_BOUND_CHECK_ERROR); + return FALSE; + } + else + { + return TRUE; + } + } +} + +inline U8 safe_instruction_bytestream2byte(U8 *stream, S32 &offset) +{ + if (safe_instruction_check_address(stream, offset, 1)) + { + return *(stream + offset++); + } + else + { + return 0; + } +} + +inline void safe_instruction_byte2bytestream(U8 *stream, S32 &offset, U8 byte) +{ + if (safe_instruction_check_address(stream, offset, 1)) + { + *(stream + offset++) = byte; + } +} + +inline S32 safe_instruction_bytestream2integer(U8 *stream, S32 &offset) +{ + if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_INTEGER])) + { + return (bytestream2integer(stream, offset)); + } + else + { + return 0; + } +} + +inline void safe_instruction_integer2bytestream(U8 *stream, S32 &offset, S32 value) +{ + if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_INTEGER])) + { + integer2bytestream(stream, offset, value); + } +} + +inline U16 safe_instruction_bytestream2u16(U8 *stream, S32 &offset) +{ + if (safe_instruction_check_address(stream, offset, 2)) + { + return (bytestream2u16(stream, offset)); + } + else + { + return 0; + } +} + +inline void safe_instruction_u162bytestream(U8 *stream, S32 &offset, U16 value) +{ + if (safe_instruction_check_address(stream, offset, 2)) + { + u162bytestream(stream, offset, value); + } +} + +inline F32 safe_instruction_bytestream2float(U8 *stream, S32 &offset) +{ + if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_INTEGER])) + { + F32 value = bytestream2float(stream, offset); + if (!llfinite(value)) + { + value = 0; + set_fault(stream, LSRF_MATH); + } + return value; + } + else + { + return 0; + } +} + +inline void safe_instruction_float2bytestream(U8 *stream, S32 &offset, F32 value) +{ + if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_FLOATINGPOINT])) + { + float2bytestream(stream, offset, value); + } +} + +inline void safe_instruction_bytestream2char(char *buffer, U8 *stream, S32 &offset) +{ + while ( (safe_instruction_check_address(stream, offset, 1)) + &&(*buffer++ = *(stream + offset++))) + ; +} + +inline void safe_instruction_bytestream_count_char(U8 *stream, S32 &offset) +{ + while ( (safe_instruction_check_address(stream, offset, 1)) + &&(*(stream + offset++))) + ; +} + +inline void safe_heap_bytestream_count_char(U8 *stream, S32 &offset) +{ + while ( (safe_heap_check_address(stream, offset, 1)) + &&(*(stream + offset++))) + ; +} + +inline void safe_instruction_char2bytestream(U8 *stream, S32 &offset, char *buffer) +{ + while ( (safe_instruction_check_address(stream, offset, 1)) + &&(*(stream + offset++) = *buffer++)) + ; +} + +inline void safe_instruction_bytestream2vector(LLVector3 &value, U8 *stream, S32 &offset) +{ + if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_VECTOR])) + { + bytestream2vector(value, stream, offset); + } +} + +inline void safe_instruction_vector2bytestream(U8 *stream, S32 &offset, LLVector3 &value) +{ + if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_VECTOR])) + { + vector2bytestream(stream, offset, value); + } +} + +inline void safe_instruction_bytestream2quaternion(LLQuaternion &value, U8 *stream, S32 &offset) +{ + if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_QUATERNION])) + { + bytestream2quaternion(value, stream, offset); + } +} + +inline void safe_instruction_quaternion2bytestream(U8 *stream, S32 &offset, LLQuaternion &value) +{ + if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_QUATERNION])) + { + quaternion2bytestream(stream, offset, value); + } +} + +static inline LSCRIPTType char2type(char type) +{ + switch(type) + { + case 'i': + return LST_INTEGER; + case 'f': + return LST_FLOATINGPOINT; + case 's': + return LST_STRING; + case 'k': + return LST_KEY; + case 'v': + return LST_VECTOR; + case 'q': + return LST_QUATERNION; + case 'l': + return LST_LIST; + default: + return LST_NULL; + } +} + +#endif |