diff options
Diffstat (limited to 'indra/lscript/lscript_execute')
-rw-r--r-- | indra/lscript/lscript_execute/CMakeLists.txt | 6 | ||||
-rw-r--r-- | indra/lscript/lscript_execute/llscriptresource.cpp | 93 | ||||
-rw-r--r-- | indra/lscript/lscript_execute/llscriptresourceconsumer.cpp | 106 | ||||
-rw-r--r-- | indra/lscript/lscript_execute/llscriptresourcepool.cpp | 44 | ||||
-rw-r--r-- | indra/lscript/lscript_execute/lscript_execute.cpp | 1198 | ||||
-rw-r--r-- | indra/lscript/lscript_execute/lscript_heapruntime.cpp | 35 | ||||
-rw-r--r-- | indra/lscript/lscript_execute/lscript_heapruntime.h | 35 | ||||
-rw-r--r-- | indra/lscript/lscript_execute/lscript_readlso.cpp | 51 | ||||
-rw-r--r-- | indra/lscript/lscript_execute/lscript_readlso.h | 35 |
9 files changed, 1067 insertions, 536 deletions
diff --git a/indra/lscript/lscript_execute/CMakeLists.txt b/indra/lscript/lscript_execute/CMakeLists.txt index f30915bab0..3a16ffdc01 100644 --- a/indra/lscript/lscript_execute/CMakeLists.txt +++ b/indra/lscript/lscript_execute/CMakeLists.txt @@ -12,6 +12,9 @@ include_directories( ) set(lscript_execute_SOURCE_FILES + llscriptresource.cpp + llscriptresourceconsumer.cpp + llscriptresourcepool.cpp lscript_execute.cpp lscript_heapruntime.cpp lscript_readlso.cpp @@ -20,6 +23,9 @@ set(lscript_execute_SOURCE_FILES set(lscript_execute_HEADER_FILES CMakeLists.txt + ../llscriptresource.h + ../llscriptresourceconsumer.h + ../llscriptresourcepool.h ../lscript_execute.h ../lscript_rt_interface.h lscript_heapruntime.h diff --git a/indra/lscript/lscript_execute/llscriptresource.cpp b/indra/lscript/lscript_execute/llscriptresource.cpp new file mode 100644 index 0000000000..2c6811b226 --- /dev/null +++ b/indra/lscript/lscript_execute/llscriptresource.cpp @@ -0,0 +1,93 @@ +/** + * @file llscriptresource.cpp + * @brief LLScriptResource class implementation for managing limited resources + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llscriptresource.h" +#include "llerror.h" + +LLScriptResource::LLScriptResource() +: mTotal(0), + mUsed(0) +{ +} + +bool LLScriptResource::request(S32 amount /* = 1 */) +{ + if (mUsed + amount <= mTotal) + { + mUsed += amount; + return true; + } + + return false; +} + +bool LLScriptResource::release(S32 amount /* = 1 */) +{ + if (mUsed >= amount) + { + mUsed -= amount; + return true; + } + + return false; +} + +S32 LLScriptResource::getAvailable() const +{ + if (mUsed > mTotal) + { + // It is possible after a parcel ownership change for more than total to be used + // In this case the user of this class just wants to know + // whether or not they can use a resource + return 0; + } + return (mTotal - mUsed); +} + +void LLScriptResource::setTotal(S32 amount) +{ + // This may cause this resource to be over spent + // such that more are in use than total allowed + // Until those resources are released getAvailable will return 0. + mTotal = amount; +} + +S32 LLScriptResource::getTotal() const +{ + return mTotal; +} + +S32 LLScriptResource::getUsed() const +{ + return mUsed; +} + +bool LLScriptResource::isOverLimit() const +{ + return (mUsed > mTotal); +} diff --git a/indra/lscript/lscript_execute/llscriptresourceconsumer.cpp b/indra/lscript/lscript_execute/llscriptresourceconsumer.cpp new file mode 100644 index 0000000000..55d47b6de2 --- /dev/null +++ b/indra/lscript/lscript_execute/llscriptresourceconsumer.cpp @@ -0,0 +1,106 @@ +/** + * @file llscriptresourceconsumer.cpp + * @brief An interface for a script resource consumer. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llscriptresourceconsumer.h" + +#include "llscriptresourcepool.h" + +LLScriptResourceConsumer::LLScriptResourceConsumer() + : mScriptResourcePool(&LLScriptResourcePool::null) +{ } + +// Get the resource pool this consumer is currently using. +// virtual +LLScriptResourcePool& LLScriptResourceConsumer::getScriptResourcePool() +{ + return *mScriptResourcePool; +} + +// Get the resource pool this consumer is currently using. +// virtual +const LLScriptResourcePool& LLScriptResourceConsumer::getScriptResourcePool() const +{ + return *mScriptResourcePool; +} + +// virtual +void LLScriptResourceConsumer::setScriptResourcePool(LLScriptResourcePool& new_pool) +{ + mScriptResourcePool = &new_pool; +} + +bool LLScriptResourceConsumer::switchScriptResourcePools(LLScriptResourcePool& new_pool) +{ + if (&new_pool == &LLScriptResourcePool::null) + { + llwarns << "New pool is null" << llendl; + } + + if (isInPool(new_pool)) + { + return true; + } + + if (!canUseScriptResourcePool(new_pool)) + { + return false; + } + + S32 used_urls = getUsedPublicURLs(); + + getScriptResourcePool().getPublicURLResource().release( used_urls ); + setScriptResourcePool(new_pool); + getScriptResourcePool().getPublicURLResource().request( used_urls ); + + return true; +} + +bool LLScriptResourceConsumer::canUseScriptResourcePool(const LLScriptResourcePool& resource_pool) +{ + if (isInPool(resource_pool)) + { + return true; + } + + if (resource_pool.getPublicURLResource().getAvailable() < getUsedPublicURLs()) + { + return false; + } + + return true; +} + +bool LLScriptResourceConsumer::isInPool(const LLScriptResourcePool& resource_pool) +{ + const LLScriptResourcePool& current_pool = getScriptResourcePool(); + if ( &resource_pool == ¤t_pool ) + { + // This consumer is already in this pool + return true; + } + return false; +} + diff --git a/indra/lscript/lscript_execute/llscriptresourcepool.cpp b/indra/lscript/lscript_execute/llscriptresourcepool.cpp new file mode 100644 index 0000000000..6bdc2bbd48 --- /dev/null +++ b/indra/lscript/lscript_execute/llscriptresourcepool.cpp @@ -0,0 +1,44 @@ +/** + * @file llscriptresourcepool.cpp + * @brief Collection of limited script resources + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llscriptresourcepool.h" + +LLScriptResourcePool LLScriptResourcePool::null; + +LLScriptResourcePool::LLScriptResourcePool() +{ + +} + +LLScriptResource& LLScriptResourcePool::getPublicURLResource() +{ + return mLSLPublicURLs; +} + +const LLScriptResource& LLScriptResourcePool::getPublicURLResource() const +{ + return mLSLPublicURLs; +} diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp index 77e24cd8f4..d79e9f8bde 100644 --- a/indra/lscript/lscript_execute/lscript_execute.cpp +++ b/indra/lscript/lscript_execute/lscript_execute.cpp @@ -2,35 +2,31 @@ * @file lscript_execute.cpp * @brief classes to execute bytecode * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2007, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * 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://secondlife.com/developers/opensource/gplv2 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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://secondlife.com/developers/opensource/flossexception + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * 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. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "linden_common.h" +#include <algorithm> #include <sstream> #include "lscript_execute.h" @@ -39,13 +35,19 @@ #include "lscript_library.h" #include "lscript_heapruntime.h" #include "lscript_alloc.h" +#include "llstat.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, + "Invalid", // LSRF_INVALID, "Math Error", // LSRF_MATH, "Stack-Heap Collision", // LSRF_STACK_HEAP_COLLISION, "Bounds Check Error", // LSRF_BOUND_CHECK_ERROR, @@ -55,16 +57,23 @@ const char* LSCRIPTRunTimeFaultStrings[LSRF_EOF] = /*Flawfinder: ignore*/ "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, + "Lists may not contain lists", // LSRF_NESTING_LISTS, + "CLI Exception" // LSRF_CLI }; -//static -S64 LLScriptExecute::sGlobalInstructionCount = 0; +void LLScriptExecuteLSL2::startRunning() {} +void LLScriptExecuteLSL2::stopRunning() {} + +const char* URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED"; +const char* URL_REQUEST_DENIED = "URL_REQUEST_DENIED"; -LLScriptExecute::LLScriptExecute(LLFILE *fp) +// HTTP Requests to LSL scripts will time out after 25 seconds. +const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC = 25 * USEC_PER_SEC; + +LLScriptExecuteLSL2::LLScriptExecuteLSL2(LLFILE *fp) { U8 sizearray[4]; - S32 filesize; + size_t filesize; S32 pos = 0; if (fread(&sizearray, 1, 4, fp) != 4) { @@ -84,19 +93,27 @@ LLScriptExecute::LLScriptExecute(LLFILE *fp) init(); } -LLScriptExecute::LLScriptExecute(U8 *buffer) +LLScriptExecuteLSL2::LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size) { - mBuffer = buffer; - + 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(); } -LLScriptExecute::~LLScriptExecute() +LLScriptExecute::~LLScriptExecute() {} +LLScriptExecuteLSL2::~LLScriptExecuteLSL2() { - delete [] mBuffer; + delete[] mBuffer; + delete[] mBytecode; } -void LLScriptExecute::init() +void LLScriptExecuteLSL2::init() { S32 i, j; @@ -270,7 +287,7 @@ void LLScriptExecute::init() // Utility routine for when there's a boundary error parsing bytecode -void LLScriptExecute::recordBoundaryError( const LLUUID &id ) +void LLScriptExecuteLSL2::recordBoundaryError( const LLUUID &id ) { set_fault(mBuffer, LSRF_BOUND_CHECK_ERROR); llwarns << "Script boundary error for ID " << id << llendl; @@ -278,7 +295,7 @@ void LLScriptExecute::recordBoundaryError( const LLUUID &id ) // set IP to the event handler with some error checking -void LLScriptExecute::setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEventType event, const LLUUID &id ) +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 ) @@ -296,12 +313,499 @@ void LLScriptExecute::setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEv S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer); -U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, const char **errorstr, BOOL &state_transition) +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 - state_transition = FALSE; - S32 value = get_register(mBuffer, LREG_VN); + S32 value = getVersion(); S32 major_version = 0; if (value == LSL2_VERSION1_END_NUMBER) { @@ -313,323 +817,156 @@ U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, const char **errorstr, } else { - set_fault(mBuffer, LSRF_VERSION_MISMATCH); + setFault(LSRF_VERSION_MISMATCH); } - value = get_register(mBuffer, LREG_FR); - if (value) + value = getFaults(); + if (value > LSRF_INVALID && value < LSRF_EOF) { if (b_print) { printf("Error!\n"); } *errorstr = LSCRIPTRunTimeFaultStrings[value]; - return NO_DELETE_FLAG; + return; } else { *errorstr = NULL; } - // Get IP - // is IP nonzero? - value = get_register(mBuffer, LREG_IP); - - if (value) + if (! isFinished()) { - // if yes, we're in opcodes, execute the next opcode by: - // call opcode run function pointer with buffer and IP - mInstructionCount++; - sGlobalInstructionCount++; - S32 tvalue = value; - S32 opcode = safe_instruction_bytestream2byte(mBuffer, tvalue); - S32 b_ret_val = 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)); - } - // update IP - if (b_ret_val) - { - return DELETE_FLAG | CREDIT_MONEY_FLAG; - } - else - { - return NO_DELETE_FLAG; - } + resumeEventHandler(b_print, id, quanta); + return; } else { // make sure that IE is zero - set_event_register(mBuffer, LREG_IE, 0, major_version); - - // if no, we're in a state and waiting for an event - S32 next_state = get_register(mBuffer, LREG_NS); - S32 current_state = get_register(mBuffer, LREG_CS); - U64 current_events = get_event_register(mBuffer, LREG_CE, major_version); - U64 event_register = get_event_register(mBuffer, LREG_ER, major_version); - // check NS to see if need to switch states (NS != CS) - if (next_state != current_state) + 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()) { - state_transition = TRUE; // ok, blow away any pending events - mEventData.mEventDataList.deleteAllData(); + deleteAllEvents(); - // if yes, check state exit flag is set + // if yes, check state exit flag is set if (current_events & LSCRIPTStateBitField[LSTT_STATE_EXIT]) { - // if yes, clear state exit flag - set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[LSTT_STATE_EXIT], major_version); + // if yes, clear state exit flag + setCurrentHandler(LSCRIPTStateBitField[LSTT_STATE_EXIT]); current_events &= ~LSCRIPTStateBitField[LSTT_STATE_EXIT]; - set_event_register(mBuffer, LREG_CE, current_events, major_version); - // check state exit event handler - // if there is a handler, call it + setCurrentEvents(current_events); + + // check state exit event handler + // if there is a handler, call it if (event_register & LSCRIPTStateBitField[LSTT_STATE_EXIT]) { - // 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); - if ( additional_size == -1 ) - { - recordBoundaryError( id ); - } - else - { - lscript_pusharge(mBuffer, additional_size); - - sp = get_register(mBuffer, LREG_SP); - sp += additional_size; - set_bp(mBuffer, sp); - // set IP to the event handler - setStateEventOpcoodeStartSafely( current_state, LSTT_STATE_EXIT, id ); - } - return NO_DELETE_FLAG; + ++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 + + // 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]; - set_event_register(mBuffer, LREG_CE, current_events, major_version); - // copy NS to CS - set_register(mBuffer, LREG_CS, next_state); - // copy new state's handled events into ER (SR + CS*4 + 4) - U64 handled_events = get_handled_events(mBuffer, next_state); - set_event_register(mBuffer, LREG_ER, handled_events, major_version); + setCurrentEvents(current_events); + + U64 handled_events = nextState(); + setEventHandlers(handled_events); } -// check to see if any current events are covered by events handled by this state (CE & ER != 0) -// now, we want to look like we were called like a function -// 0x0000: 00 00 00 00 (return ip) -// 0x0004: bp (current sp) -// 0x0008: parameters -// push sp -// add parameter size -// pop bp -// set ip - - S32 size = 0; -// try to get next event from stack + + // try to get next event from stack BOOL b_done = FALSE; LSCRIPTStateEventType event = LSTT_NULL; - LLScriptDataCollection *eventdata; - next_state = get_register(mBuffer, LREG_NS); - current_state = get_register(mBuffer, LREG_CS); - current_events = get_event_register(mBuffer, LREG_CE, major_version); - event_register = get_event_register(mBuffer, LREG_ER, major_version); + 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]) + if ((current_events & LSCRIPTStateBitField[LSTT_STATE_ENTRY]) &&(current_events & event_register)) { - // ok, this is easy since there isn't any data waiting, just set it - // 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); - if ( additional_size == -1 ) - { // b_done will be set, so we'll exit the loop at the bottom - recordBoundaryError( id ); - } - else - { - additional_size -= 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 - setStateEventOpcoodeStartSafely( current_state, event, id ); - } + ++events_processed; + callEventHandler(LSTT_STATE_ENTRY, id, quanta); b_done = TRUE; } - else if ( (current_events & LSCRIPTStateBitField[LSTT_REZ]) - &&(current_events & event_register)) + else if ((current_events & LSCRIPTStateBitField[LSTT_REZ]) + &&(current_events & event_register)) { - for (eventdata = mEventData.mEventDataList.getFirstData(); eventdata; eventdata = mEventData.mEventDataList.getNextData()) - { - if (eventdata->mType & LSCRIPTStateBitField[LSTT_REZ]) - { - // 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); - - set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], 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; - while (data->mType) - { - size += lscript_push_variable(data, mBuffer); - data++; - } - // now, push any additional stack space - S32 additional_size = get_event_stack_size(mBuffer, current_state, event); - if ( additional_size == -1 ) - { // b_done will be set, so we'll exit the loop at the bottom - recordBoundaryError( id ); - } - else - { - additional_size -= 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 - setStateEventOpcoodeStartSafely( current_state, event, id ); - mEventData.mEventDataList.deleteCurrentData(); - } - b_done = TRUE; - break; - } - } + ++events_processed; + callQueuedEventHandler(LSTT_REZ, id, quanta); + b_done = TRUE; } - while (!b_done) + if (!b_done) { - eventdata = mEventData.getNextEvent(); - if (eventdata) + // Call handler for next queued event. + if(getEventCount() > 0) { - 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); - - set_event_register(mBuffer, LREG_IE, LSCRIPTStateBitField[event], 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; - while (data->mType) - { - size += lscript_push_variable(data, mBuffer); - data++; - } - b_done = TRUE; - // now, push any additional stack space - S32 additional_size = get_event_stack_size(mBuffer, current_state, event); - if ( additional_size == -1 ) - { // b_done was just set, so we'll exit the loop at the bottom - recordBoundaryError( id ); - } - else - { - additional_size -= 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 - setStateEventOpcoodeStartSafely( current_state, event, id ); - } - } - else - { - llwarns << "Shit, somehow got an event that we're not registered for!" << llendl; - } - delete eventdata; + ++events_processed; + callNextQueuedEventHandler(event_register, id, quanta); } else { -// if no data waiting, do it the old way: + // if no data waiting, do it the old way: U64 handled_current = current_events & event_register; if (handled_current) { - // 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)handled_current); - 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); - if ( additional_size == -1 ) - { // b_done will be set, so we'll exit the loop at the bottom - recordBoundaryError( id ); - } - else - { - additional_size -= 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 - setStateEventOpcoodeStartSafely( current_state, event, id ); - } + ++events_processed; + callEventHandler(event, id, quanta); } - b_done = TRUE; } - } // while (!b_done) - } // end of else ... in state processing code + b_done = TRUE; + } + } +} - return NO_DELETE_FLAG; +// 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) @@ -2309,14 +2646,24 @@ void list_list_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode) } } +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 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2334,8 +2681,8 @@ BOOL run_sub(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) printf("[0x%X]\tSUB ", offset); offset++; U8 arg = safe_instruction_bytestream2byte(buffer, offset); - U8 arg1 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2352,8 +2699,8 @@ BOOL run_mul(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) printf("[0x%X]\tMUL ", offset); offset++; U8 arg = safe_instruction_bytestream2byte(buffer, offset); - U8 arg1 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2370,8 +2717,8 @@ BOOL run_div(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) printf("[0x%X]\tDIV ", offset); offset++; U8 arg = safe_instruction_bytestream2byte(buffer, offset); - U8 arg1 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2388,8 +2735,8 @@ BOOL run_mod(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) printf("[0x%X]\tMOD ", offset); offset++; U8 arg = safe_instruction_bytestream2byte(buffer, offset); - U8 arg1 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2407,8 +2754,8 @@ BOOL run_eq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) printf("[0x%X]\tEQ ", offset); offset++; U8 arg = safe_instruction_bytestream2byte(buffer, offset); - U8 arg1 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2425,8 +2772,8 @@ BOOL run_neq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) printf("[0x%X]\tNEQ ", offset); offset++; U8 arg = safe_instruction_bytestream2byte(buffer, offset); - U8 arg1 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2443,8 +2790,8 @@ BOOL run_leq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) printf("[0x%X]\tLEQ ", offset); offset++; U8 arg = safe_instruction_bytestream2byte(buffer, offset); - U8 arg1 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2461,8 +2808,8 @@ BOOL run_geq(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) printf("[0x%X]\tGEQ ", offset); offset++; U8 arg = safe_instruction_bytestream2byte(buffer, offset); - U8 arg1 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2479,8 +2826,8 @@ BOOL run_less(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) printf("[0x%X]\tLESS ", offset); offset++; U8 arg = safe_instruction_bytestream2byte(buffer, offset); - U8 arg1 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2497,8 +2844,8 @@ BOOL run_greater(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) printf("[0x%X]\tGREATER ", offset); offset++; U8 arg = safe_instruction_bytestream2byte(buffer, offset); - U8 arg1 = arg >> 4; - U8 arg2 = arg & 0xf; + U8 arg1 = safe_op_index(arg >> 4); + U8 arg2 = safe_op_index(arg & 0xf); if (b_print) { print_type(arg1); @@ -2640,13 +2987,12 @@ void quaternion_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode) } } - 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_instruction_bytestream2byte(buffer, offset); + U8 arg = safe_op_index(safe_instruction_bytestream2byte(buffer, offset)); if (b_print) { print_type(arg); @@ -2972,7 +3318,7 @@ BOOL run_state(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) { major_version = 2; } - + S32 current_state = get_register(buffer, LREG_CS); if (state != current_state) { @@ -3675,56 +4021,49 @@ BOOL run_print(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) } -void lscript_run(char *filename, BOOL b_debug) +void lscript_run(const std::string& filename, BOOL b_debug) { LLTimer timer; - if (filename == NULL) + + 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 } - else + LLFILE* file = LLFile::fopen(filename, "r"); /* Flawfinder: ignore */ + if(file) { - const char *error; - BOOL b_state; - LLScriptExecute *execute = NULL; - - LLFILE* file = LLFile::fopen(filename, "r"); - if (file) - { - execute = new LLScriptExecute(file); - // note: LLScriptExecute() closes file for us - } - file = LLFile::fopen(filename, "r"); - if (file) - { - LLFILE* fp = LLFile::fopen("lscript.parse", "w"); /*Flawfinder: ignore*/ - LLScriptLSOParse *parse = new LLScriptLSOParse(file); - parse->printData(fp); - delete parse; - fclose(file); - fclose(fp); - } - file = LLFile::fopen(filename, "r"); - if (file && execute) - { - timer.reset(); - while (!execute->run(b_debug, LLUUID::null, &error, b_state)) - ; - 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); - } + 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); } } @@ -3745,7 +4084,8 @@ void lscript_pop_variable(LLScriptLibData *data, U8 *buffer, char type) 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) @@ -3764,7 +4104,7 @@ void lscript_pop_variable(LLScriptLibData *data, U8 *buffer, char type) } lsa_decrease_ref_count(buffer, base_address); } - else + if (data->mKey == NULL) { data->mKey = new char[1]; data->mKey[0] = 0; @@ -3772,6 +4112,7 @@ void lscript_pop_variable(LLScriptLibData *data, U8 *buffer, char type) 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 @@ -3791,7 +4132,7 @@ void lscript_pop_variable(LLScriptLibData *data, U8 *buffer, char type) } lsa_decrease_ref_count(buffer, base_address); } - else + if (data->mString == NULL) { data->mString = new char[1]; data->mString[0] = 0; @@ -3890,19 +4231,16 @@ S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer) return 4; } -BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) + +// Shared code for run_calllib() and run_calllib_two_byte() +BOOL run_calllib_common(U8 *buffer, S32 &offset, const LLUUID &id, U16 arg) { - if (b_print) - printf("[0x%X]\tCALLLIB ", offset); - offset++; - U8 arg = safe_instruction_bytestream2byte(buffer, offset); - if (arg >= gScriptLibrary.mNextNumber) + if (arg >= 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); + LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg]; // pull out the arguments and the return values LLScriptLibData *arguments = NULL; @@ -3910,14 +4248,14 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) S32 i, number; - if (gScriptLibrary.mFunctions[arg]->mReturnType) + if (function.mReturnType) { returnvalue = new LLScriptLibData; } - if (gScriptLibrary.mFunctions[arg]->mArgs) + if (function.mArgs) { - number = (S32)strlen(gScriptLibrary.mFunctions[arg]->mArgs); /*Flawfinder: ignore*/ + number = (S32)strlen(function.mArgs); //Flawfinder: ignore arguments = new LLScriptLibData[number]; } else @@ -3927,24 +4265,18 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) for (i = number - 1; i >= 0; i--) { - lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg]->mArgs[i]); + lscript_pop_variable(&arguments[i], buffer, function.mArgs[i]); } - if (b_print) - { - printf("%s\n", gScriptLibrary.mFunctions[arg]->mDesc); - } + // Actually execute the function call + function.mExecFunc(returnvalue, arguments, id); - { - // 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); + add_register_fp(buffer, LREG_ESR, -(function.mEnergyUse)); + add_register_fp(buffer, LREG_SLR, function.mSleepTime); if (returnvalue) { - returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg]->mReturnType); + returnvalue->mType = char2type(*function.mReturnType); lscript_push_return_variable(returnvalue, buffer); } @@ -3961,72 +4293,32 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) } -BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) +BOOL run_calllib(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 >= gScriptLibrary.mNextNumber) + U16 arg = (U16) safe_instruction_bytestream2byte(buffer, offset); + if (b_print && + arg < 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("%s\n", gScriptLibrary.mFunctions[arg]->mDesc); - } - - { - // LLFastTimer time_in_libraries2(LLFastTimer::FTM_TEMP8); - gScriptLibrary.mFunctions[arg]->mExecFunc(returnvalue, arguments, id); + printf("[0x%X]\tCALLLIB ", offset); + LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg]; + printf("%d (%s)\n", (U32)arg, function.mName); + //printf("%s\n", function.mDesc); } - add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg]->mEnergyUse); - add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg]->mSleepTime); + return run_calllib_common(buffer, offset, id, arg); +} - if (returnvalue) +BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) +{ + offset++; + U16 arg = safe_instruction_bytestream2u16(buffer, offset); + if (b_print && + arg < gScriptLibrary.mFunctions.size()) { - returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg]->mReturnType); - lscript_push_return_variable(returnvalue, buffer); + printf("[0x%X]\tCALLLIB ", (offset-1)); + LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg]; + printf("%d (%s)\n", (U32)arg, function.mName); + //printf("%s\n", function.mDesc); } - - 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; + return run_calllib_common(buffer, offset, id, arg); } diff --git a/indra/lscript/lscript_execute/lscript_heapruntime.cpp b/indra/lscript/lscript_execute/lscript_heapruntime.cpp index 057db79f6f..749857753d 100644 --- a/indra/lscript/lscript_execute/lscript_heapruntime.cpp +++ b/indra/lscript/lscript_execute/lscript_heapruntime.cpp @@ -2,30 +2,25 @@ * @file lscript_heapruntime.cpp * @brief classes to manage script heap at runtime * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2007, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * 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://secondlife.com/developers/opensource/gplv2 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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://secondlife.com/developers/opensource/flossexception + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * 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. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/lscript/lscript_execute/lscript_heapruntime.h b/indra/lscript/lscript_execute/lscript_heapruntime.h index c4ade6cb62..0e924a2036 100644 --- a/indra/lscript/lscript_execute/lscript_heapruntime.h +++ b/indra/lscript/lscript_execute/lscript_heapruntime.h @@ -2,30 +2,25 @@ * @file lscript_heapruntime.h * @brief classes to manage script heap at runtime * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2007, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * 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://secondlife.com/developers/opensource/gplv2 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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://secondlife.com/developers/opensource/flossexception + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * 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. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ diff --git a/indra/lscript/lscript_execute/lscript_readlso.cpp b/indra/lscript/lscript_execute/lscript_readlso.cpp index 7f82926a3a..35caa41ae1 100644 --- a/indra/lscript/lscript_execute/lscript_readlso.cpp +++ b/indra/lscript/lscript_execute/lscript_readlso.cpp @@ -2,30 +2,25 @@ * @file lscript_readlso.cpp * @brief classes to read lso file * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2007, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * 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://secondlife.com/developers/opensource/gplv2 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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://secondlife.com/developers/opensource/flossexception + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * 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. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -38,7 +33,7 @@ LLScriptLSOParse::LLScriptLSOParse(LLFILE *fp) { U8 sizearray[4]; - S32 filesize; + size_t filesize; S32 pos = 0; if (fread(&sizearray, 1, 4, fp) != 4) { @@ -624,6 +619,16 @@ void LLScriptLSOParse::printStates(LLFILE *fp) bytestream2char(name, mRawData, event_offset, sizeof(name)); fprintf(fp, "\t\tstring %s\n", name); break; + case LSTT_HTTP_REQUEST: // LSTT_HTTP_REQUEST + bytestream2char(name, mRawData, event_offset, sizeof(name)); + fprintf(fp, "%s\n", name); + bytestream2char(name, mRawData, event_offset, sizeof(name)); + fprintf(fp, "\t\tkey %s\n", name); + bytestream2char(name, mRawData, event_offset, sizeof(name)); + fprintf(fp, "\t\tstring %s\n", name); + bytestream2char(name, mRawData, event_offset, sizeof(name)); + fprintf(fp, "\t\tstring %s\n", name); + break; default: break; } @@ -1568,7 +1573,7 @@ void print_calllib(LLFILE *fp, U8 *buffer, S32 &offset, S32 tabs) lso_print_tabs(fp, tabs); fprintf(fp, "[0x%X]\tCALLLIB ", offset++); arg = *(buffer + offset++); - fprintf(fp, "%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg]->mName); + fprintf(fp, "%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName); } @@ -1578,6 +1583,6 @@ void print_calllib_two_byte(LLFILE *fp, U8 *buffer, S32 &offset, S32 tabs) lso_print_tabs(fp, tabs); fprintf(fp, "[0x%X]\tCALLLIB_TWO_BYTE ", offset++); arg = bytestream2u16(buffer, offset); - fprintf(fp, "%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg]->mName); + fprintf(fp, "%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName); } diff --git a/indra/lscript/lscript_execute/lscript_readlso.h b/indra/lscript/lscript_execute/lscript_readlso.h index 7ed6622bdd..a545a9daf8 100644 --- a/indra/lscript/lscript_execute/lscript_readlso.h +++ b/indra/lscript/lscript_execute/lscript_readlso.h @@ -2,30 +2,25 @@ * @file lscript_readlso.h * @brief classes to read lso file * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2007, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * 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://secondlife.com/developers/opensource/gplv2 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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://secondlife.com/developers/opensource/flossexception + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * 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. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ |