PageRenderTime 100ms CodeModel.GetById 13ms app.highlight 80ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/lscript/lscript_byteconvert.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 1170 lines | 962 code | 140 blank | 68 comment | 126 complexity | f6e8fa6c8be9e8e85a7ca9f978b3d22d MD5 | raw file
   1/** 
   2 * @file lscript_byteconvert.h
   3 * @brief Shared code for compiler and assembler for LSL
   4 *
   5 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27// data shared between compiler/assembler
  28// used to convert data between byte stream and outside data types
  29
  30#ifndef LL_LSCRIPT_BYTECONVERT_H
  31#define LL_LSCRIPT_BYTECONVERT_H
  32
  33#include "stdtypes.h"
  34#include "v3math.h"
  35#include "llquaternion.h"
  36#include "lscript_byteformat.h"
  37#include "lluuid.h"
  38
  39void reset_hp_to_safe_spot(const U8 *buffer);
  40
  41// remember that LScript byte stream is BigEndian
  42void set_fault(const U8 *stream, LSCRIPTRunTimeFaults fault);
  43
  44inline S32 bytestream2integer(const U8 *stream, S32 &offset)
  45{
  46	stream += offset;
  47	offset += 4;
  48	return (*stream<<24) | (*(stream + 1)<<16) | (*(stream + 2)<<8) | *(stream + 3);
  49}
  50
  51inline U32 bytestream2unsigned_integer(const U8 *stream, S32 &offset)
  52{
  53	stream += offset;
  54	offset += 4;
  55	return (*stream<<24) | (*(stream + 1)<<16) | (*(stream + 2)<<8) | *(stream + 3);
  56}
  57
  58inline U64 bytestream2u64(const U8 *stream, S32 &offset)
  59{
  60	stream += offset;
  61	offset += 8;
  62	return ((U64)(*stream)<<56)| ((U64)(*(stream + 1))<<48) | ((U64)(*(stream + 2))<<40) | ((U64)(*(stream + 3))<<32) | 
  63		   ((U64)(*(stream + 4))<<24) | ((U64)(*(stream + 5))<<16) | ((U64)(*(stream + 6))<<8) | (U64)(*(stream + 7));
  64}
  65
  66inline void integer2bytestream(U8 *stream, S32 &offset, S32 integer)
  67{
  68	stream += offset;
  69	offset += 4;
  70	*(stream)	= (integer >> 24);
  71	*(stream + 1)	= (integer >> 16) & 0xff;
  72	*(stream + 2)	= (integer >> 8) & 0xff;
  73	*(stream + 3)	= (integer) & 0xff;
  74}
  75
  76inline void unsigned_integer2bytestream(U8 *stream, S32 &offset, U32 integer)
  77{
  78	stream += offset;
  79	offset += 4;
  80	*(stream)	= (integer >> 24);
  81	*(stream + 1)	= (integer >> 16) & 0xff;
  82	*(stream + 2)	= (integer >> 8) & 0xff;
  83	*(stream + 3)	= (integer) & 0xff;
  84}
  85inline void u642bytestream(U8 *stream, S32 &offset, U64 integer)
  86{
  87	stream += offset;
  88	offset += 8;
  89	*(stream)		= (U8)(integer >> 56);
  90	*(stream + 1)	= (U8)((integer >> 48) & 0xff);
  91	*(stream + 2)	= (U8)((integer >> 40) & 0xff);
  92	*(stream + 3)	= (U8)((integer >> 32) & 0xff);
  93	*(stream + 4)	= (U8)((integer >> 24) & 0xff);
  94	*(stream + 5)	= (U8)((integer >> 16) & 0xff);
  95	*(stream + 6)	= (U8)((integer >> 8) & 0xff);
  96	*(stream + 7)	= (U8)((integer) & 0xff);
  97}
  98
  99inline S16 bytestream2s16(const U8 *stream, S32 &offset)
 100{
 101	stream += offset;
 102	offset += 2;
 103	return (*stream<<8) | *(stream + 1);
 104}
 105
 106inline void s162bytestream(U8 *stream, S32 &offset, S16 integer)
 107{
 108	stream += offset;
 109	offset += 2;
 110	*(stream)		= (integer >> 8);
 111	*(stream + 1)	= (integer) & 0xff;
 112}
 113
 114inline U16 bytestream2u16(const U8 *stream, S32 &offset)
 115{
 116	stream += offset;
 117	offset += 2;
 118	return (*stream<<8) | *(stream + 1);
 119}
 120
 121inline void u162bytestream(U8 *stream, S32 &offset, U16 integer)
 122{
 123	stream += offset;
 124	offset += 2;
 125	*(stream)		= (integer >> 8);
 126	*(stream + 1)	= (integer) & 0xff;
 127}
 128
 129inline F32 bytestream2float(const U8 *stream, S32 &offset)
 130{
 131	S32 value = bytestream2integer(stream, offset);
 132	F32 fpvalue = *(F32 *)&value;
 133	if (!llfinite(fpvalue))
 134	{
 135		fpvalue = 0;
 136		set_fault(stream, LSRF_MATH);
 137	}
 138	return fpvalue;
 139}
 140
 141inline void float2bytestream(U8 *stream, S32 &offset, F32 floatingpoint)
 142{
 143	S32 value = *(S32 *)&floatingpoint;
 144	integer2bytestream(stream, offset, value);
 145}
 146
 147inline void bytestream_int2float(U8 *stream, S32 &offset)
 148{
 149	S32 value = bytestream2integer(stream, offset);
 150	offset -= 4;
 151	F32 fpvalue = (F32)value;
 152	if (!llfinite(fpvalue))
 153	{
 154		fpvalue = 0;
 155		set_fault(stream, LSRF_MATH);
 156	}
 157	float2bytestream(stream, offset, fpvalue);
 158}
 159
 160// Returns true on success, return false and clip copy on buffer overflow
 161inline bool bytestream2char(char *buffer, const U8 *stream, S32 &offset, S32 buffsize)
 162{
 163	S32 source_len = strlen( (const char *)stream+offset );
 164	S32 copy_len = buffsize - 1;
 165	if( copy_len > source_len )
 166	{
 167		copy_len = source_len;
 168	}
 169
 170	// strncpy without \0 padding overhead
 171	memcpy( buffer, stream+offset, copy_len );
 172	buffer[copy_len] = 0;
 173
 174	offset += source_len + 1; // advance past source string, include terminating '\0'
 175
 176	return source_len < buffsize;
 177}
 178
 179inline void char2bytestream(U8 *stream, S32 &offset, const char *buffer)
 180{
 181	while ((*(stream + offset++) = *buffer++))
 182		;
 183}
 184
 185inline U8 bytestream2byte(const U8 *stream, S32 &offset)
 186{
 187	return *(stream + offset++);
 188}
 189
 190inline void byte2bytestream(U8 *stream, S32 &offset, U8 byte)
 191{
 192	*(stream + offset++) = byte;
 193}
 194
 195inline void bytestream2bytestream(U8 *dest, S32 &dest_offset, const U8 *src, S32 &src_offset, S32 count)
 196{
 197	while (count)
 198	{
 199		(*(dest + dest_offset++)) = (*(src + src_offset++));
 200		count--;
 201	}
 202}
 203
 204inline void uuid2bytestream(U8 *stream, S32 &offset, const LLUUID &uuid)
 205{
 206	S32 i;
 207	for (i = 0; i < UUID_BYTES; i++)
 208	{
 209		*(stream + offset++) = uuid.mData[i];
 210	}
 211}
 212
 213inline void bytestream2uuid(U8 *stream, S32 &offset, LLUUID &uuid)
 214{
 215	S32 i;
 216	for (i = 0; i < UUID_BYTES; i++)
 217	{
 218		uuid.mData[i] = *(stream + offset++);
 219	}
 220}
 221
 222// vectors and quaternions and encoded in backwards order to match the way in which they are stored on the stack
 223inline void bytestream2vector(LLVector3 &vector, const U8 *stream, S32 &offset)
 224{
 225	S32 value = bytestream2integer(stream, offset);
 226	vector.mV[VZ] = *(F32 *)&value;
 227	if (!llfinite(vector.mV[VZ]))
 228	{
 229		vector.mV[VZ] = 0;
 230		set_fault(stream, LSRF_MATH);
 231	}
 232	value = bytestream2integer(stream, offset);
 233	vector.mV[VY] = *(F32 *)&value;
 234	if (!llfinite(vector.mV[VY]))
 235	{
 236		vector.mV[VY] = 0;
 237		set_fault(stream, LSRF_MATH);
 238	}
 239	value = bytestream2integer(stream, offset);
 240	vector.mV[VX] = *(F32 *)&value;
 241	if (!llfinite(vector.mV[VX]))
 242	{
 243		vector.mV[VX] = 0;
 244		set_fault(stream, LSRF_MATH);
 245	}
 246}
 247
 248inline void vector2bytestream(U8 *stream, S32 &offset, const LLVector3 &vector)
 249{
 250	S32 value = *(S32 *)&vector.mV[VZ];
 251	integer2bytestream(stream, offset, value);
 252	value = *(S32 *)&vector.mV[VY];
 253	integer2bytestream(stream, offset, value);
 254	value = *(S32 *)&vector.mV[VX];
 255	integer2bytestream(stream, offset, value);
 256}
 257
 258inline void bytestream2quaternion(LLQuaternion &quat, const U8 *stream, S32 &offset)
 259{
 260	S32 value = bytestream2integer(stream, offset);
 261	quat.mQ[VS] = *(F32 *)&value;
 262	if (!llfinite(quat.mQ[VS]))
 263	{
 264		quat.mQ[VS] = 0;
 265		set_fault(stream, LSRF_MATH);
 266	}
 267	value = bytestream2integer(stream, offset);
 268	quat.mQ[VZ] = *(F32 *)&value;
 269	if (!llfinite(quat.mQ[VZ]))
 270	{
 271		quat.mQ[VZ] = 0;
 272		set_fault(stream, LSRF_MATH);
 273	}
 274	value = bytestream2integer(stream, offset);
 275	quat.mQ[VY] = *(F32 *)&value;
 276	if (!llfinite(quat.mQ[VY]))
 277	{
 278		quat.mQ[VY] = 0;
 279		set_fault(stream, LSRF_MATH);
 280	}
 281	value = bytestream2integer(stream, offset);
 282	quat.mQ[VX] = *(F32 *)&value;
 283	if (!llfinite(quat.mQ[VX]))
 284	{
 285		quat.mQ[VX] = 0;
 286		set_fault(stream, LSRF_MATH);
 287	}
 288}
 289
 290inline void quaternion2bytestream(U8 *stream, S32 &offset, const LLQuaternion &quat)
 291{
 292	S32 value = *(S32 *)&quat.mQ[VS];
 293	integer2bytestream(stream, offset, value);
 294	value = *(S32 *)&quat.mQ[VZ];
 295	integer2bytestream(stream, offset, value);
 296	value = *(S32 *)&quat.mQ[VY];
 297	integer2bytestream(stream, offset, value);
 298	value = *(S32 *)&quat.mQ[VX];
 299	integer2bytestream(stream, offset, value);
 300}
 301
 302inline S32 get_register(const U8 *stream, LSCRIPTRegisters reg)
 303{
 304	S32 offset = gLSCRIPTRegisterAddresses[reg];
 305	return bytestream2integer(stream, offset);
 306}
 307
 308inline F32 get_register_fp(U8 *stream, LSCRIPTRegisters reg)
 309{
 310	S32 offset = gLSCRIPTRegisterAddresses[reg];
 311	F32 value = bytestream2float(stream, offset);
 312	if (!llfinite(value))
 313	{
 314		value = 0;
 315		set_fault(stream, LSRF_MATH);
 316	}
 317	return value;
 318}
 319inline U64 get_register_u64(U8 *stream, LSCRIPTRegisters reg)
 320{
 321	S32 offset = gLSCRIPTRegisterAddresses[reg];
 322	return bytestream2u64(stream, offset);
 323}
 324
 325inline U64 get_event_register(U8 *stream, LSCRIPTRegisters reg, S32 major_version)
 326{
 327	if (major_version == 1)
 328	{
 329		S32 offset = gLSCRIPTRegisterAddresses[reg];
 330		return (U64)bytestream2integer(stream, offset);
 331	}
 332	else if (major_version == 2)
 333	{
 334		S32 offset = gLSCRIPTRegisterAddresses[reg + (LREG_NCE - LREG_CE)];
 335		return bytestream2u64(stream, offset);
 336	}
 337	else
 338	{
 339		S32 offset = gLSCRIPTRegisterAddresses[reg];
 340		return (U64)bytestream2integer(stream, offset);
 341	}
 342}
 343
 344inline void set_register(U8 *stream, LSCRIPTRegisters reg, S32 value)
 345{
 346	S32 offset = gLSCRIPTRegisterAddresses[reg];
 347	integer2bytestream(stream, offset, value);
 348}
 349
 350inline void set_register_fp(U8 *stream, LSCRIPTRegisters reg, F32 value)
 351{
 352	S32 offset = gLSCRIPTRegisterAddresses[reg];
 353	float2bytestream(stream, offset, value);
 354}
 355
 356inline void set_register_u64(U8 *stream, LSCRIPTRegisters reg, U64 value)
 357{
 358	S32 offset = gLSCRIPTRegisterAddresses[reg];
 359	u642bytestream(stream, offset, value);
 360}
 361
 362inline void set_event_register(U8 *stream, LSCRIPTRegisters reg, U64 value, S32 major_version)
 363{
 364	if (major_version == 1)
 365	{
 366		S32 offset = gLSCRIPTRegisterAddresses[reg];
 367		integer2bytestream(stream, offset, (S32)value);
 368	}
 369	else if (major_version == 2)
 370	{
 371		S32 offset = gLSCRIPTRegisterAddresses[reg + (LREG_NCE - LREG_CE)];
 372		u642bytestream(stream, offset, value);
 373	}
 374	else
 375	{
 376		S32 offset = gLSCRIPTRegisterAddresses[reg];
 377		integer2bytestream(stream, offset, (S32)value);
 378	}
 379}
 380
 381
 382inline F32 add_register_fp(U8 *stream, LSCRIPTRegisters reg, F32 value)
 383{
 384	S32 offset = gLSCRIPTRegisterAddresses[reg];
 385	F32 newvalue = bytestream2float(stream, offset);
 386	newvalue += value;
 387	if (!llfinite(newvalue))
 388	{
 389		newvalue = 0;
 390		set_fault(stream, LSRF_MATH);
 391	}
 392	offset = gLSCRIPTRegisterAddresses[reg];
 393	float2bytestream(stream, offset, newvalue);
 394	return newvalue;
 395}
 396
 397void lsa_print_heap(U8 *buffer);
 398
 399
 400inline void set_fault(const U8 *stream, LSCRIPTRunTimeFaults fault)
 401{
 402   S32 fr = get_register(stream, LREG_FR);
 403   // record the first error
 404   if (!fr)
 405   {
 406	   if (  (fault == LSRF_HEAP_ERROR)
 407		   ||(fault == LSRF_STACK_HEAP_COLLISION)
 408		   ||(fault == LSRF_BOUND_CHECK_ERROR))
 409	   {
 410			reset_hp_to_safe_spot(stream);
 411//		    lsa_print_heap((U8 *)stream);
 412	   }
 413       fr = fault;
 414       set_register((U8 *)stream, LREG_FR, fr);
 415   }
 416}
 417
 418inline BOOL set_ip(U8 *stream, S32 ip)
 419{
 420	// Verify that the Instruction Pointer is in a valid
 421	// code area (between the Global Function Register
 422	// and Heap Register).
 423	S32 gfr = get_register(stream, LREG_GFR);
 424	if (ip == 0)
 425	{
 426		set_register(stream, LREG_IP, ip);
 427		return TRUE;
 428	}
 429	if (ip < gfr)
 430	{
 431		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 432		return FALSE;
 433	}
 434	S32 hr = get_register(stream, LREG_HR);
 435	if (ip >= hr)
 436	{
 437		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 438		return FALSE;
 439	}
 440	set_register(stream, LREG_IP, ip);
 441	return TRUE;
 442}
 443
 444inline BOOL set_bp(U8 *stream, S32 bp)
 445{
 446	// Verify that the Base Pointer is in a valid
 447	// data area (between the Heap Pointer and
 448	// the Top of Memory, and below the
 449	// Stack Pointer).
 450	S32 hp = get_register(stream, LREG_HP);
 451	if (bp <= hp)
 452	{
 453		set_fault(stream, LSRF_STACK_HEAP_COLLISION);
 454		return FALSE;
 455	}
 456	S32 tm = get_register(stream, LREG_TM);
 457	if (bp >= tm)
 458	{
 459		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 460		return FALSE;
 461	}
 462	S32 sp = get_register(stream, LREG_SP);
 463	if (bp < sp)
 464	{
 465		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 466		return FALSE;
 467	}
 468	set_register(stream, LREG_BP, bp);
 469	return TRUE;
 470}
 471
 472inline BOOL set_sp(U8 *stream, S32 sp)
 473{
 474	// Verify that the Stack Pointer is in a valid
 475	// data area (between the Heap Pointer and
 476	// the Top of Memory).
 477	S32 hp = get_register(stream, LREG_HP);
 478	if (sp <= hp)
 479	{
 480		set_fault(stream, LSRF_STACK_HEAP_COLLISION);
 481		return FALSE;
 482	}
 483	S32 tm = get_register(stream, LREG_TM);
 484	if (sp >= tm)
 485	{
 486		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 487		return FALSE;
 488	}
 489	set_register(stream, LREG_SP, sp);
 490	return TRUE;
 491}
 492
 493inline void lscript_push(U8 *stream, U8 value)
 494{
 495	S32 sp = get_register(stream, LREG_SP);
 496	sp -= 1;
 497
 498	if (set_sp(stream, sp))
 499	{
 500		*(stream + sp) = value;
 501	}
 502}
 503
 504inline void lscript_push(U8 *stream, S32 value)
 505{
 506	S32 sp = get_register(stream, LREG_SP);
 507	sp -= LSCRIPTDataSize[LST_INTEGER];
 508
 509	if (set_sp(stream, sp))
 510	{
 511		integer2bytestream(stream, sp, value);
 512	}
 513}
 514
 515inline void lscript_push(U8 *stream, F32 value)
 516{
 517	S32 sp = get_register(stream, LREG_SP);
 518	sp -= LSCRIPTDataSize[LST_FLOATINGPOINT];
 519
 520	if (set_sp(stream, sp))
 521	{
 522		float2bytestream(stream, sp, value);
 523	}
 524}
 525
 526inline void lscript_push(U8 *stream, const LLVector3 &value)
 527{
 528	S32 sp = get_register(stream, LREG_SP);
 529	sp -= LSCRIPTDataSize[LST_VECTOR];
 530
 531	if (set_sp(stream, sp))
 532	{
 533		vector2bytestream(stream, sp, value);
 534	}
 535}
 536
 537inline void lscript_push(U8 *stream, const LLQuaternion &value)
 538{
 539	S32 sp = get_register(stream, LREG_SP);
 540	sp -= LSCRIPTDataSize[LST_QUATERNION];
 541
 542	if (set_sp(stream, sp))
 543	{
 544		quaternion2bytestream(stream, sp, value);
 545	}
 546}
 547
 548inline void lscript_pusharg(U8 *stream, S32 arg)
 549{
 550	S32 sp = get_register(stream, LREG_SP);
 551	sp -= arg;
 552
 553	set_sp(stream, sp);
 554}
 555
 556inline void lscript_poparg(U8 *stream, S32 arg)
 557{
 558	S32 sp = get_register(stream, LREG_SP);
 559	sp += arg;
 560
 561	set_sp(stream, sp);
 562}
 563
 564inline U8 lscript_pop_char(U8 *stream)
 565{
 566	S32 sp = get_register(stream, LREG_SP);
 567	U8 value = *(stream + sp++);
 568	set_sp(stream, sp);
 569	return value;
 570}
 571
 572inline S32 lscript_pop_int(U8 *stream)
 573{
 574	S32 sp = get_register(stream, LREG_SP);
 575	S32 value = bytestream2integer(stream, sp);
 576	set_sp(stream, sp);
 577	return value;
 578}
 579
 580inline F32 lscript_pop_float(U8 *stream)
 581{
 582	S32 sp = get_register(stream, LREG_SP);
 583	F32 value = bytestream2float(stream, sp);
 584	if (!llfinite(value))
 585	{
 586		value = 0;
 587		set_fault(stream, LSRF_MATH);
 588	}
 589	set_sp(stream, sp);
 590	return value;
 591}
 592
 593inline void lscript_pop_vector(U8 *stream, LLVector3 &value)
 594{
 595	S32 sp = get_register(stream, LREG_SP);
 596	bytestream2vector(value, stream, sp);
 597	set_sp(stream, sp);
 598}
 599
 600inline void lscript_pop_quaternion(U8 *stream, LLQuaternion &value)
 601{
 602	S32 sp = get_register(stream, LREG_SP);
 603	bytestream2quaternion(value, stream, sp);
 604	set_sp(stream, sp);
 605}
 606
 607inline void lscript_pusharge(U8 *stream, S32 value)
 608{
 609	S32 sp = get_register(stream, LREG_SP);
 610	sp -= value;
 611	if (set_sp(stream, sp))
 612	{
 613		S32 i;
 614		for (i = 0; i < value; i++)
 615		{
 616			*(stream + sp++) = 0;
 617		}
 618	}
 619}
 620
 621inline BOOL lscript_check_local(U8 *stream, S32 &address, S32 size)
 622{
 623	S32 sp = get_register(stream, LREG_SP);
 624	S32 bp = get_register(stream, LREG_BP);
 625
 626	address += size;
 627	address = bp - address;
 628
 629	if (address < sp - size)
 630	{
 631		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 632		return FALSE;
 633	}
 634	S32 tm = get_register(stream, LREG_TM);
 635	if (address + size > tm)
 636	{
 637		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 638		return FALSE;
 639	}
 640	return TRUE;
 641}
 642
 643inline BOOL lscript_check_global(U8 *stream, S32 &address, S32 size)
 644{
 645	S32 gvr = get_register(stream, LREG_GVR);
 646
 647	// Possibility of overwriting registers?  -- DK 09/07/04
 648	if (address < 0)
 649	{
 650		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 651		return FALSE;
 652	}
 653
 654	address += gvr;
 655	S32 gfr = get_register(stream, LREG_GFR);
 656
 657	if (address + size > gfr)
 658	{
 659		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 660		return FALSE;
 661	}
 662	return TRUE;
 663}
 664
 665inline void lscript_local_store(U8 *stream, S32 address, S32 value)
 666{
 667	if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_INTEGER]))
 668		integer2bytestream(stream, address, value);
 669}
 670
 671inline void lscript_local_store(U8 *stream, S32 address, F32 value)
 672{
 673	if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_FLOATINGPOINT]))
 674		float2bytestream(stream, address, value);
 675}
 676
 677inline void lscript_local_store(U8 *stream, S32 address, const LLVector3 value)
 678{
 679	if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_VECTOR]))
 680		vector2bytestream(stream, address, value);
 681}
 682
 683inline void lscript_local_store(U8 *stream, S32 address, const LLQuaternion value)
 684{
 685	if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_QUATERNION]))
 686		quaternion2bytestream(stream, address, value);
 687}
 688
 689inline void lscript_global_store(U8 *stream, S32 address, S32 value)
 690{
 691	if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_INTEGER]))
 692		integer2bytestream(stream, address, value);
 693}
 694
 695inline void lscript_global_store(U8 *stream, S32 address, F32 value)
 696{
 697	if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_FLOATINGPOINT]))
 698		float2bytestream(stream, address, value);
 699}
 700
 701inline void lscript_global_store(U8 *stream, S32 address, const LLVector3 value)
 702{
 703	if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_VECTOR]))
 704		vector2bytestream(stream, address, value);
 705}
 706
 707inline void lscript_global_store(U8 *stream, S32 address, const LLQuaternion value)
 708{
 709	if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_QUATERNION]))
 710		quaternion2bytestream(stream, address, value);
 711}
 712
 713inline S32 lscript_local_get(U8 *stream, S32 address)
 714{
 715	if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_INTEGER]))
 716		return bytestream2integer(stream, address);
 717	return 0;
 718}
 719
 720inline void lscript_local_get(U8 *stream, S32 address, F32 &value)
 721{
 722	if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_FLOATINGPOINT]))
 723		value = bytestream2float(stream, address);
 724	if (!llfinite(value))
 725	{
 726		value = 0;
 727		set_fault(stream, LSRF_MATH);
 728	}
 729}
 730
 731inline void lscript_local_get(U8 *stream, S32 address, LLVector3 &value)
 732{
 733	if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_VECTOR]))
 734		bytestream2vector(value, stream, address);
 735}
 736
 737inline void lscript_local_get(U8 *stream, S32 address, LLQuaternion &value)
 738{
 739	if (lscript_check_local(stream, address, LSCRIPTDataSize[LST_QUATERNION]))
 740		bytestream2quaternion(value, stream, address);
 741}
 742
 743inline S32 lscript_global_get(U8 *stream, S32 address)
 744{
 745	if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_INTEGER]))
 746		return bytestream2integer(stream, address);
 747	return 0;
 748}
 749
 750inline void lscript_global_get(U8 *stream, S32 address, F32 &value)
 751{
 752	if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_FLOATINGPOINT]))
 753		value = bytestream2float(stream, address);
 754	if (!llfinite(value))
 755	{
 756		value = 0;
 757		set_fault(stream, LSRF_MATH);
 758	}
 759}
 760
 761inline void lscript_global_get(U8 *stream, S32 address, LLVector3 &value)
 762{
 763	if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_VECTOR]))
 764		bytestream2vector(value, stream, address);
 765}
 766
 767inline void lscript_global_get(U8 *stream, S32 address, LLQuaternion &value)
 768{
 769	if (lscript_check_global(stream, address, LSCRIPTDataSize[LST_QUATERNION]))
 770		bytestream2quaternion(value, stream, address);
 771}
 772
 773
 774
 775inline S32 get_state_event_opcoode_start(U8 *stream, S32 state, LSCRIPTStateEventType event)
 776{
 777	// get the start of the state table
 778	S32 sr = get_register(stream, LREG_SR);
 779
 780	// get the position of the jump to the desired state
 781	S32 value = get_register(stream, LREG_VN);
 782
 783	S32 state_offset_offset = 0;
 784	S32 major_version = 0;
 785	if (value == LSL2_VERSION1_END_NUMBER)
 786	{
 787		major_version = LSL2_MAJOR_VERSION_ONE;
 788		state_offset_offset = sr + LSCRIPTDataSize[LST_INTEGER] + LSCRIPTDataSize[LST_INTEGER]*2*state;
 789	}
 790	else if (value == LSL2_VERSION_NUMBER)
 791	{
 792		major_version = LSL2_MAJOR_VERSION_TWO;
 793		state_offset_offset = sr + LSCRIPTDataSize[LST_INTEGER] + LSCRIPTDataSize[LST_INTEGER]*3*state;
 794	}
 795	if ( state_offset_offset < 0 || state_offset_offset > TOP_OF_MEMORY )
 796	{
 797		return -1;
 798	}
 799
 800	// get the actual position in memory of the desired state
 801	S32 state_offset = sr + bytestream2integer(stream, state_offset_offset);
 802	if ( state_offset < 0 || state_offset > TOP_OF_MEMORY )
 803	{
 804		return -1;
 805	}
 806
 807	// save that value
 808	S32 state_offset_base = state_offset;
 809
 810	// jump past the state name
 811	S32 event_jump_offset = state_offset_base + bytestream2integer(stream, state_offset);
 812
 813	// get the location of the event offset
 814	S32 event_offset = event_jump_offset + LSCRIPTDataSize[LST_INTEGER]*2*get_event_handler_jump_position(get_event_register(stream, LREG_ER, major_version), event);
 815	if ( event_offset < 0 || event_offset > TOP_OF_MEMORY )
 816	{
 817		return -1;
 818	}
 819
 820	// now, jump to the event
 821	S32 event_start = bytestream2integer(stream, event_offset);
 822	if ( event_start < 0 || event_start > TOP_OF_MEMORY )
 823	{
 824		return -1;
 825	}
 826	event_start += event_jump_offset;
 827
 828	S32 event_start_original = event_start;
 829
 830	// now skip past the parameters
 831	S32 opcode_offset = bytestream2integer(stream, event_start);
 832	if ( opcode_offset < 0 || opcode_offset > TOP_OF_MEMORY )
 833	{
 834		return -1;
 835	}
 836
 837	return opcode_offset + event_start_original;
 838}
 839
 840
 841inline U64 get_handled_events(U8 *stream, S32 state)
 842{
 843	U64 retvalue = 0;
 844	// get the start of the state table
 845	S32 sr = get_register(stream, LREG_SR);
 846
 847	// get the position of the jump to the desired state
 848	S32 value = get_register(stream, LREG_VN);
 849	S32 state_handled_offset = 0;
 850	if (value == LSL2_VERSION1_END_NUMBER)
 851	{
 852		state_handled_offset = sr + LSCRIPTDataSize[LST_INTEGER]*2*state + 2*LSCRIPTDataSize[LST_INTEGER];	
 853		retvalue = bytestream2integer(stream, state_handled_offset);
 854	}
 855	else if (value == LSL2_VERSION_NUMBER)
 856	{
 857		state_handled_offset = sr + LSCRIPTDataSize[LST_INTEGER]*3*state + 2*LSCRIPTDataSize[LST_INTEGER];	
 858		retvalue = bytestream2u64(stream, state_handled_offset);
 859	}
 860
 861	// get the handled events
 862	return retvalue;
 863}
 864
 865// Returns -1 on error
 866inline S32 get_event_stack_size(U8 *stream, S32 state, LSCRIPTStateEventType event)
 867{
 868	// get the start of the state table
 869	S32 sr = get_register(stream, LREG_SR);
 870
 871	// get state offset
 872	S32 value = get_register(stream, LREG_VN);
 873	S32 state_offset_offset = 0;
 874	S32 major_version = 0;
 875	if (value == LSL2_VERSION1_END_NUMBER)
 876	{
 877		major_version = LSL2_MAJOR_VERSION_ONE;
 878		state_offset_offset = sr + LSCRIPTDataSize[LST_INTEGER] + LSCRIPTDataSize[LST_INTEGER]*2*state;
 879	}
 880	else if (value == LSL2_VERSION_NUMBER)
 881	{
 882		major_version = LSL2_MAJOR_VERSION_TWO;
 883		state_offset_offset = sr + LSCRIPTDataSize[LST_INTEGER] + LSCRIPTDataSize[LST_INTEGER]*3*state;
 884	}
 885
 886	if ( state_offset_offset < 0 || state_offset_offset > TOP_OF_MEMORY )
 887	{
 888		return -1;
 889	}
 890
 891	S32 state_offset = bytestream2integer(stream, state_offset_offset);
 892	state_offset += sr;
 893
 894	state_offset_offset = state_offset;
 895	if ( state_offset_offset < 0 || state_offset_offset > TOP_OF_MEMORY )
 896	{
 897		return -1;
 898	}
 899
 900	// skip to jump table
 901	S32 jump_table = bytestream2integer(stream, state_offset_offset);
 902
 903	jump_table += state_offset;
 904	if ( jump_table < 0 || jump_table > TOP_OF_MEMORY )
 905	{
 906		return -1;
 907	}
 908
 909	// get the position of the jump to the desired state
 910	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];
 911
 912	// get the handled events
 913	S32 stack_size = bytestream2integer(stream, stack_size_offset);
 914	if ( stack_size < 0 || stack_size > TOP_OF_MEMORY )
 915	{
 916		return -1;
 917	}
 918
 919	return stack_size;
 920}
 921
 922inline LSCRIPTStateEventType return_first_event(S32 event)
 923{
 924	S32 count = 1;
 925	while (count < LSTT_EOF)
 926	{
 927		if (event & 0x1)
 928		{
 929			return (LSCRIPTStateEventType) count;
 930		}
 931		else
 932		{
 933			event >>= 1;
 934			count++;
 935		}
 936	}
 937	return LSTT_NULL;
 938}
 939
 940
 941// the safe instruction versions of these commands will only work if offset is between
 942// GFR and HR, meaning that it is an instruction (more or less) in global functions or event handlers
 943
 944inline BOOL safe_instruction_check_address(U8 *stream, S32 offset, S32 size)
 945{
 946	S32 gfr = get_register(stream, LREG_GFR);
 947	if (offset < gfr)
 948	{
 949		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 950		return FALSE;
 951	}
 952	else
 953	{
 954		S32 hr = get_register(stream, LREG_HR);
 955		if (offset + size > hr)
 956		{
 957			set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 958			return FALSE;
 959		}
 960		else
 961		{
 962			return TRUE;
 963		}
 964	}
 965}
 966
 967inline BOOL safe_heap_check_address(U8 *stream, S32 offset, S32 size)
 968{
 969	S32 hr = get_register(stream, LREG_HR);
 970	if (offset < hr)
 971	{
 972		set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 973		return FALSE;
 974	}
 975	else
 976	{
 977		S32 hp = get_register(stream, LREG_HP);
 978		if (offset + size > hp)
 979		{
 980			set_fault(stream, LSRF_BOUND_CHECK_ERROR);
 981			return FALSE;
 982		}
 983		else
 984		{
 985			return TRUE;
 986		}
 987	}
 988}
 989
 990inline U8 safe_instruction_bytestream2byte(U8 *stream, S32 &offset)
 991{
 992	if (safe_instruction_check_address(stream, offset, 1))
 993	{
 994		return *(stream + offset++);
 995	}
 996	else
 997	{
 998		return 0;
 999	}
1000}
1001
1002inline void safe_instruction_byte2bytestream(U8 *stream, S32 &offset, U8 byte)
1003{
1004	if (safe_instruction_check_address(stream, offset, 1))
1005	{
1006		*(stream + offset++) = byte;
1007	}
1008}
1009
1010inline S32 safe_instruction_bytestream2integer(U8 *stream, S32 &offset)
1011{
1012	if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_INTEGER]))
1013	{
1014		return (bytestream2integer(stream, offset));
1015	}
1016	else
1017	{
1018		return 0;
1019	}
1020}
1021
1022inline void safe_instruction_integer2bytestream(U8 *stream, S32 &offset, S32 value)
1023{
1024	if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_INTEGER]))
1025	{
1026		integer2bytestream(stream, offset, value);
1027	}
1028}
1029
1030inline U16 safe_instruction_bytestream2u16(U8 *stream, S32 &offset)
1031{
1032	if (safe_instruction_check_address(stream, offset, 2))
1033	{
1034		return (bytestream2u16(stream, offset));
1035	}
1036	else
1037	{
1038		return 0;
1039	}
1040}
1041
1042inline void safe_instruction_u162bytestream(U8 *stream, S32 &offset, U16 value)
1043{
1044	if (safe_instruction_check_address(stream, offset, 2))
1045	{
1046		u162bytestream(stream, offset, value);
1047	}
1048}
1049
1050inline F32 safe_instruction_bytestream2float(U8 *stream, S32 &offset)
1051{
1052	if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_INTEGER]))
1053	{
1054		F32 value = bytestream2float(stream, offset);
1055		if (!llfinite(value))
1056		{
1057			value = 0;
1058			set_fault(stream, LSRF_MATH);
1059		}
1060		return value;
1061	}
1062	else
1063	{
1064		return 0;
1065	}
1066}
1067
1068inline void safe_instruction_float2bytestream(U8 *stream, S32 &offset, F32 value)
1069{
1070	if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_FLOATINGPOINT]))
1071	{
1072		float2bytestream(stream, offset, value);
1073	}
1074}
1075
1076inline void safe_instruction_bytestream2char(char *buffer, U8 *stream, S32 &offset, S32 buffsize)
1077{
1078	// This varies from the old method. Previously, we would copy up until we got an error,
1079	// then halt the script via safe_isntruction_check_address. Now we don't bother
1080	// copying a thing if there's an error.
1081
1082	if( safe_instruction_check_address(stream, offset, strlen( (const char *)stream + offset ) + 1 ) )
1083	{
1084		// Takes the same parms as this function. Won't overread, per above check.
1085		bytestream2char( buffer, stream, offset, buffsize );
1086	}
1087	else
1088	{
1089		// Truncate - no point in copying
1090		*buffer = 0;
1091	}
1092}
1093
1094inline void safe_instruction_bytestream_count_char(U8 *stream, S32 &offset)
1095{
1096	while (  (safe_instruction_check_address(stream, offset, 1))
1097		   &&(*(stream + offset++)))
1098		;
1099}
1100
1101inline void safe_heap_bytestream_count_char(U8 *stream, S32 &offset)
1102{
1103	while (  (safe_heap_check_address(stream, offset, 1))
1104		   &&(*(stream + offset++)))
1105		;
1106}
1107
1108inline void safe_instruction_char2bytestream(U8 *stream, S32 &offset, const char* buffer)
1109{
1110	while (  (safe_instruction_check_address(stream, offset, 1))
1111		   &&(*(stream + offset++) = *buffer++))
1112		;
1113}
1114
1115inline void safe_instruction_bytestream2vector(LLVector3 &value, U8 *stream, S32 &offset)
1116{
1117	if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_VECTOR]))
1118	{
1119		bytestream2vector(value, stream, offset);
1120	}
1121}
1122
1123inline void safe_instruction_vector2bytestream(U8 *stream, S32 &offset, const LLVector3 &value)
1124{
1125	if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_VECTOR]))
1126	{
1127		vector2bytestream(stream, offset, value);
1128	}
1129}
1130
1131inline void safe_instruction_bytestream2quaternion(LLQuaternion &value, U8 *stream, S32 &offset)
1132{
1133	if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_QUATERNION]))
1134	{
1135		bytestream2quaternion(value, stream, offset);
1136	}
1137}
1138
1139inline void safe_instruction_quaternion2bytestream(U8 *stream, S32 &offset, const LLQuaternion &value)
1140{
1141	if (safe_instruction_check_address(stream, offset, LSCRIPTDataSize[LST_QUATERNION]))
1142	{
1143		quaternion2bytestream(stream, offset, value);
1144	}
1145}
1146
1147static inline LSCRIPTType char2type(char type)
1148{
1149		switch(type)
1150		{
1151		case 'i':
1152			return LST_INTEGER;
1153		case 'f':
1154			return LST_FLOATINGPOINT;
1155		case 's':
1156			return LST_STRING;
1157		case 'k':
1158			return LST_KEY;
1159		case 'v':
1160			return LST_VECTOR;
1161		case 'q':
1162			return LST_QUATERNION;
1163		case 'l':
1164			return LST_LIST;
1165		default:
1166			return LST_NULL;
1167		}
1168}
1169
1170#endif