summaryrefslogtreecommitdiff
path: root/indra/lscript/lscript_byteconvert.h
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/lscript/lscript_byteconvert.h
Print done when done.
Diffstat (limited to 'indra/lscript/lscript_byteconvert.h')
-rw-r--r--indra/lscript/lscript_byteconvert.h1087
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