Files
SingularityViewer/indra/lscript/lscript_execute/lscript_execute.cpp
Beeks 810fff09d6 -Sanity checks from snowglobe. ...
-Null terminated a string buffer.
-Mutex locks are expensive.
-Realloc is my friend.
-But leaks are not.
-Nor are unused variables.
-And buffer overruns should get lost.
-bindManual shouldnt return failure if texture's already bound.
-Pulled windlight and classic clouds apart into unique rendertypes.
-'Client or Account' savedsettings stuff is now moar bettar. (and efficient)
-Replaced LLSavedSettingsGlue with something that supports gSavedSettings, gSavedPerAccountSettings, and gCOASavedSettings

-Added 'Enable Classic Clouds' checkbox to ascet performance settings panel
-New cards added to gpu table.
-General cleaning...
-How2spell 'dimensions'?

Via Shyotl

Signed-off-by: Beeks <HgDelirium@gmail.com>
2010-10-01 22:51:50 -04:00

4377 lines
107 KiB
C++

/**
* @file lscript_execute.cpp
* @brief classes to execute bytecode
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include <algorithm>
#include <sstream>
#include "lscript_execute.h"
#include "lltimer.h"
#include "lscript_readlso.h"
#include "lscript_library.h"
#include "lscript_heapruntime.h"
#include "lscript_alloc.h"
// Static
const S32 DEFAULT_SCRIPT_TIMER_CHECK_SKIP = 4;
S32 LLScriptExecute::sTimerCheckSkip = DEFAULT_SCRIPT_TIMER_CHECK_SKIP;
void (*binary_operations[LST_EOF][LST_EOF])(U8 *buffer, LSCRIPTOpCodesEnum opcode);
void (*unary_operations[LST_EOF])(U8 *buffer, LSCRIPTOpCodesEnum opcode);
const char* LSCRIPTRunTimeFaultStrings[LSRF_EOF] = /*Flawfinder: ignore*/
{
"Invalid", // LSRF_INVALID,
"Math Error", // LSRF_MATH,
"Stack-Heap Collision", // LSRF_STACK_HEAP_COLLISION,
"Bounds Check Error", // LSRF_BOUND_CHECK_ERROR,
"Heap Error", // LSRF_HEAP_ERROR,
"Version Mismatch", // LSRF_VERSION_MISMATCH,
"Missing Inventory", // LSRF_MISSING_INVENTORY,
"Hit Sandbox Limit", // LSRF_SANDBOX,
"Chat Overrun", // LSRF_CHAT_OVERRUN,
"Too Many Listens", // LSRF_TOO_MANY_LISTENS,
"Lists may not contain lists", // LSRF_NESTING_LISTS,
"CLI Exception" // LSRF_CLI
};
void LLScriptExecuteLSL2::startRunning() {}
void LLScriptExecuteLSL2::stopRunning() {}
const char* URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED";
const char* URL_REQUEST_DENIED = "URL_REQUEST_DENIED";
// HTTP Requests to LSL scripts will time out after 25 seconds.
const U64 LSL_HTTP_REQUEST_TIMEOUT = 25 * USEC_PER_SEC;
LLScriptExecuteLSL2::LLScriptExecuteLSL2(LLFILE *fp)
{
U8 sizearray[4];
S32 filesize;
S32 pos = 0;
if (fread(&sizearray, 1, 4, fp) != 4)
{
llwarns << "Short read" << llendl;
filesize = 0;
} else {
filesize = bytestream2integer(sizearray, pos);
}
mBuffer = new U8[filesize];
fseek(fp, 0, SEEK_SET);
if (fread(mBuffer, 1, filesize, fp) != filesize)
{
llwarns << "Short read" << llendl;
}
fclose(fp);
init();
}
LLScriptExecuteLSL2::LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size)
{
mBuffer = new U8[TOP_OF_MEMORY];
memset(mBuffer + bytecode_size, 0, TOP_OF_MEMORY - bytecode_size);
S32 src_offset = 0;
S32 dest_offset = 0;
bytestream2bytestream(mBuffer, dest_offset, bytecode, src_offset, bytecode_size);
mBytecodeSize = bytecode_size;
mBytecode = new U8[mBytecodeSize];
memcpy(mBytecode, bytecode, mBytecodeSize);
init();
}
LLScriptExecuteLSL2::~LLScriptExecuteLSL2()
{
delete[] mBuffer;
delete[] mBytecode;
}
void LLScriptExecuteLSL2::init()
{
S32 i, j;
mInstructionCount = 0;
for (i = 0; i < 256; i++)
{
mExecuteFuncs[i] = run_noop;
}
mExecuteFuncs[LSCRIPTOpCodes[LOPC_NOOP]] = run_noop;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_POP]] = run_pop;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_POPS]] = run_pops;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_POPL]] = run_popl;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_POPV]] = run_popv;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_POPQ]] = run_popq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_POPARG]] = run_poparg;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_POPIP]] = run_popip;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_POPBP]] = run_popbp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_POPSP]] = run_popsp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_POPSLR]] = run_popslr;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_DUP]] = run_dup;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_DUPS]] = run_dups;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_DUPL]] = run_dupl;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_DUPV]] = run_dupv;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_DUPQ]] = run_dupq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STORE]] = run_store;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STORES]] = run_stores;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STOREL]] = run_storel;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STOREV]] = run_storev;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STOREQ]] = run_storeq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STOREG]] = run_storeg;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STOREGL]] = run_storegl;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STOREGS]] = run_storegs;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STOREGV]] = run_storegv;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STOREGQ]] = run_storegq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LOADP]] = run_loadp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LOADSP]] = run_loadsp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LOADLP]] = run_loadlp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LOADVP]] = run_loadvp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LOADQP]] = run_loadqp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LOADGP]] = run_loadgp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LOADGSP]] = run_loadgsp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LOADGLP]] = run_loadglp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LOADGVP]] = run_loadgvp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LOADGQP]] = run_loadgqp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSH]] = run_push;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHS]] = run_pushs;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHL]] = run_pushl;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHV]] = run_pushv;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHQ]] = run_pushq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHG]] = run_pushg;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHGS]] = run_pushgs;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHGL]] = run_pushgl;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHGV]] = run_pushgv;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHGQ]] = run_pushgq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHIP]] = run_puship;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHSP]] = run_pushsp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHBP]] = run_pushbp;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHARGB]] = run_pushargb;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHARGI]] = run_pushargi;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHARGF]] = run_pushargf;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHARGS]] = run_pushargs;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHARGV]] = run_pushargv;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHARGQ]] = run_pushargq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHE]] = run_pushe;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHEV]] = run_pushev;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHEQ]] = run_pusheq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PUSHARGE]] = run_pusharge;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_ADD]] = run_add;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_SUB]] = run_sub;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_MUL]] = run_mul;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_DIV]] = run_div;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_MOD]] = run_mod;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_EQ]] = run_eq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_NEQ]] = run_neq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LEQ]] = run_leq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_GEQ]] = run_geq;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_LESS]] = run_less;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_GREATER]] = run_greater;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_BITAND]] = run_bitand;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_BITOR]] = run_bitor;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_BITXOR]] = run_bitxor;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_BOOLAND]] = run_booland;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_BOOLOR]] = run_boolor;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_SHL]] = run_shl;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_SHR]] = run_shr;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_NEG]] = run_neg;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_BITNOT]] = run_bitnot;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_BOOLNOT]] = run_boolnot;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_JUMP]] = run_jump;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_JUMPIF]] = run_jumpif;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_JUMPNIF]] = run_jumpnif;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STATE]] = run_state;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_CALL]] = run_call;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_RETURN]] = run_return;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_CAST]] = run_cast;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STACKTOS]] = run_stacktos;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_STACKTOL]] = run_stacktol;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_PRINT]] = run_print;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_CALLLIB]] = run_calllib;
mExecuteFuncs[LSCRIPTOpCodes[LOPC_CALLLIB_TWO_BYTE]] = run_calllib_two_byte;
for (i = 0; i < LST_EOF; i++)
{
for (j = 0; j < LST_EOF; j++)
{
binary_operations[i][j] = unknown_operation;
}
}
binary_operations[LST_INTEGER][LST_INTEGER] = integer_integer_operation;
binary_operations[LST_INTEGER][LST_FLOATINGPOINT] = integer_float_operation;
binary_operations[LST_INTEGER][LST_VECTOR] = integer_vector_operation;
binary_operations[LST_FLOATINGPOINT][LST_INTEGER] = float_integer_operation;
binary_operations[LST_FLOATINGPOINT][LST_FLOATINGPOINT] = float_float_operation;
binary_operations[LST_FLOATINGPOINT][LST_VECTOR] = float_vector_operation;
binary_operations[LST_STRING][LST_STRING] = string_string_operation;
binary_operations[LST_STRING][LST_KEY] = string_key_operation;
binary_operations[LST_KEY][LST_STRING] = key_string_operation;
binary_operations[LST_KEY][LST_KEY] = key_key_operation;
binary_operations[LST_VECTOR][LST_INTEGER] = vector_integer_operation;
binary_operations[LST_VECTOR][LST_FLOATINGPOINT] = vector_float_operation;
binary_operations[LST_VECTOR][LST_VECTOR] = vector_vector_operation;
binary_operations[LST_VECTOR][LST_QUATERNION] = vector_quaternion_operation;
binary_operations[LST_QUATERNION][LST_QUATERNION] = quaternion_quaternion_operation;
binary_operations[LST_INTEGER][LST_LIST] = integer_list_operation;
binary_operations[LST_FLOATINGPOINT][LST_LIST] = float_list_operation;
binary_operations[LST_STRING][LST_LIST] = string_list_operation;
binary_operations[LST_KEY][LST_LIST] = key_list_operation;
binary_operations[LST_VECTOR][LST_LIST] = vector_list_operation;
binary_operations[LST_QUATERNION][LST_LIST] = quaternion_list_operation;
binary_operations[LST_LIST][LST_INTEGER] = list_integer_operation;
binary_operations[LST_LIST][LST_FLOATINGPOINT] = list_float_operation;
binary_operations[LST_LIST][LST_STRING] = list_string_operation;
binary_operations[LST_LIST][LST_KEY] = list_key_operation;
binary_operations[LST_LIST][LST_VECTOR] = list_vector_operation;
binary_operations[LST_LIST][LST_QUATERNION] = list_quaternion_operation;
binary_operations[LST_LIST][LST_LIST] = list_list_operation;
for (i = 0; i < LST_EOF; i++)
{
unary_operations[i] = unknown_operation;
}
unary_operations[LST_INTEGER] = integer_operation;
unary_operations[LST_FLOATINGPOINT] = float_operation;
unary_operations[LST_VECTOR] = vector_operation;
unary_operations[LST_QUATERNION] = quaternion_operation;
}
// Utility routine for when there's a boundary error parsing bytecode
void LLScriptExecuteLSL2::recordBoundaryError( const LLUUID &id )
{
set_fault(mBuffer, LSRF_BOUND_CHECK_ERROR);
llwarns << "Script boundary error for ID " << id << llendl;
}
// set IP to the event handler with some error checking
void LLScriptExecuteLSL2::setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEventType event, const LLUUID &id )
{
S32 opcode_start = get_state_event_opcoode_start( mBuffer, state, event );
if ( opcode_start == -1 )
{
recordBoundaryError( id );
}
else
{
set_ip( mBuffer, opcode_start );
}
}
S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer);
void LLScriptExecuteLSL2::resumeEventHandler(BOOL b_print, const LLUUID &id, F32 time_slice)
{
// call opcode run function pointer with buffer and IP
mInstructionCount++;
S32 value = get_register(mBuffer, LREG_IP);
S32 tvalue = value;
S32 opcode = safe_instruction_bytestream2byte(mBuffer, tvalue);
mExecuteFuncs[opcode](mBuffer, value, b_print, id);
set_ip(mBuffer, value);
add_register_fp(mBuffer, LREG_ESR, -0.1f);
// lsa_print_heap(mBuffer);
if (b_print)
{
lsa_print_heap(mBuffer);
printf("ip: 0x%X\n", get_register(mBuffer, LREG_IP));
printf("sp: 0x%X\n", get_register(mBuffer, LREG_SP));
printf("bp: 0x%X\n", get_register(mBuffer, LREG_BP));
printf("hr: 0x%X\n", get_register(mBuffer, LREG_HR));
printf("hp: 0x%X\n", get_register(mBuffer, LREG_HP));
}
// NOTE: Babbage: all mExecuteFuncs return false.
}
void LLScriptExecuteLSL2::callEventHandler(LSCRIPTStateEventType event, const LLUUID &id, F32 time_slice)
{
S32 major_version = getMajorVersion();
// push a zero to be popped
lscript_push(mBuffer, 0);
// push sp as current bp
S32 sp = get_register(mBuffer, LREG_SP);
lscript_push(mBuffer, sp);
// Update current handler and current events registers.
set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
U64 current_events = get_event_register(mBuffer, LREG_CE, major_version);
current_events &= ~LSCRIPTStateBitField[event];
set_event_register(mBuffer, LREG_CE, current_events, major_version);
// now, push any additional stack space
U32 current_state = get_register(mBuffer, LREG_CS);
S32 additional_size = get_event_stack_size(mBuffer, current_state, event);
lscript_pusharge(mBuffer, additional_size);
// now set the bp correctly
sp = get_register(mBuffer, LREG_SP);
sp += additional_size;
set_bp(mBuffer, sp);
// set IP to the function
S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event);
set_ip(mBuffer, opcode_start);
}
//void callStateExitHandler()
//{
// // push a zero to be popped
// lscript_push(mBuffer, 0);
// // push sp as current bp
// S32 sp = get_register(mBuffer, LREG_SP);
// lscript_push(mBuffer, sp);
//
// // now, push any additional stack space
// S32 additional_size = get_event_stack_size(mBuffer, current_state, LSTT_STATE_EXIT);
// lscript_pusharge(mBuffer, additional_size);
//
// sp = get_register(mBuffer, LREG_SP);
// sp += additional_size;
// set_bp(mBuffer, sp);
//
// // set IP to the event handler
// S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, LSTT_STATE_EXIT);
// set_ip(mBuffer, opcode_start);
//}
//
//void callStateEntryHandler()
//{
// // push a zero to be popped
// lscript_push(mBuffer, 0);
// // push sp as current bp
// S32 sp = get_register(mBuffer, LREG_SP);
// lscript_push(mBuffer, sp);
//
// event = return_first_event((S32)LSCRIPTStateBitField[LSTT_STATE_ENTRY]);
// set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
// current_events &= ~LSCRIPTStateBitField[event];
// set_event_register(mBuffer, LREG_CE, current_events, major_version);
//
// // now, push any additional stack space
// S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size;
// lscript_pusharge(mBuffer, additional_size);
//
// // now set the bp correctly
// sp = get_register(mBuffer, LREG_SP);
// sp += additional_size + size;
// set_bp(mBuffer, sp);
// // set IP to the function
// S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event);
// set_ip(mBuffer, opcode_start);
//}
void LLScriptExecuteLSL2::callQueuedEventHandler(LSCRIPTStateEventType event, const LLUUID &id, F32 time_slice)
{
S32 major_version = getMajorVersion();
LLScriptDataCollection* eventdata;
for (eventdata = mEventData.mEventDataList.getFirstData(); eventdata; eventdata = mEventData.mEventDataList.getNextData())
{
if (eventdata->mType == event)
{
// push a zero to be popped
lscript_push(mBuffer, 0);
// push sp as current bp
S32 sp = get_register(mBuffer, LREG_SP);
lscript_push(mBuffer, sp);
// Update current handler and current events registers.
set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
U64 current_events = get_event_register(mBuffer, LREG_CE, major_version);
current_events &= ~LSCRIPTStateBitField[event];
set_event_register(mBuffer, LREG_CE, current_events, major_version);
// push any arguments that need to be pushed onto the stack
// last piece of data will be type LST_NULL
LLScriptLibData *data = eventdata->mData;
U32 size = 0;
while (data->mType)
{
size += lscript_push_variable(data, mBuffer);
data++;
}
// now, push any additional stack space
U32 current_state = get_register(mBuffer, LREG_CS);
S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size;
lscript_pusharge(mBuffer, additional_size);
// now set the bp correctly
sp = get_register(mBuffer, LREG_SP);
sp += additional_size + size;
set_bp(mBuffer, sp);
// set IP to the function
S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event);
set_ip(mBuffer, opcode_start);
mEventData.mEventDataList.deleteCurrentData();
break;
}
}
}
void LLScriptExecuteLSL2::callNextQueuedEventHandler(U64 event_register, const LLUUID &id, F32 time_slice)
{
S32 major_version = getMajorVersion();
LLScriptDataCollection* eventdata = mEventData.getNextEvent();
if (eventdata)
{
LSCRIPTStateEventType event = eventdata->mType;
// make sure that we can actually handle this one
if (LSCRIPTStateBitField[event] & event_register)
{
// push a zero to be popped
lscript_push(mBuffer, 0);
// push sp as current bp
S32 sp = get_register(mBuffer, LREG_SP);
lscript_push(mBuffer, sp);
// Update current handler and current events registers.
set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], major_version);
U64 current_events = get_event_register(mBuffer, LREG_CE, major_version);
current_events &= ~LSCRIPTStateBitField[event];
set_event_register(mBuffer, LREG_CE, current_events, major_version);
// push any arguments that need to be pushed onto the stack
// last piece of data will be type LST_NULL
LLScriptLibData *data = eventdata->mData;
U32 size = 0;
while (data->mType)
{
size += lscript_push_variable(data, mBuffer);
data++;
}
// now, push any additional stack space
U32 current_state = get_register(mBuffer, LREG_CS);
S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size;
lscript_pusharge(mBuffer, additional_size);
// now set the bp correctly
sp = get_register(mBuffer, LREG_SP);
sp += additional_size + size;
set_bp(mBuffer, sp);
// set IP to the function
S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event);
set_ip(mBuffer, opcode_start);
}
else
{
llwarns << "Somehow got an event that we're not registered for!" << llendl;
}
delete eventdata;
}
}
U64 LLScriptExecuteLSL2::nextState()
{
// copy NS to CS
S32 next_state = get_register(mBuffer, LREG_NS);
set_register(mBuffer, LREG_CS, next_state);
// copy new state's handled events into ER (SR + CS*4 + 4)
return get_handled_events(mBuffer, next_state);
}
//virtual
void LLScriptExecuteLSL2::addEvent(LLScriptDataCollection* event)
{
mEventData.addEventData(event);
}
//virtual
void LLScriptExecuteLSL2::removeEventType(LSCRIPTStateEventType event_type)
{
mEventData.removeEventType(event_type);
}
//virtual
F32 LLScriptExecuteLSL2::getSleep() const
{
return get_register_fp(mBuffer, LREG_SLR);
}
//virtual
void LLScriptExecuteLSL2::setSleep(F32 value)
{
set_register_fp(mBuffer, LREG_SLR, value);
}
//virtual
U64 LLScriptExecuteLSL2::getCurrentHandler()
{
return get_event_register(mBuffer, LREG_IE, getMajorVersion());
}
//virtual
F32 LLScriptExecuteLSL2::getEnergy() const
{
return get_register_fp(mBuffer, LREG_ESR);
}
//virtual
void LLScriptExecuteLSL2::setEnergy(F32 value)
{
set_register_fp(mBuffer, LREG_ESR, value);
}
//virtual
U32 LLScriptExecuteLSL2::getFreeMemory()
{
return get_register(mBuffer, LREG_SP) - get_register(mBuffer, LREG_HP);
}
//virtual
S32 LLScriptExecuteLSL2::getParameter()
{
return get_register(mBuffer, LREG_PR);
}
//virtual
void LLScriptExecuteLSL2::setParameter(S32 value)
{
set_register(mBuffer, LREG_PR, value);
}
S32 LLScriptExecuteLSL2::writeState(U8 **dest, U32 header_size, U32 footer_size)
{
// data format:
// 4 bytes of size of Registers, Name and Description, and Global Variables
// Registers, Name and Description, and Global Variables data
// 4 bytes of size of Heap
// Heap data
// 4 bytes of stack size
// Stack data
S32 registers_size = get_register(mBuffer, LREG_GFR);
if (get_register(mBuffer, LREG_HP) > TOP_OF_MEMORY)
reset_hp_to_safe_spot(mBuffer);
S32 heap_size = get_register(mBuffer, LREG_HP) - get_register(mBuffer, LREG_HR);
S32 stack_size = get_register(mBuffer, LREG_TM) - get_register(mBuffer, LREG_SP);
S32 total_size = registers_size + LSCRIPTDataSize[LST_INTEGER] +
heap_size + LSCRIPTDataSize[LST_INTEGER] +
stack_size + LSCRIPTDataSize[LST_INTEGER];
// actually allocate data
delete[] *dest;
*dest = new U8[header_size + total_size + footer_size];
memset(*dest, 0, header_size + total_size + footer_size);
S32 dest_offset = header_size;
S32 src_offset = 0;
// registers
integer2bytestream(*dest, dest_offset, registers_size);
// llinfos << "Writing CE: " << getCurrentEvents() << llendl;
bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, registers_size);
// heap
integer2bytestream(*dest, dest_offset, heap_size);
src_offset = get_register(mBuffer, LREG_HR);
bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, heap_size);
// stack
integer2bytestream(*dest, dest_offset, stack_size);
src_offset = get_register(mBuffer, LREG_SP);
bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, stack_size);
return total_size;
}
S32 LLScriptExecuteLSL2::writeBytecode(U8 **dest)
{
// data format:
// registers through top of heap
// Heap data
S32 total_size = get_register(mBuffer, LREG_HP);
// actually allocate data
delete [] *dest;
*dest = new U8[total_size];
S32 dest_offset = 0;
S32 src_offset = 0;
bytestream2bytestream(*dest, dest_offset, mBuffer, src_offset, total_size);
return total_size;
}
S32 LLScriptExecuteLSL2::readState(U8 *src)
{
// first, blitz heap and stack
S32 hr = get_register(mBuffer, LREG_HR);
S32 tm = get_register(mBuffer, LREG_TM);
memset(mBuffer + hr, 0, tm - hr);
S32 src_offset = 0;
S32 dest_offset = 0;
S32 size;
// read register size
size = bytestream2integer(src, src_offset);
// copy data into register area
bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size);
// llinfos << "Read CE: " << getCurrentEvents() << llendl;
if (get_register(mBuffer, LREG_TM) != TOP_OF_MEMORY)
{
llwarns << "Invalid state. Top of memory register does not match"
<< " constant." << llendl;
reset_hp_to_safe_spot(mBuffer);
return -1;
}
// read heap size
size = bytestream2integer(src, src_offset);
// set dest offset
dest_offset = get_register(mBuffer, LREG_HR);
if (dest_offset + size > TOP_OF_MEMORY)
{
reset_hp_to_safe_spot(mBuffer);
return -1;
}
// copy data into heap area
bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size);
// read stack size
size = bytestream2integer(src, src_offset);
// set dest offset
dest_offset = get_register(mBuffer, LREG_SP);
if (dest_offset + size > TOP_OF_MEMORY)
{
reset_hp_to_safe_spot(mBuffer);
return -1;
}
// copy data into heap area
bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size);
// Return offset to first byte after read data.
return src_offset;
}
void LLScriptExecuteLSL2::reset()
{
LLScriptExecute::reset();
const U8 *src = getBytecode();
S32 size = getBytecodeSize();
if (!src)
return;
// first, blitz heap and stack
S32 hr = get_register(mBuffer, LREG_HR);
S32 tm = get_register(mBuffer, LREG_TM);
memset(mBuffer + hr, 0, tm - hr);
S32 dest_offset = 0;
S32 src_offset = 0;
bytestream2bytestream(mBuffer, dest_offset, src, src_offset, size);
}
S32 LLScriptExecuteLSL2::getMajorVersion() const
{
S32 version = getVersion();
S32 major_version = 0;
if (version == LSL2_VERSION1_END_NUMBER){
major_version = 1;
}
else if (version == LSL2_VERSION_NUMBER)
{
major_version = 2;
}
return major_version;
}
U32 LLScriptExecuteLSL2::getUsedMemory()
{
return getBytecodeSize();
}
LLScriptExecute::LLScriptExecute() :
mReset(FALSE)
{
}
void LLScriptExecute::reset()
{
mReset = FALSE;
}
bool LLScriptExecute::isYieldDue() const
{
if(mReset)
{
return true;
}
if(getSleep() > 0.f)
{
return true;
}
if(isFinished())
{
return true;
}
// State changes can occur within a single time slice,
// but LLScriptData's clean up is required. Yield here
// to allow LLScriptData to perform cleanup and then call
// runQuanta again.
if(isStateChangePending())
{
return true;
}
return false;
}
// Run smallest number of instructions possible:
// a single instruction for LSL2, a segment between save tests for Mono
void LLScriptExecute::runInstructions(BOOL b_print, const LLUUID &id,
const char **errorstr,
U32& events_processed,
F32 quanta)
{
// is there a fault?
// if yes, print out message and exit
S32 value = getVersion();
S32 major_version = 0;
if (value == LSL2_VERSION1_END_NUMBER)
{
major_version = 1;
}
else if (value == LSL2_VERSION_NUMBER)
{
major_version = 2;
}
else
{
setFault(LSRF_VERSION_MISMATCH);
}
value = getFaults();
if (value > LSRF_INVALID && value < LSRF_EOF)
{
if (b_print)
{
printf("Error!\n");
}
*errorstr = LSCRIPTRunTimeFaultStrings[value];
return;
}
else
{
*errorstr = NULL;
}
if (! isFinished())
{
resumeEventHandler(b_print, id, quanta);
return;
}
else
{
// make sure that IE is zero
setCurrentHandler(0);
// if no, we're in a state and waiting for an event
U64 current_events = getCurrentEvents();
U64 event_register = getEventHandlers();
// check NS to see if need to switch states (NS != CS)
if (isStateChangePending())
{
// ok, blow away any pending events
deleteAllEvents();
// if yes, check state exit flag is set
if (current_events & LSCRIPTStateBitField[LSTT_STATE_EXIT])
{
// if yes, clear state exit flag
setCurrentHandler(LSCRIPTStateBitField[LSTT_STATE_EXIT]);
current_events &= ~LSCRIPTStateBitField[LSTT_STATE_EXIT];
setCurrentEvents(current_events);
// check state exit event handler
// if there is a handler, call it
if (event_register & LSCRIPTStateBitField[LSTT_STATE_EXIT])
{
++events_processed;
callEventHandler(LSTT_STATE_EXIT, id, quanta);
return;
}
}
// if no handler or no state exit flag switch to new state
// set state entry flag and clear other CE flags
current_events = LSCRIPTStateBitField[LSTT_STATE_ENTRY];
setCurrentEvents(current_events);
U64 handled_events = nextState();
setEventHandlers(handled_events);
}
// try to get next event from stack
BOOL b_done = FALSE;
LSCRIPTStateEventType event = LSTT_NULL;
current_events = getCurrentEvents();
event_register = getEventHandlers();
// first, check to see if state_entry or onrez are raised and handled
if ((current_events & LSCRIPTStateBitField[LSTT_STATE_ENTRY])
&&(current_events & event_register))
{
++events_processed;
callEventHandler(LSTT_STATE_ENTRY, id, quanta);
b_done = TRUE;
}
else if ((current_events & LSCRIPTStateBitField[LSTT_REZ])
&&(current_events & event_register))
{
++events_processed;
callQueuedEventHandler(LSTT_REZ, id, quanta);
b_done = TRUE;
}
if (!b_done)
{
// Call handler for next queued event.
if(getEventCount() > 0)
{
++events_processed;
callNextQueuedEventHandler(event_register, id, quanta);
}
else
{
// if no data waiting, do it the old way:
U64 handled_current = current_events & event_register;
if (handled_current)
{
event = return_first_event((S32)handled_current);
++events_processed;
callEventHandler(event, id, quanta);
}
}
b_done = TRUE;
}
}
}
// Run for a single timeslice, or until a yield or state transition is due
F32 LLScriptExecute::runQuanta(BOOL b_print, const LLUUID &id, const char **errorstr, F32 quanta, U32& events_processed, LLTimer& timer)
{
S32 timer_checks = 0;
F32 inloop = 0;
// Loop while not finished, yield not due and time remaining
// NOTE: Default implementation does not do adaptive timer skipping
// to preserve current LSL behaviour and not break scripts that rely
// on current execution speed.
while(true)
{
runInstructions(b_print, id, errorstr,
events_processed, quanta);
if(isYieldDue())
{
break;
}
else if(timer_checks++ >= LLScriptExecute::sTimerCheckSkip)
{
inloop = timer.getElapsedTimeF32();
if(inloop > quanta)
{
break;
}
timer_checks = 0;
}
}
if (inloop == 0.0f)
{
inloop = timer.getElapsedTimeF32();
}
return inloop;
}
F32 LLScriptExecute::runNested(BOOL b_print, const LLUUID &id, const char **errorstr, F32 quanta, U32& events_processed, LLTimer& timer)
{
return LLScriptExecute::runQuanta(b_print, id, errorstr, quanta, events_processed, timer);
}
BOOL run_noop(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tNOOP\n", offset);
offset++;
return FALSE;
}
BOOL run_pop(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPOP\n", offset);
offset++;
lscript_poparg(buffer, LSCRIPTDataSize[LST_INTEGER]);
return FALSE;
}
BOOL run_pops(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPOPS\n", offset);
offset++;
S32 address = lscript_pop_int(buffer);
if (address)
lsa_decrease_ref_count(buffer, address);
return FALSE;
}
BOOL run_popl(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPOPL\n", offset);
offset++;
S32 address = lscript_pop_int(buffer);
if (address)
lsa_decrease_ref_count(buffer, address);
return FALSE;
}
BOOL run_popv(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPOPV\n", offset);
offset++;
lscript_poparg(buffer, LSCRIPTDataSize[LST_VECTOR]);
return FALSE;
}
BOOL run_popq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPOPQ\n", offset);
offset++;
lscript_poparg(buffer, LSCRIPTDataSize[LST_QUATERNION]);
return FALSE;
}
BOOL run_poparg(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPOPARG ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("%d\n", arg);
lscript_poparg(buffer, arg);
return FALSE;
}
BOOL run_popip(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPOPIP\n", offset);
offset++;
offset = lscript_pop_int(buffer);
return FALSE;
}
BOOL run_popbp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPOPBP\n", offset);
offset++;
S32 bp = lscript_pop_int(buffer);
set_bp(buffer, bp);
return FALSE;
}
BOOL run_popsp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPOPSP\n", offset);
offset++;
S32 sp = lscript_pop_int(buffer);
set_sp(buffer, sp);
return FALSE;
}
BOOL run_popslr(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPOPSLR\n", offset);
offset++;
S32 slr = lscript_pop_int(buffer);
set_register(buffer, LREG_SLR, slr);
return FALSE;
}
BOOL run_dup(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tDUP\n", offset);
offset++;
S32 sp = get_register(buffer, LREG_SP);
S32 value = bytestream2integer(buffer, sp);
lscript_push(buffer, value);
return FALSE;
}
BOOL run_dups(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tDUPS\n", offset);
offset++;
S32 sp = get_register(buffer, LREG_SP);
S32 value = bytestream2integer(buffer, sp);
lscript_push(buffer, value);
lsa_increase_ref_count(buffer, value);
return FALSE;
}
BOOL run_dupl(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tDUPL\n", offset);
offset++;
S32 sp = get_register(buffer, LREG_SP);
S32 value = bytestream2integer(buffer, sp);
lscript_push(buffer, value);
lsa_increase_ref_count(buffer, value);
return FALSE;
}
BOOL run_dupv(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tDUPV\n", offset);
offset++;
S32 sp = get_register(buffer, LREG_SP);
LLVector3 value;
bytestream2vector(value, buffer, sp);
lscript_push(buffer, value);
return FALSE;
}
BOOL run_dupq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tDUPV\n", offset);
offset++;
S32 sp = get_register(buffer, LREG_SP);
LLQuaternion value;
bytestream2quaternion(value, buffer, sp);
lscript_push(buffer, value);
return FALSE;
}
BOOL run_store(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTORE ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 sp = get_register(buffer, LREG_SP);
S32 value = bytestream2integer(buffer, sp);
lscript_local_store(buffer, arg, value);
return FALSE;
}
BOOL run_stores(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTORES ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 sp = get_register(buffer, LREG_SP);
S32 value = bytestream2integer(buffer, sp);
S32 address = lscript_local_get(buffer, arg);
lscript_local_store(buffer, arg, value);
lsa_increase_ref_count(buffer, value);
if (address)
lsa_decrease_ref_count(buffer, address);
return FALSE;
}
BOOL run_storel(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREL ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 sp = get_register(buffer, LREG_SP);
S32 value = bytestream2integer(buffer, sp);
S32 address = lscript_local_get(buffer, arg);
lscript_local_store(buffer, arg, value);
lsa_increase_ref_count(buffer, value);
if (address)
lsa_decrease_ref_count(buffer, address);
return FALSE;
}
BOOL run_storev(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREV ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLVector3 value;
S32 sp = get_register(buffer, LREG_SP);
bytestream2vector(value, buffer, sp);
lscript_local_store(buffer, arg, value);
return FALSE;
}
BOOL run_storeq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREQ ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLQuaternion value;
S32 sp = get_register(buffer, LREG_SP);
bytestream2quaternion(value, buffer, sp);
lscript_local_store(buffer, arg, value);
return FALSE;
}
BOOL run_storeg(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREG ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 sp = get_register(buffer, LREG_SP);
S32 value = bytestream2integer(buffer, sp);
lscript_global_store(buffer, arg, value);
return FALSE;
}
BOOL run_storegs(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREGS ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 sp = get_register(buffer, LREG_SP);
S32 value = bytestream2integer(buffer, sp);
S32 address = lscript_global_get(buffer, arg);
lscript_global_store(buffer, arg, value);
lsa_increase_ref_count(buffer, value);
if (address)
lsa_decrease_ref_count(buffer, address);
return FALSE;
}
BOOL run_storegl(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREGL ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 sp = get_register(buffer, LREG_SP);
S32 value = bytestream2integer(buffer, sp);
S32 address = lscript_global_get(buffer, arg);
lscript_global_store(buffer, arg, value);
lsa_increase_ref_count(buffer, value);
if (address)
lsa_decrease_ref_count(buffer, address);
return FALSE;
}
BOOL run_storegv(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREGV ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLVector3 value;
S32 sp = get_register(buffer, LREG_SP);
bytestream2vector(value, buffer, sp);
lscript_global_store(buffer, arg, value);
return FALSE;
}
BOOL run_storegq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREGQ ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLQuaternion value;
S32 sp = get_register(buffer, LREG_SP);
bytestream2quaternion(value, buffer, sp);
lscript_global_store(buffer, arg, value);
return FALSE;
}
BOOL run_loadp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_pop_int(buffer);
lscript_local_store(buffer, arg, value);
return FALSE;
}
BOOL run_loadsp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTORESP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_pop_int(buffer);
S32 address = lscript_local_get(buffer, arg);
if (address)
lsa_decrease_ref_count(buffer, address);
lscript_local_store(buffer, arg, value);
return FALSE;
}
BOOL run_loadlp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTORELP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_pop_int(buffer);
S32 address = lscript_local_get(buffer, arg);
if (address)
lsa_decrease_ref_count(buffer, address);
lscript_local_store(buffer, arg, value);
return FALSE;
}
BOOL run_loadvp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREVP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLVector3 value;
lscript_pop_vector(buffer, value);
lscript_local_store(buffer, arg, value);
return FALSE;
}
BOOL run_loadqp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREQP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLQuaternion value;
lscript_pop_quaternion(buffer, value);
lscript_local_store(buffer, arg, value);
return FALSE;
}
BOOL run_loadgp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREGP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_pop_int(buffer);
lscript_global_store(buffer, arg, value);
return FALSE;
}
BOOL run_loadgsp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREGSP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("%d\n", arg);
S32 value = lscript_pop_int(buffer);
S32 address = lscript_global_get(buffer, arg);
if (address)
lsa_decrease_ref_count(buffer, address);
lscript_global_store(buffer, arg, value);
return FALSE;
}
BOOL run_loadglp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREGLP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_pop_int(buffer);
S32 address = lscript_global_get(buffer, arg);
if (address)
lsa_decrease_ref_count(buffer, address);
lscript_global_store(buffer, arg, value);
return FALSE;
}
BOOL run_loadgvp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREGVP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLVector3 value;
lscript_pop_vector(buffer, value);
lscript_global_store(buffer, arg, value);
return FALSE;
}
BOOL run_loadgqp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTOREGQP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLQuaternion value;
lscript_pop_quaternion(buffer, value);
lscript_global_store(buffer, arg, value);
return FALSE;
}
BOOL run_push(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSH ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_local_get(buffer, arg);
lscript_push(buffer, value);
return FALSE;
}
BOOL run_pushs(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHS ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_local_get(buffer, arg);
lscript_push(buffer, value);
lsa_increase_ref_count(buffer, value);
return FALSE;
}
BOOL run_pushl(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHL ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_local_get(buffer, arg);
lscript_push(buffer, value);
lsa_increase_ref_count(buffer, value);
return FALSE;
}
BOOL run_pushv(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHV ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLVector3 value;
lscript_local_get(buffer, arg, value);
lscript_push(buffer, value);
return FALSE;
}
BOOL run_pushq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHQ ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLQuaternion value;
lscript_local_get(buffer, arg, value);
lscript_push(buffer, value);
return FALSE;
}
BOOL run_pushg(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHG ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_global_get(buffer, arg);
lscript_push(buffer, value);
return FALSE;
}
BOOL run_pushgs(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHGS ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_global_get(buffer, arg);
lscript_push(buffer, value);
lsa_increase_ref_count(buffer, value);
return FALSE;
}
BOOL run_pushgl(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHGL ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
S32 value = lscript_global_get(buffer, arg);
lscript_push(buffer, value);
lsa_increase_ref_count(buffer, value);
return FALSE;
}
BOOL run_pushgv(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHGV ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLVector3 value;
lscript_global_get(buffer, arg, value);
lscript_push(buffer, value);
return FALSE;
}
BOOL run_pushgq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHGQ ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("0x%X\n", arg);
LLQuaternion value;
lscript_global_get(buffer, arg, value);
lscript_push(buffer, value);
return FALSE;
}
BOOL run_puship(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHIP\n", offset);
offset++;
lscript_push(buffer, offset);
return FALSE;
}
BOOL run_pushbp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHBP\n", offset);
offset++;
lscript_push(buffer, get_register(buffer, LREG_BP));
return FALSE;
}
BOOL run_pushsp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHSP\n", offset);
offset++;
lscript_push(buffer, get_register(buffer, LREG_SP));
return FALSE;
}
BOOL run_pushargb(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHGARGB ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
if (b_print)
printf("%d\n", (U32)arg);
lscript_push(buffer, arg);
return FALSE;
}
BOOL run_pushargi(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHARGI ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("%d\n", arg);
lscript_push(buffer, arg);
return FALSE;
}
BOOL run_pushargf(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHARGF ", offset);
offset++;
F32 arg = safe_instruction_bytestream2float(buffer, offset);
if (b_print)
printf("%f\n", arg);
lscript_push(buffer, arg);
return FALSE;
}
BOOL run_pushargs(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHARGS ", offset);
S32 toffset = offset;
safe_instruction_bytestream_count_char(buffer, toffset);
S32 size = toffset - offset;
char *arg = new char[size];
offset++;
safe_instruction_bytestream2char(arg, buffer, offset, size);
if (b_print)
printf("%s\n", arg);
S32 address = lsa_heap_add_data(buffer, new LLScriptLibData(arg), get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
delete [] arg;
return FALSE;
}
BOOL run_pushargv(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHARGV ", offset);
offset++;
LLVector3 arg;
safe_instruction_bytestream2vector(arg, buffer, offset);
if (b_print)
printf("< %f, %f, %f >\n", arg.mV[VX], arg.mV[VY], arg.mV[VZ]);
lscript_push(buffer, arg);
return FALSE;
}
BOOL run_pushargq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHARGQ ", offset);
offset++;
LLQuaternion arg;
safe_instruction_bytestream2quaternion(arg, buffer, offset);
if (b_print)
printf("< %f, %f, %f, %f >\n", arg.mQ[VX], arg.mQ[VY], arg.mQ[VZ], arg.mQ[VS]);
lscript_push(buffer, arg);
return FALSE;
}
BOOL run_pushe(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHE\n", offset);
offset++;
lscript_pusharge(buffer, LSCRIPTDataSize[LST_INTEGER]);
return FALSE;
}
BOOL run_pushev(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHEV\n", offset);
offset++;
lscript_pusharge(buffer, LSCRIPTDataSize[LST_VECTOR]);
return FALSE;
}
BOOL run_pusheq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHEQ\n", offset);
offset++;
lscript_pusharge(buffer, LSCRIPTDataSize[LST_QUATERNION]);
return FALSE;
}
BOOL run_pusharge(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPUSHARGE ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("%d\n", arg);
lscript_pusharge(buffer, arg);
return FALSE;
}
void print_type(U8 type)
{
if (type == LSCRIPTTypeByte[LST_INTEGER])
{
printf("integer");
}
else if (type == LSCRIPTTypeByte[LST_FLOATINGPOINT])
{
printf("float");
}
else if (type == LSCRIPTTypeByte[LST_STRING])
{
printf("string");
}
else if (type == LSCRIPTTypeByte[LST_KEY])
{
printf("key");
}
else if (type == LSCRIPTTypeByte[LST_VECTOR])
{
printf("vector");
}
else if (type == LSCRIPTTypeByte[LST_QUATERNION])
{
printf("quaternion");
}
else if (type == LSCRIPTTypeByte[LST_LIST])
{
printf("list");
}
}
void unknown_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
printf("Unknown arithmetic operation!\n");
}
void integer_integer_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 result = 0;
switch(opcode)
{
case LOPC_ADD:
result = lside + rside;
break;
case LOPC_SUB:
result = lside - rside;
break;
case LOPC_MUL:
result = lside * rside;
break;
case LOPC_DIV:
if (rside){
if( ( rside == -1 ) || ( rside == (S32) 0xffffffff ) )// division by -1 can have funny results: multiplication is OK: SL-31252
{
result = -1 * lside;
}
else
{
result = lside / rside;
}
}
else
set_fault(buffer, LSRF_MATH);
break;
case LOPC_MOD:
if (rside)
{
if (rside == -1 || rside == 1 ) // mod(1) = mod(-1) = 0: SL-31252
{
result = 0;
}
else
{
result = lside % rside;
}
}
else
set_fault(buffer, LSRF_MATH);
break;
case LOPC_EQ:
result = (lside == rside);
break;
case LOPC_NEQ:
result = (lside != rside);
break;
case LOPC_LEQ:
result = (lside <= rside);
break;
case LOPC_GEQ:
result = (lside >= rside);
break;
case LOPC_LESS:
result = (lside < rside);
break;
case LOPC_GREATER:
result = (lside > rside);
break;
case LOPC_BITAND:
result = (lside & rside);
break;
case LOPC_BITOR:
result = (lside | rside);
break;
case LOPC_BITXOR:
result = (lside ^ rside);
break;
case LOPC_BOOLAND:
result = (lside && rside);
break;
case LOPC_BOOLOR:
result = (lside || rside);
break;
case LOPC_SHL:
result = (lside << rside);
break;
case LOPC_SHR:
result = (lside >> rside);
break;
default:
break;
}
lscript_push(buffer, result);
}
void integer_float_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
F32 rside = lscript_pop_float(buffer);
S32 resulti = 0;
F32 resultf = 0;
switch(opcode)
{
case LOPC_ADD:
resultf = lside + rside;
lscript_push(buffer, resultf);
break;
case LOPC_SUB:
resultf = lside - rside;
lscript_push(buffer, resultf);
break;
case LOPC_MUL:
resultf = lside * rside;
lscript_push(buffer, resultf);
break;
case LOPC_DIV:
if (rside)
resultf = lside / rside;
else
set_fault(buffer, LSRF_MATH);
lscript_push(buffer, resultf);
break;
case LOPC_EQ:
resulti = (lside == rside);
lscript_push(buffer, resulti);
break;
case LOPC_NEQ:
resulti = (lside != rside);
lscript_push(buffer, resulti);
break;
case LOPC_LEQ:
resulti = (lside <= rside);
lscript_push(buffer, resulti);
break;
case LOPC_GEQ:
resulti = (lside >= rside);
lscript_push(buffer, resulti);
break;
case LOPC_LESS:
resulti = (lside < rside);
lscript_push(buffer, resulti);
break;
case LOPC_GREATER:
resulti = (lside > rside);
lscript_push(buffer, resulti);
break;
default:
break;
}
}
void integer_vector_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
LLVector3 rside;
lscript_pop_vector(buffer, rside);
switch(opcode)
{
case LOPC_MUL:
rside *= (F32)lside;
lscript_push(buffer, rside);
break;
default:
break;
}
}
void float_integer_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
F32 lside = lscript_pop_float(buffer);
S32 rside = lscript_pop_int(buffer);
S32 resulti = 0;
F32 resultf = 0;
switch(opcode)
{
case LOPC_ADD:
resultf = lside + rside;
lscript_push(buffer, resultf);
break;
case LOPC_SUB:
resultf = lside - rside;
lscript_push(buffer, resultf);
break;
case LOPC_MUL:
resultf = lside * rside;
lscript_push(buffer, resultf);
break;
case LOPC_DIV:
if (rside)
resultf = lside / rside;
else
set_fault(buffer, LSRF_MATH);
lscript_push(buffer, resultf);
break;
case LOPC_EQ:
resulti = (lside == rside);
lscript_push(buffer, resulti);
break;
case LOPC_NEQ:
resulti = (lside != rside);
lscript_push(buffer, resulti);
break;
case LOPC_LEQ:
resulti = (lside <= rside);
lscript_push(buffer, resulti);
break;
case LOPC_GEQ:
resulti = (lside >= rside);
lscript_push(buffer, resulti);
break;
case LOPC_LESS:
resulti = (lside < rside);
lscript_push(buffer, resulti);
break;
case LOPC_GREATER:
resulti = (lside > rside);
lscript_push(buffer, resulti);
break;
default:
break;
}
}
void float_float_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
F32 lside = lscript_pop_float(buffer);
F32 rside = lscript_pop_float(buffer);
F32 resultf = 0;
S32 resulti = 0;
switch(opcode)
{
case LOPC_ADD:
resultf = lside + rside;
lscript_push(buffer, resultf);
break;
case LOPC_SUB:
resultf = lside - rside;
lscript_push(buffer, resultf);
break;
case LOPC_MUL:
resultf = lside * rside;
lscript_push(buffer, resultf);
break;
case LOPC_DIV:
if (rside)
resultf = lside / rside;
else
set_fault(buffer, LSRF_MATH);
lscript_push(buffer, resultf);
break;
case LOPC_EQ:
resulti = (lside == rside);
lscript_push(buffer, resulti);
break;
case LOPC_NEQ:
resulti = (lside != rside);
lscript_push(buffer, resulti);
break;
case LOPC_LEQ:
resulti = (lside <= rside);
lscript_push(buffer, resulti);
break;
case LOPC_GEQ:
resulti = (lside >= rside);
lscript_push(buffer, resulti);
break;
case LOPC_LESS:
resulti = (lside < rside);
lscript_push(buffer, resulti);
break;
case LOPC_GREATER:
resulti = (lside > rside);
lscript_push(buffer, resulti);
break;
default:
break;
}
}
void float_vector_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
F32 lside = lscript_pop_float(buffer);
LLVector3 rside;
lscript_pop_vector(buffer, rside);
switch(opcode)
{
case LOPC_MUL:
rside *= lside;
lscript_push(buffer, rside);
break;
default:
break;
}
}
void string_string_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 resulti;
S32 address;
switch(opcode)
{
case LOPC_ADD:
address = lsa_cat_strings(buffer, lside, rside, get_max_heap_size(buffer));
lscript_push(buffer, address);
break;
case LOPC_EQ:
resulti = !lsa_cmp_strings(buffer, lside, rside);
lscript_push(buffer, resulti);
break;
case LOPC_NEQ:
resulti = lsa_cmp_strings(buffer, lside, rside);
lscript_push(buffer, resulti);
break;
default:
break;
}
}
void string_key_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 resulti;
switch(opcode)
{
case LOPC_NEQ:
resulti = lsa_cmp_strings(buffer, lside, rside);
lscript_push(buffer, resulti);
break;
case LOPC_EQ:
resulti = !lsa_cmp_strings(buffer, lside, rside);
lscript_push(buffer, resulti);
break;
default:
break;
}
}
void key_string_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 resulti;
switch(opcode)
{
case LOPC_NEQ:
resulti = lsa_cmp_strings(buffer, lside, rside);
lscript_push(buffer, resulti);
break;
case LOPC_EQ:
resulti = !lsa_cmp_strings(buffer, lside, rside);
lscript_push(buffer, resulti);
break;
default:
break;
}
}
void key_key_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 resulti;
switch(opcode)
{
case LOPC_EQ:
resulti = !lsa_cmp_strings(buffer, lside, rside);
lscript_push(buffer, resulti);
break;
case LOPC_NEQ:
resulti = lsa_cmp_strings(buffer, lside, rside);
lscript_push(buffer, resulti);
break;
default:
break;
}
}
void vector_integer_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
LLVector3 lside;
lscript_pop_vector(buffer, lside);
S32 rside = lscript_pop_int(buffer);
switch(opcode)
{
case LOPC_MUL:
lside *= (F32)rside;
lscript_push(buffer, lside);
break;
case LOPC_DIV:
if (rside)
lside *= (1.f/rside);
else
set_fault(buffer, LSRF_MATH);
lscript_push(buffer, lside);
break;
default:
break;
}
}
void vector_float_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
LLVector3 lside;
lscript_pop_vector(buffer, lside);
F32 rside = lscript_pop_float(buffer);
switch(opcode)
{
case LOPC_MUL:
lside *= rside;
lscript_push(buffer, lside);
break;
case LOPC_DIV:
if (rside)
lside *= (1.f/rside);
else
set_fault(buffer, LSRF_MATH);
lscript_push(buffer, lside);
break;
default:
break;
}
}
void vector_vector_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
LLVector3 lside;
lscript_pop_vector(buffer, lside);
LLVector3 rside;
lscript_pop_vector(buffer, rside);
S32 resulti = 0;
F32 resultf = 0.f;
switch(opcode)
{
case LOPC_ADD:
lside += rside;
lscript_push(buffer, lside);
break;
case LOPC_SUB:
lside -= rside;
lscript_push(buffer, lside);
break;
case LOPC_MUL:
resultf = lside * rside;
lscript_push(buffer, resultf);
break;
case LOPC_MOD:
lside = lside % rside;
lscript_push(buffer, lside);
break;
case LOPC_EQ:
resulti = (lside == rside);
lscript_push(buffer, resulti);
break;
case LOPC_NEQ:
resulti = (lside != rside);
lscript_push(buffer, resulti);
break;
default:
break;
}
}
void vector_quaternion_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
LLVector3 lside;
lscript_pop_vector(buffer, lside);
LLQuaternion rside;
lscript_pop_quaternion(buffer, rside);
switch(opcode)
{
case LOPC_MUL:
lside = lside * rside;
lscript_push(buffer, lside);
break;
case LOPC_DIV:
lside = lside * rside.conjQuat();
lscript_push(buffer, lside);
break;
default:
break;
}
}
void quaternion_quaternion_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
LLQuaternion lside;
lscript_pop_quaternion(buffer, lside);
LLQuaternion rside;
lscript_pop_quaternion(buffer, rside);
S32 resulti = 0;
switch(opcode)
{
case LOPC_ADD:
lside = lside + rside;
lscript_push(buffer, lside);
break;
case LOPC_SUB:
lside = lside - rside;
lscript_push(buffer, lside);
break;
case LOPC_MUL:
lside *= rside;
lscript_push(buffer, lside);
break;
case LOPC_DIV:
lside = lside * rside.conjQuat();
lscript_push(buffer, lside);
break;
case LOPC_EQ:
resulti = (lside == rside);
lscript_push(buffer, resulti);
break;
case LOPC_NEQ:
resulti = (lside != rside);
lscript_push(buffer, resulti);
break;
default:
break;
}
}
void integer_list_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(lside);
address = lsa_preadd_lists(buffer, list, rside, get_max_heap_size(buffer));
lscript_push(buffer, address);
list->mListp = NULL;
delete list;
}
break;
default:
break;
}
}
void float_list_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
F32 lside = lscript_pop_float(buffer);
S32 rside = lscript_pop_int(buffer);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(lside);
address = lsa_preadd_lists(buffer, list, rside, get_max_heap_size(buffer));
lscript_push(buffer, address);
list->mListp = NULL;
delete list;
}
break;
default:
break;
}
}
void string_list_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *string = lsa_get_data(buffer, lside, TRUE);
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = string;
address = lsa_preadd_lists(buffer, list, rside, get_max_heap_size(buffer));
lscript_push(buffer, address);
list->mListp = NULL;
delete list;
}
break;
default:
break;
}
}
void key_list_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *key = lsa_get_data(buffer, lside, TRUE);
// need to convert key to key, since it comes out like a string
if (key->mType == LST_STRING)
{
key->mKey = key->mString;
key->mString = NULL;
key->mType = LST_KEY;
}
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = key;
address = lsa_preadd_lists(buffer, list, rside, get_max_heap_size(buffer));
lscript_push(buffer, address);
list->mListp = NULL;
delete list;
}
break;
default:
break;
}
}
void vector_list_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
LLVector3 lside;
lscript_pop_vector(buffer, lside);
S32 rside = lscript_pop_int(buffer);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(lside);
address = lsa_preadd_lists(buffer, list, rside, get_max_heap_size(buffer));
lscript_push(buffer, address);
list->mListp = NULL;
delete list;
}
break;
default:
break;
}
}
void quaternion_list_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
LLQuaternion lside;
lscript_pop_quaternion(buffer, lside);
S32 rside = lscript_pop_int(buffer);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(lside);
address = lsa_preadd_lists(buffer, list, rside, get_max_heap_size(buffer));
lscript_push(buffer, address);
list->mListp = NULL;
delete list;
}
break;
default:
break;
}
}
void list_integer_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(rside);
address = lsa_postadd_lists(buffer, lside, list, get_max_heap_size(buffer));
list->mListp = NULL;
delete list;
lscript_push(buffer, address);
}
break;
default:
break;
}
}
void list_float_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
F32 rside = lscript_pop_float(buffer);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(rside);
address = lsa_postadd_lists(buffer, lside, list, get_max_heap_size(buffer));
list->mListp = NULL;
delete list;
lscript_push(buffer, address);
}
break;
default:
break;
}
}
void list_string_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *string = lsa_get_data(buffer, rside, TRUE);
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = string;
address = lsa_postadd_lists(buffer, lside, list, get_max_heap_size(buffer));
list->mListp = NULL;
delete list;
lscript_push(buffer, address);
}
break;
default:
break;
}
}
void list_key_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *key = lsa_get_data(buffer, rside, TRUE);
// need to convert key to key, since it comes out like a string
if (key->mType == LST_STRING)
{
key->mKey = key->mString;
key->mString = NULL;
key->mType = LST_KEY;
}
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = key;
address = lsa_postadd_lists(buffer, lside, list, get_max_heap_size(buffer));
list->mListp = NULL;
delete list;
lscript_push(buffer, address);
}
break;
default:
break;
}
}
void list_vector_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
LLVector3 rside;
lscript_pop_vector(buffer, rside);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(rside);
address = lsa_postadd_lists(buffer, lside, list, get_max_heap_size(buffer));
list->mListp = NULL;
delete list;
lscript_push(buffer, address);
}
break;
default:
break;
}
}
void list_quaternion_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
LLQuaternion rside;
lscript_pop_quaternion(buffer, rside);
S32 address;
switch(opcode)
{
case LOPC_ADD:
{
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(rside);
address = lsa_postadd_lists(buffer, lside, list, get_max_heap_size(buffer));
list->mListp = NULL;
delete list;
lscript_push(buffer, address);
}
break;
default:
break;
}
}
void list_list_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 rside = lscript_pop_int(buffer);
S32 resulti;
S32 address;
switch(opcode)
{
case LOPC_ADD:
address = lsa_cat_lists(buffer, lside, rside, get_max_heap_size(buffer));
lscript_push(buffer, address);
break;
case LOPC_EQ:
resulti = !lsa_cmp_lists(buffer, lside, rside);
lscript_push(buffer, resulti);
break;
case LOPC_NEQ:
resulti = lsa_cmp_lists(buffer, lside, rside);
lscript_push(buffer, resulti);
break;
default:
break;
}
}
static U8 safe_op_index(U8 index)
{
if(index >= LST_EOF)
{
// Operations on LST_NULL will always be unknown_operation.
index = LST_NULL;
}
return index;
}
BOOL run_add(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tADD ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_ADD);
return FALSE;
}
BOOL run_sub(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSUB ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_SUB);
return FALSE;
}
BOOL run_mul(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tMUL ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_MUL);
return FALSE;
}
BOOL run_div(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tDIV ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_DIV);
return FALSE;
}
BOOL run_mod(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tMOD ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_MOD);
return FALSE;
}
BOOL run_eq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tEQ ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_EQ);
return FALSE;
}
BOOL run_neq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tNEQ ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_NEQ);
return FALSE;
}
BOOL run_leq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tLEQ ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_LEQ);
return FALSE;
}
BOOL run_geq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tGEQ ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_GEQ);
return FALSE;
}
BOOL run_less(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tLESS ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_LESS);
return FALSE;
}
BOOL run_greater(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tGREATER ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 arg1 = safe_op_index(arg >> 4);
U8 arg2 = safe_op_index(arg & 0xf);
if (b_print)
{
print_type(arg1);
printf(", ");
print_type(arg2);
printf("\n");
}
binary_operations[arg1][arg2](buffer, LOPC_GREATER);
return FALSE;
}
BOOL run_bitand(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tBITAND\n", offset);
offset++;
binary_operations[LST_INTEGER][LST_INTEGER](buffer, LOPC_BITAND);
return FALSE;
}
BOOL run_bitor(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tBITOR\n", offset);
offset++;
binary_operations[LST_INTEGER][LST_INTEGER](buffer, LOPC_BITOR);
return FALSE;
}
BOOL run_bitxor(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tBITXOR\n", offset);
offset++;
binary_operations[LST_INTEGER][LST_INTEGER](buffer, LOPC_BITXOR);
return FALSE;
}
BOOL run_booland(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tBOOLAND\n", offset);
offset++;
binary_operations[LST_INTEGER][LST_INTEGER](buffer, LOPC_BOOLAND);
return FALSE;
}
BOOL run_boolor(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tBOOLOR\n", offset);
offset++;
binary_operations[LST_INTEGER][LST_INTEGER](buffer, LOPC_BOOLOR);
return FALSE;
}
BOOL run_shl(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSHL\n", offset);
offset++;
binary_operations[LST_INTEGER][LST_INTEGER](buffer, LOPC_SHL);
return FALSE;
}
BOOL run_shr(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSHR\n", offset);
offset++;
binary_operations[LST_INTEGER][LST_INTEGER](buffer, LOPC_SHR);
return FALSE;
}
void integer_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
S32 lside = lscript_pop_int(buffer);
S32 result = 0;
switch(opcode)
{
case LOPC_NEG:
result = -lside;
break;
case LOPC_BITNOT:
result = ~lside;
break;
case LOPC_BOOLNOT:
result = !lside;
break;
default:
break;
}
lscript_push(buffer, result);
}
void float_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
F32 lside = lscript_pop_float(buffer);
F32 result = 0;
switch(opcode)
{
case LOPC_NEG:
result = -lside;
lscript_push(buffer, result);
break;
default:
break;
}
}
void vector_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
LLVector3 lside;
lscript_pop_vector(buffer, lside);
LLVector3 result;
switch(opcode)
{
case LOPC_NEG:
result = -lside;
lscript_push(buffer, result);
break;
default:
break;
}
}
void quaternion_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode)
{
LLQuaternion lside;
lscript_pop_quaternion(buffer, lside);
LLQuaternion result;
switch(opcode)
{
case LOPC_NEG:
result = -lside;
lscript_push(buffer, result);
break;
default:
break;
}
}
BOOL run_neg(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tNEG ", offset);
offset++;
U8 arg = safe_op_index(safe_instruction_bytestream2byte(buffer, offset));
if (b_print)
{
print_type(arg);
printf("\n");
}
unary_operations[arg](buffer, LOPC_NEG);
return FALSE;
}
BOOL run_bitnot(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tBITNOT\n", offset);
offset++;
unary_operations[LST_INTEGER](buffer, LOPC_BITNOT);
return FALSE;
}
BOOL run_boolnot(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tBOOLNOT\n", offset);
offset++;
unary_operations[LST_INTEGER](buffer, LOPC_BOOLNOT);
return FALSE;
}
BOOL run_jump(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tJUMP ", offset);
offset++;
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("%d\n", arg);
offset += arg;
return FALSE;
}
BOOL run_jumpif(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tJUMPIF ", offset);
offset++;
U8 type = safe_instruction_bytestream2byte(buffer, offset);
if (b_print)
{
print_type(type);
printf(", ");
}
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("%d\n", arg);
if (type == LST_INTEGER)
{
S32 test = lscript_pop_int(buffer);
if (test)
{
offset += arg;
}
}
else if (type == LST_FLOATINGPOINT)
{
F32 test = lscript_pop_float(buffer);
if (test)
{
offset += arg;
}
}
else if (type == LST_VECTOR)
{
LLVector3 test;
lscript_pop_vector(buffer, test);
if (!test.isExactlyZero())
{
offset += arg;
}
}
else if (type == LST_QUATERNION)
{
LLQuaternion test;
lscript_pop_quaternion(buffer, test);
if (!test.isIdentity())
{
offset += arg;
}
}
else if (type == LST_STRING)
{
S32 base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to
// local variables can result in lack of initialization and
// function clean up of ref counts isn't based on scope (a
// mistake, I know)
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
S32 string = address;
string += SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
char *sdata = new char[size];
bytestream2char(sdata, buffer, string, size);
if (strlen(sdata)) /*Flawfinder: ignore*/
{
offset += arg;
}
delete [] sdata;
}
lsa_decrease_ref_count(buffer, base_address);
}
}
else if (type == LST_KEY)
{
S32 base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to
// local variables can result in lack of initialization and
// function clean up of ref counts isn't based on scope (a
// mistake, I know)
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
S32 string = address;
string += SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
char *sdata = new char[size];
bytestream2char(sdata, buffer, string, size);
if (strlen(sdata)) /*Flawfinder: ignore*/
{
LLUUID id;
if (id.set(sdata) && id.notNull())
offset += arg;
}
delete [] sdata;
}
lsa_decrease_ref_count(buffer, base_address);
}
}
else if (type == LST_LIST)
{
S32 base_address = lscript_pop_int(buffer);
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
if (safe_heap_check_address(buffer, address + SIZEOF_SCRIPT_ALLOC_ENTRY, 1))
{
LLScriptLibData *list = lsa_get_list_ptr(buffer, base_address, TRUE);
if (list && list->getListLength())
{
offset += arg;
}
delete list;
}
}
}
return FALSE;
}
BOOL run_jumpnif(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tJUMPNIF ", offset);
offset++;
U8 type = safe_instruction_bytestream2byte(buffer, offset);
if (b_print)
{
print_type(type);
printf(", ");
}
S32 arg = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("%d\n", arg);
if (type == LST_INTEGER)
{
S32 test = lscript_pop_int(buffer);
if (!test)
{
offset += arg;
}
}
else if (type == LST_FLOATINGPOINT)
{
F32 test = lscript_pop_float(buffer);
if (!test)
{
offset += arg;
}
}
else if (type == LST_VECTOR)
{
LLVector3 test;
lscript_pop_vector(buffer, test);
if (test.isExactlyZero())
{
offset += arg;
}
}
else if (type == LST_QUATERNION)
{
LLQuaternion test;
lscript_pop_quaternion(buffer, test);
if (test.isIdentity())
{
offset += arg;
}
}
else if (type == LST_STRING)
{
S32 base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to
// local variables can result in lack of initialization and
// function clean up of ref counts isn't based on scope (a
// mistake, I know)
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
S32 string = address;
string += SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
char *sdata = new char[size];
bytestream2char(sdata, buffer, string, size);
if (!strlen(sdata)) /*Flawfinder: ignore*/
{
offset += arg;
}
delete [] sdata;
}
lsa_decrease_ref_count(buffer, base_address);
}
}
else if (type == LST_KEY)
{
S32 base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to
// local variables can result in lack of initialization and
// function clean up of ref counts isn't based on scope (a
// mistake, I know)
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
S32 string = address;
string += SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
char *sdata = new char[size];
bytestream2char(sdata, buffer, string, size);
if (strlen(sdata)) /*Flawfinder: ignore*/
{
LLUUID id;
if (!id.set(sdata) || id.isNull())
offset += arg;
}
else
{
offset += arg;
}
delete [] sdata;
}
lsa_decrease_ref_count(buffer, base_address);
}
}
else if (type == LST_LIST)
{
S32 base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to
// local variables can result in lack of initialization and
// function clean up of ref counts isn't based on scope (a
// mistake, I know)
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
if (safe_heap_check_address(buffer, address + SIZEOF_SCRIPT_ALLOC_ENTRY, 1))
{
LLScriptLibData *list = lsa_get_list_ptr(buffer, base_address, TRUE);
if (!list || !list->getListLength())
{
offset += arg;
}
delete list;
}
}
}
return FALSE;
}
BOOL run_state(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tSTATE ", offset);
offset++;
S32 state = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("%d\n", state);
S32 bp = lscript_pop_int(buffer);
set_bp(buffer, bp);
offset = lscript_pop_int(buffer);
S32 major_version = 0;
S32 value = get_register(buffer, LREG_VN);
if (value == LSL2_VERSION1_END_NUMBER)
{
major_version = 1;
}
else if (value == LSL2_VERSION_NUMBER)
{
major_version = 2;
}
S32 current_state = get_register(buffer, LREG_CS);
if (state != current_state)
{
U64 ce = get_event_register(buffer, LREG_CE, major_version);
ce |= LSCRIPTStateBitField[LSTT_STATE_EXIT];
set_event_register(buffer, LREG_CE, ce, major_version);
}
set_register(buffer, LREG_NS, state);
return FALSE;
}
BOOL run_call(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tCALL ", offset);
offset++;
S32 func = safe_instruction_bytestream2integer(buffer, offset);
if (b_print)
printf("%d\n", func);
lscript_local_store(buffer, -8, offset);
S32 minimum = get_register(buffer, LREG_GFR);
S32 maximum = get_register(buffer, LREG_SR);
S32 lookup = minimum + func*4 + 4;
S32 function;
if ( (lookup >= minimum)
&&(lookup < maximum))
{
function = bytestream2integer(buffer, lookup) + minimum;
if ( (lookup >= minimum)
&&(lookup < maximum))
{
offset = function;
offset += bytestream2integer(buffer, function);
}
else
{
set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
}
}
else
{
set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
}
return FALSE;
}
BOOL run_return(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tRETURN\n", offset);
offset++;
// SEC-53: babbage: broken instructions may allow inbalanced pushes and
// pops which can cause caller BP and return IP to be corrupted, so restore
// SP from BP before popping caller BP and IP.
S32 bp = get_register(buffer, LREG_BP);
set_sp(buffer, bp);
bp = lscript_pop_int(buffer);
set_bp(buffer, bp);
offset = lscript_pop_int(buffer);
return FALSE;
}
BOOL run_cast(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
char caststr[1024]; /*Flawfinder: ignore*/
if (b_print)
printf("[0x%X]\tCAST ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
U8 from = arg >> 4;
U8 to = arg & 0xf;
if (b_print)
{
print_type(from);
printf(", ");
print_type(to);
printf("\n");
}
switch(from)
{
case LST_INTEGER:
{
switch(to)
{
case LST_INTEGER:
break;
case LST_FLOATINGPOINT:
{
S32 source = lscript_pop_int(buffer);
F32 dest = (F32)source;
lscript_push(buffer, dest);
}
break;
case LST_STRING:
{
S32 address, source = lscript_pop_int(buffer);
snprintf(caststr, sizeof(caststr), "%d", source); /* Flawfinder: ignore */
address = lsa_heap_add_data(buffer, new LLScriptLibData(caststr), get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
}
break;
case LST_LIST:
{
S32 address, source = lscript_pop_int(buffer);
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(source);
address = lsa_heap_add_data(buffer, list, get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
}
break;
default:
break;
}
}
break;
case LST_FLOATINGPOINT:
{
switch(to)
{
case LST_INTEGER:
{
F32 source = lscript_pop_float(buffer);
S32 dest = (S32)source;
lscript_push(buffer, dest);
}
break;
case LST_FLOATINGPOINT:
break;
case LST_STRING:
{
S32 address;
F32 source = lscript_pop_float(buffer);
snprintf(caststr, sizeof(caststr), "%f", source); /* Flawfinder: ignore */
address = lsa_heap_add_data(buffer, new LLScriptLibData(caststr), get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
}
break;
case LST_LIST:
{
S32 address;
F32 source = lscript_pop_float(buffer);
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(source);
address = lsa_heap_add_data(buffer, list, get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
}
break;
default:
break;
}
}
break;
case LST_STRING:
{
switch(to)
{
case LST_INTEGER:
{
S32 base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
// and function clean up of ref counts isn't based on scope (a mistake, I know)
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
S32 string = address;
string += SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
char *arg = new char[size];
bytestream2char(arg, buffer, string, size);
// S32 length = strlen(arg);
S32 dest;
S32 base;
// Check to see if this is a hexidecimal number.
if ( (arg[0] == '0') &&
(arg[1] == 'x' || arg[1] == 'X') )
{
// Let strtoul do a hex conversion.
base = 16;
}
else
{
// Force base-10, so octal is never used.
base = 10;
}
dest = strtoul(arg, NULL, base);
lscript_push(buffer, dest);
delete [] arg;
}
lsa_decrease_ref_count(buffer, base_address);
}
}
break;
case LST_FLOATINGPOINT:
{
S32 base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
// and function clean up of ref counts isn't based on scope (a mistake, I know)
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
S32 string = address;
string += SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
char *arg = new char[size];
bytestream2char(arg, buffer, string, size);
F32 dest = (F32)atof(arg);
lscript_push(buffer, dest);
delete [] arg;
}
lsa_decrease_ref_count(buffer, base_address);
}
}
break;
case LST_STRING:
break;
case LST_LIST:
{
S32 saddress = lscript_pop_int(buffer);
LLScriptLibData *string = lsa_get_data(buffer, saddress, TRUE);
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = string;
S32 address = lsa_heap_add_data(buffer, list, get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
}
break;
case LST_VECTOR:
{
S32 base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
// and function clean up of ref counts isn't based on scope (a mistake, I know)
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
S32 string = address;
string += SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
char *arg = new char[size];
bytestream2char(arg, buffer, string, size);
LLVector3 vec;
S32 num = sscanf(arg, "<%f, %f, %f>", &vec.mV[VX], &vec.mV[VY], &vec.mV[VZ]);
if (num != 3)
{
vec = LLVector3::zero;
}
lscript_push(buffer, vec);
delete [] arg;
}
lsa_decrease_ref_count(buffer, base_address);
}
}
break;
case LST_QUATERNION:
{
S32 base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
// and function clean up of ref counts isn't based on scope (a mistake, I know)
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
S32 string = address;
string += SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
char *arg = new char[size];
bytestream2char(arg, buffer, string, size);
LLQuaternion quat;
S32 num = sscanf(arg, "<%f, %f, %f, %f>", &quat.mQ[VX], &quat.mQ[VY], &quat.mQ[VZ], &quat.mQ[VW]);
if (num != 4)
{
quat = LLQuaternion::DEFAULT;
}
lscript_push(buffer, quat);
delete [] arg;
}
lsa_decrease_ref_count(buffer, base_address);
}
}
break;
default:
break;
}
}
break;
case LST_KEY:
{
switch(to)
{
case LST_KEY:
break;
case LST_STRING:
break;
case LST_LIST:
{
S32 saddress = lscript_pop_int(buffer);
LLScriptLibData *string = lsa_get_data(buffer, saddress, TRUE);
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = string;
S32 address = lsa_heap_add_data(buffer, list, get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
}
break;
default:
break;
}
}
break;
case LST_VECTOR:
{
switch(to)
{
case LST_VECTOR:
break;
case LST_STRING:
{
S32 address;
LLVector3 source;
lscript_pop_vector(buffer, source);
snprintf(caststr, sizeof(caststr), "<%5.5f, %5.5f, %5.5f>", source.mV[VX], source.mV[VY], source.mV[VZ]); /* Flawfinder: ignore */
address = lsa_heap_add_data(buffer, new LLScriptLibData(caststr), get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
}
break;
case LST_LIST:
{
S32 address;
LLVector3 source;
lscript_pop_vector(buffer, source);
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(source);
address = lsa_heap_add_data(buffer, list, get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
}
break;
default:
break;
}
}
break;
case LST_QUATERNION:
{
switch(to)
{
case LST_QUATERNION:
break;
case LST_STRING:
{
S32 address;
LLQuaternion source;
lscript_pop_quaternion(buffer, source);
snprintf(caststr, sizeof(caststr), "<%5.5f, %5.5f, %5.5f, %5.5f>", source.mQ[VX], source.mQ[VY], source.mQ[VZ], source.mQ[VS]); /* Flawfinder: ignore */
address = lsa_heap_add_data(buffer, new LLScriptLibData(caststr), get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
}
break;
case LST_LIST:
{
S32 address;
LLQuaternion source;
lscript_pop_quaternion(buffer, source);
LLScriptLibData *list = new LLScriptLibData;
list->mType = LST_LIST;
list->mListp = new LLScriptLibData(source);
address = lsa_heap_add_data(buffer, list, get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
}
break;
default:
break;
}
}
break;
case LST_LIST:
{
switch(to)
{
case LST_LIST:
break;
case LST_STRING:
{
S32 address = lscript_pop_int(buffer);
LLScriptLibData *list = lsa_get_data(buffer, address, TRUE);
LLScriptLibData *list_root = list;
std::ostringstream dest;
while (list)
{
list->print(dest, FALSE);
list = list->mListp;
}
delete list_root;
char *tmp = strdup(dest.str().c_str());
LLScriptLibData *string = new LLScriptLibData(tmp);
free(tmp);
tmp = NULL;
S32 destaddress = lsa_heap_add_data(buffer, string, get_max_heap_size(buffer), TRUE);
lscript_push(buffer, destaddress);
}
break;
default:
break;
}
}
break;
default:
break;
}
return FALSE;
}
BOOL run_stacktos(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
offset++;
S32 length = lscript_pop_int(buffer);
S32 i;
char *arg = new char[length];
S32 fault;
for (i = 0; i < length; i++)
{
fault = get_register(buffer, LREG_FR);
if (fault)
break;
arg[length - i - 1] = lscript_pop_char(buffer);
}
S32 address = lsa_heap_add_data(buffer, new LLScriptLibData(arg), get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
delete [] arg;
return FALSE;
}
void lscript_stacktol_pop_variable(LLScriptLibData *data, U8 *buffer, char type)
{
S32 address, string;
S32 base_address;
switch(type)
{
case LST_INTEGER:
data->mType = LST_INTEGER;
data->mInteger = lscript_pop_int(buffer);
break;
case LST_FLOATINGPOINT:
data->mType = LST_FLOATINGPOINT;
data->mFP = lscript_pop_float(buffer);
break;
case LST_KEY:
data->mType = LST_KEY;
base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
// and function clean up of ref counts isn't based on scope (a mistake, I know)
address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
string = address + SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
data->mKey = new char[size];
bytestream2char(data->mKey, buffer, string, size);
}
lsa_decrease_ref_count(buffer, base_address);
}
else
{
data->mKey = new char[1];
data->mKey[0] = 0;
}
break;
case LST_STRING:
data->mType = LST_STRING;
base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
// and function clean up of ref counts isn't based on scope (a mistake, I know)
address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
string = address + SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
data->mString = new char[size];
bytestream2char(data->mString, buffer, string, size);
}
lsa_decrease_ref_count(buffer, base_address);
}
else
{
data->mString = new char[1];
data->mString[0] = 0;
}
break;
case LST_VECTOR:
data->mType = LST_VECTOR;
lscript_pop_vector(buffer, data->mVec);
break;
case LST_QUATERNION:
data->mType = LST_QUATERNION;
lscript_pop_quaternion(buffer, data->mQuat);
break;
case LST_LIST:
data->mType = LST_LIST;
address = lscript_pop_int(buffer);
data->mListp = lsa_get_data(buffer, address, TRUE);
break;
}
}
BOOL run_stacktol(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
offset++;
S32 length = safe_instruction_bytestream2integer(buffer, offset);
S32 i;
S32 fault;
S8 type;
LLScriptLibData *data = new LLScriptLibData, *tail;
data->mType = LST_LIST;
for (i = 0; i < length; i++)
{
fault = get_register(buffer, LREG_FR);
if (fault)
break;
type = lscript_pop_char(buffer);
tail = new LLScriptLibData;
lscript_stacktol_pop_variable(tail, buffer, type);
tail->mListp = data->mListp;
data->mListp = tail;
}
S32 address = lsa_heap_add_data(buffer,data, get_max_heap_size(buffer), TRUE);
lscript_push(buffer, address);
return FALSE;
}
BOOL run_print(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tPRINT ", offset);
offset++;
U8 type = safe_instruction_bytestream2byte(buffer, offset);
if (b_print)
{
print_type(type);
printf("\n");
}
switch(type)
{
case LST_INTEGER:
{
S32 source = lscript_pop_int(buffer);
printf("%d\n", source);
}
break;
case LST_FLOATINGPOINT:
{
F32 source = lscript_pop_float(buffer);
printf("%f\n", source);
}
break;
case LST_STRING:
{
S32 base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
// and function clean up of ref counts isn't based on scope (a mistake, I know)
S32 address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
S32 string = address;
string += SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
char *arg = new char[size];
bytestream2char(arg, buffer, string, size);
printf("%s\n", arg);
delete [] arg;
}
lsa_decrease_ref_count(buffer, base_address);
}
}
break;
case LST_VECTOR:
{
LLVector3 source;
lscript_pop_vector(buffer, source);
printf("< %f, %f, %f >\n", source.mV[VX], source.mV[VY], source.mV[VZ]);
}
break;
case LST_QUATERNION:
{
LLQuaternion source;
lscript_pop_quaternion(buffer, source);
printf("< %f, %f, %f, %f >\n", source.mQ[VX], source.mQ[VY], source.mQ[VZ], source.mQ[VS]);
}
break;
case LST_LIST:
{
S32 base_address = lscript_pop_int(buffer);
LLScriptLibData *data = lsa_get_data(buffer, base_address, TRUE);
LLScriptLibData *print = data;
printf("list\n");
while (print)
{
switch(print->mType)
{
case LST_INTEGER:
{
printf("%d\n", print->mInteger);
}
break;
case LST_FLOATINGPOINT:
{
printf("%f\n", print->mFP);
}
break;
case LST_STRING:
{
printf("%s\n", print->mString);
}
break;
case LST_KEY:
{
printf("%s\n", print->mKey);
}
break;
case LST_VECTOR:
{
printf("< %f, %f, %f >\n", print->mVec.mV[VX], print->mVec.mV[VY], print->mVec.mV[VZ]);
}
break;
case LST_QUATERNION:
{
printf("< %f, %f, %f, %f >\n", print->mQuat.mQ[VX], print->mQuat.mQ[VY], print->mQuat.mQ[VZ], print->mQuat.mQ[VS]);
}
break;
default:
break;
}
print = print->mListp;
}
delete data;
}
break;
default:
break;
}
return FALSE;
}
void lscript_run(const std::string& filename, BOOL b_debug)
{
LLTimer timer;
const char *error;
LLScriptExecuteLSL2 *execute = NULL;
if (filename.empty())
{
llerrs << "filename is NULL" << llendl;
// Just reporting error is likely not enough. Need
// to check how to abort or error out gracefully
// from this function. XXXTBD
}
LLFILE* file = LLFile::fopen(filename, "r"); /* Flawfinder: ignore */
if(file)
{
execute = new LLScriptExecuteLSL2(file);
fclose(file);
}
if (execute)
{
timer.reset();
F32 time_slice = 3600.0f; // 1 hr.
U32 events_processed = 0;
do {
LLTimer timer2;
execute->runQuanta(b_debug, LLUUID::null, &error,
time_slice, events_processed, timer2);
} while (!execute->isFinished());
F32 time = timer.getElapsedTimeF32();
F32 ips = execute->mInstructionCount / time;
llinfos << execute->mInstructionCount << " instructions in " << time << " seconds" << llendl;
llinfos << ips/1000 << "K instructions per second" << llendl;
printf("ip: 0x%X\n", get_register(execute->mBuffer, LREG_IP));
printf("sp: 0x%X\n", get_register(execute->mBuffer, LREG_SP));
printf("bp: 0x%X\n", get_register(execute->mBuffer, LREG_BP));
printf("hr: 0x%X\n", get_register(execute->mBuffer, LREG_HR));
printf("hp: 0x%X\n", get_register(execute->mBuffer, LREG_HP));
delete execute;
fclose(file);
}
}
void lscript_pop_variable(LLScriptLibData *data, U8 *buffer, char type)
{
S32 address, string;
S32 base_address;
switch(type)
{
case 'i':
data->mType = LST_INTEGER;
data->mInteger = lscript_pop_int(buffer);
break;
case 'f':
data->mType = LST_FLOATINGPOINT;
data->mFP = lscript_pop_float(buffer);
break;
case 'k':
data->mType = LST_KEY;
data->mKey = NULL;
base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
// and function clean up of ref counts isn't based on scope (a mistake, I know)
address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
string = address + SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
data->mKey = new char[size];
bytestream2char(data->mKey, buffer, string, size);
}
lsa_decrease_ref_count(buffer, base_address);
}
if (data->mKey == NULL)
{
data->mKey = new char[1];
data->mKey[0] = 0;
}
break;
case 's':
data->mType = LST_STRING;
data->mString = NULL;
base_address = lscript_pop_int(buffer);
// this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
// and function clean up of ref counts isn't based on scope (a mistake, I know)
address = base_address + get_register(buffer, LREG_HR) - 1;
if (address)
{
string = address + SIZEOF_SCRIPT_ALLOC_ENTRY;
if (safe_heap_check_address(buffer, string, 1))
{
S32 toffset = string;
safe_heap_bytestream_count_char(buffer, toffset);
S32 size = toffset - string;
data->mString = new char[size];
bytestream2char(data->mString, buffer, string, size);
}
lsa_decrease_ref_count(buffer, base_address);
}
if (data->mString == NULL)
{
data->mString = new char[1];
data->mString[0] = 0;
}
break;
case 'l':
{
S32 base_address = lscript_pop_int(buffer);
data->mType = LST_LIST;
data->mListp = lsa_get_list_ptr(buffer, base_address, TRUE);
}
break;
case 'v':
data->mType = LST_VECTOR;
lscript_pop_vector(buffer, data->mVec);
break;
case 'q':
data->mType = LST_QUATERNION;
lscript_pop_quaternion(buffer, data->mQuat);
break;
}
}
void lscript_push_return_variable(LLScriptLibData *data, U8 *buffer)
{
S32 address;
switch(data->mType)
{
case LST_INTEGER:
lscript_local_store(buffer, -12, data->mInteger);
break;
case LST_FLOATINGPOINT:
lscript_local_store(buffer, -12, data->mFP);
break;
case LST_KEY:
address = lsa_heap_add_data(buffer, data, get_max_heap_size(buffer), FALSE);
lscript_local_store(buffer, -12, address);
break;
case LST_STRING:
address = lsa_heap_add_data(buffer, data, get_max_heap_size(buffer), FALSE);
lscript_local_store(buffer, -12, address);
break;
case LST_LIST:
address = lsa_heap_add_data(buffer, data, get_max_heap_size(buffer), FALSE);
lscript_local_store(buffer, -12, address);
break;
case LST_VECTOR:
lscript_local_store(buffer, -20, data->mVec);
break;
case LST_QUATERNION:
lscript_local_store(buffer, -24, data->mQuat);
break;
default:
break;
}
}
S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer)
{
S32 address;
switch(data->mType)
{
case LST_INTEGER:
lscript_push(buffer, data->mInteger);
break;
case LST_FLOATINGPOINT:
lscript_push(buffer, data->mFP);
return 4;
break;
case LST_KEY:
address = lsa_heap_add_data(buffer, data, get_max_heap_size(buffer), FALSE);
lscript_push(buffer, address);
return 4;
break;
case LST_STRING:
address = lsa_heap_add_data(buffer, data, get_max_heap_size(buffer), FALSE);
lscript_push(buffer, address);
return 4;
break;
case LST_LIST:
address = lsa_heap_add_data(buffer, data, get_max_heap_size(buffer), FALSE);
lscript_push(buffer, address);
return 4;
break;
case LST_VECTOR:
lscript_push(buffer, data->mVec);
return 12;
break;
case LST_QUATERNION:
lscript_push(buffer, data->mQuat);
return 16;
break;
default:
break;
}
return 4;
}
BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tCALLLIB ", offset);
offset++;
U8 arg = safe_instruction_bytestream2byte(buffer, offset);
if (arg >= (U8)gScriptLibrary.mFunctions.size())
{
set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
return FALSE;
}
if (b_print)
printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
// pull out the arguments and the return values
LLScriptLibData *arguments = NULL;
LLScriptLibData *returnvalue = NULL;
S32 i, number;
if (gScriptLibrary.mFunctions[arg].mReturnType)
{
returnvalue = new LLScriptLibData;
}
if (gScriptLibrary.mFunctions[arg].mArgs)
{
number = (S32)strlen(gScriptLibrary.mFunctions[arg].mArgs); /*Flawfinder: ignore*/
arguments = new LLScriptLibData[number];
}
else
{
number = 0;
}
for (i = number - 1; i >= 0; i--)
{
lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg].mArgs[i]);
}
if (b_print)
{
printf("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
}
{
// LLFastTimer time_in_libraries1(LLFastTimer::FTM_TEMP7);
gScriptLibrary.mFunctions[arg].mExecFunc(returnvalue, arguments, id);
}
add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg].mEnergyUse);
add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg].mSleepTime);
if (returnvalue)
{
returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg].mReturnType);
lscript_push_return_variable(returnvalue, buffer);
}
delete [] arguments;
delete returnvalue;
// reset the BP after calling the library files
S32 bp = lscript_pop_int(buffer);
set_bp(buffer, bp);
// pop off the spot for the instruction pointer
lscript_poparg(buffer, 4);
return FALSE;
}
BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
if (b_print)
printf("[0x%X]\tCALLLIB ", offset);
offset++;
U16 arg = safe_instruction_bytestream2u16(buffer, offset);
if (arg >= (U16)gScriptLibrary.mFunctions.size())
{
set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
return FALSE;
}
if (b_print)
printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
// pull out the arguments and the return values
LLScriptLibData *arguments = NULL;
LLScriptLibData *returnvalue = NULL;
S32 i, number;
if (gScriptLibrary.mFunctions[arg].mReturnType)
{
returnvalue = new LLScriptLibData;
}
if (gScriptLibrary.mFunctions[arg].mArgs)
{
number = (S32)strlen(gScriptLibrary.mFunctions[arg].mArgs); /*Flawfinder: ignore*/
arguments = new LLScriptLibData[number];
}
else
{
number = 0;
}
for (i = number - 1; i >= 0; i--)
{
lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg].mArgs[i]);
}
if (b_print)
{
printf("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
}
{
// LLFastTimer time_in_libraries2(LLFastTimer::FTM_TEMP8);
gScriptLibrary.mFunctions[arg].mExecFunc(returnvalue, arguments, id);
}
add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg].mEnergyUse);
add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg].mSleepTime);
if (returnvalue)
{
returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg].mReturnType);
lscript_push_return_variable(returnvalue, buffer);
}
delete [] arguments;
delete returnvalue;
// reset the BP after calling the library files
S32 bp = lscript_pop_int(buffer);
set_bp(buffer, bp);
// pop off the spot for the instruction pointer
lscript_poparg(buffer, 4);
return FALSE;
}